Skip to content

Commit ae99f5b

Browse files
[Feature][Add] Added support for azure key vault (#12)
* Added support for azure key vault Signed-off-by: iamabhishek-dubey <abhishekbhardwaj510@gmail.com> * Updated architecture diagram Signed-off-by: iamabhishek-dubey <abhishekbhardwaj510@gmail.com> * Updated docs for Azure Support Signed-off-by: iamabhishek-dubey <abhishekbhardwaj510@gmail.com>
1 parent ca92aa7 commit ae99f5b

24 files changed

+245
-24
lines changed

CHANGELOG.md

+9
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
### v3.0
2+
##### May 9, 2021
3+
4+
#### :tada: [Features Added]
5+
6+
- Added Azure Key Vault support
7+
- Fetch secrets from Azure Key Vault and inject them in pods/containers
8+
- Pod AD identity and Service principal based authentication in Azure
9+
110
### v2.0
211
##### May 8, 2021
312

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
REGISTRY ?= quay.io
33
REPOSITORY ?= $(REGISTRY)/opstree
44
ARTIFACT_NAME=k8s-vault-webhook
5-
VERSION = 2.0
5+
VERSION = 3.0
66

77
all: build-code build-image
88

README.md

+5-10
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@ The secret managers which are currently supported:-
3232

3333
- **[Hashicorp Vault](https://www.vaultproject.io/)**
3434
- **[AWS Secret Manager](https://aws.amazon.com/secrets-manager/)**
35+
- **[Azure Key Vault](https://azure.microsoft.com/en-in/services/key-vault/)**
3536

3637
There are some secret managers which are planned to be implemented in future.
3738

38-
- **[Azure Key Vault](https://azure.microsoft.com/en-in/services/key-vault/)**
3939
- **[GCP Secret Manager](https://cloud.google.com/secret-manager)**
4040

4141
### Supported Features
@@ -45,21 +45,16 @@ There are some secret managers which are planned to be implemented in future.
4545
- Inject secret directly to pods/containers running inside Kubernetes
4646
- Inject secret directly to pods/containers from AWS Secret Manager
4747
- Authentication with AWS Secret Manager with access key and iam role
48+
- Fetch secrets from Azure Key Vault and inject them in pods/containers
49+
- Pod AD identity and Service principal based authentication in Azure
50+
- Authentication with AWS Secret Manager with access key and iam role
4851
- Support regex to inject all secrets from a certain path of Vault
4952
- Inject secrets directly to the process of container, i.e. after the injection you cannot read secrets from the environment variable
5053

5154
### Architecture
5255

53-
#### Hashicorp Vault
54-
55-
<div align="center">
56-
<img src="./static/k8s-vault-webhook-arc-vault.png">
57-
</div>
58-
59-
#### AWS Secret Manager
60-
6156
<div align="center">
62-
<img src="./static/k8s-vault-webhook-arc-aws.png">
57+
<img src="./static/k8s-vault-webhook-arc.png">
6358
</div>
6459

6560
### Installation

annotations.go

+6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
package main
22

33
const (
4+
// AnnotationAzureKeyVaultEnabled if enabled it will use Azure Key Vault
5+
AnnotationAzureKeyVaultEnabled = "azure.opstree.secret.manager/enabled"
6+
7+
// AnnotationAzureKeyVaultName azure key vault name
8+
AnnotationAzureKeyVaultName = "azure.opstree.secret.manager/vault-name"
9+
410
// AnnotationAWSSecretManagerEnabled if enabled it will use AWS secret manager
511
AnnotationAWSSecretManagerEnabled = "aws.opstree.secret.manager/enabled"
612

azure.go

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
6+
corev1 "k8s.io/api/core/v1"
7+
)
8+
9+
type azure struct {
10+
config struct {
11+
enabled bool
12+
azureKeyVaultName string
13+
}
14+
}
15+
16+
func (azure *azure) mutateContainer(container corev1.Container) corev1.Container {
17+
container = azure.setArgs(container)
18+
return container
19+
}
20+
21+
func (azure *azure) setArgs(c corev1.Container) corev1.Container {
22+
args := []string{"azure"}
23+
args = append(args, fmt.Sprintf("--azure-vault-name=%s", azure.config.azureKeyVaultName))
24+
25+
args = append(args, "--")
26+
c.Args = append(args, c.Args...)
27+
return c
28+
}

docs/src/.vuepress/config.js

+2
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ module.exports = {
7070
children: [
7171
'hashicorp-vault',
7272
'aws-secret-manager',
73+
'azure-integration',
7374
]
7475
},
7576
{
@@ -78,6 +79,7 @@ module.exports = {
7879
children: [
7980
'hashicorp-vault-example',
8081
'aws-secret-manager-example',
82+
'azure-examples',
8183
]
8284
},
8385
{

docs/src/guide/README.md

+1-9
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,6 @@ There are some secret managers which are planned to be implemented in future.
3131

3232
## Architecture
3333

34-
### Hashicorp Vault
35-
36-
<div align="center" style="padding-top: 25px;">
37-
<img src="./images/k8s-vault-webhook-arc-vault.png">
38-
</div>
39-
40-
### AWS Secret Manager
41-
4234
<div align="center" style="padding-top: 25px;">
43-
<img src="./images/k8s-vault-webhook-arc-aws.png">
35+
<img src="./images/k8s-vault-webhook-arc.png">
4436
</div>

docs/src/guide/annotations.md

+8-1
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ The annotations which are currently supported:-
77

88
- **[Hashicorp Vault](https://www.vaultproject.io/)**
99
- **[AWS Secret Manager](https://aws.amazon.com/secrets-manager/)**
10+
- **[Azure Key Vault](https://azure.microsoft.com/en-in/services/key-vault/)**
1011

1112
There are some other annotations which are planned to be implemented in future.
1213

13-
- **[Azure Key Vault](https://azure.microsoft.com/en-in/services/key-vault/)**
1414
- **[GCP Secret Manager](https://cloud.google.com/secret-manager)**
1515

1616
## Vault Annotations
@@ -39,3 +39,10 @@ The available annotations for k8s vault webhook are:-
3939
|`aws.secret.manager/role-arn`| AWS IAM Role to access the secret | no | |
4040
|`aws.secret.manager/secret-name`| Name of the AWS secret | no | |
4141
|`aws.secret.manager/previous-version`| If the secret is rotated, set to "true" | no | |
42+
43+
## Azure Annotations
44+
45+
|**Name**|**Description**|**Required**|**Default**|
46+
|--------|---------------|------------|-----------|
47+
|`azure.secret.manager/enabled`| Enable the Azure Key Vault | - | false |
48+
|`azure.secret.manager/vault-name`| Name of the Azure Key Vault in which secrets are held | no | test-secret |

docs/src/guide/azure-examples.md

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# Azure Key Vault
2+
3+
Let's try to create a deployment to inject secrets directly from Azure Key Vault. For example, purpose we are taking mysql as deployment and then we will try to set mysql root password using k8s-vault-webhook.
4+
5+
We can use our [example](https://github.com/OT-CONTAINER-KIT/k8s-vault-webhook/tree/master/example) folder.
6+
7+
The environment variables will get substitute automatically, we just have to provide some custom annotations.
8+
9+
```yaml
10+
template:
11+
metadata:
12+
labels:
13+
app: k8s-azure-mysql
14+
tier: mysql
15+
# Use Azure App Pod Pinding if cluster is configured in Azure
16+
# aadpodidbinding: POD_IDENTITY_NAME
17+
annotations:
18+
azure.opstree.secret.manager/enabled: "true"
19+
azure.opstree.secret.manager/vault-name: "vault-k8s-secret"
20+
spec:
21+
containers:
22+
- image: opstree/mysql:latest
23+
name: mysql
24+
# If running outside Azure
25+
env:
26+
- name: AZURE_CLIENT_SECRET
27+
valueFrom:
28+
secretKeyRef:
29+
name: azure-secret
30+
key: AZURE_CLIENT_SECRET
31+
- name: AZURE_CLIENT_ID
32+
valueFrom:
33+
secretKeyRef:
34+
name: azure-secret
35+
key: AZURE_CLIENT_ID
36+
- name: AZURE_TENANT_ID
37+
valueFrom:
38+
secretKeyRef:
39+
name: azure-secret
40+
key: AZURE_TENANT_ID
41+
```
42+
43+
Let's try to apply the deployment manifest.
44+
45+
```shell
46+
$ kubectl apply -f example/azure-mysql-example.yaml
47+
...
48+
deployment.apps/k8s-azure-mysql configured
49+
```
50+
51+
Verify the mysql pods are running or not by using `kubectl` command line.
52+
53+
```shell
54+
$ kubectl get pods
55+
...
56+
NAME READY STATUS RESTARTS AGE
57+
k8s-azure-mysql-658b99f8dc-k9r58 1/1 Running 0 128m
58+
```
59+
60+
Now let's try to get inside the `mysql` pod and see if the Azure Key Vault's password is working fine or not.
61+
62+
```shell
63+
$ kubectl exec -it k8s-azure-mysql-658b99f8dc-k9r58 \
64+
-- mysql -u root -pazurepassword -e "show databases;"
65+
...
66+
Warning: Using a password on the command line interface can be insecure.
67+
+--------------------+
68+
| Database |
69+
+--------------------+
70+
| information_schema |
71+
| mysql |
72+
| performance_schema |
73+
+--------------------+
74+
```
75+
76+
Also, try to check the value in environment variable of MySQL pod.
77+
78+
```shell
79+
$ kubectl exec -it k8s-azure-mysql-658b99f8dc-k9r58 \
80+
-- env | grep ROOT
81+
...
82+
No output
83+
```

docs/src/guide/azure-integration.md

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Azure Key Vault
2+
3+
For integrating AWS Secret Manager with the K8s Vault Webhook, first we need to setup Azure Key Vault inside Azure account.
4+
5+
Here we will talk about the integration of Azure Key Vault inside Kubernetes.
6+
7+
Login into the [Azure Portal](http://portal.azure.com/#home) and select [Azure Key Vault](https://azure.microsoft.com/en-in/services/key-vault/) service.
8+
9+
![](./images/azure-key-vault-azure.png)
10+
11+
Create a secret in Settings > Secrets and click on `Generate/Import` ans specify these details for testing.
12+
13+
|**Key**|**Value**|
14+
|-------|---------|
15+
| mysql-root-password | azurepassword |
16+
17+
![](./images/azure-key-vault-secrets.png)
18+
19+
Once the details has been provided, create the secret.
20+
21+
![](./images/azure-key-vault-name.png)
22+
23+
**Since Azure Key Vault doesn't supports underscore `_`, we will use hyphen `-`. The k8s-vault-webhook will automatically replace the hyphen with underscore.**

docs/src/guide/changelog.md

+9
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
### v3.0
2+
**May 9, 2021**
3+
4+
**:tada: [Features Added]**
5+
6+
- Added Azure Key Vault support
7+
- Fetch secrets from Azure Key Vault and inject them in pods/containers
8+
- Pod AD identity and Service principal based authentication in Azure
9+
110
### v2.0
211
**May 8, 2021**
312

23.6 KB
Loading
32.9 KB
Loading
Loading
Loading
Loading
Loading

example/azure-mysql-example.yaml

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
---
2+
apiVersion: apps/v1
3+
kind: Deployment
4+
metadata:
5+
name: k8s-azure-mysql
6+
labels:
7+
app: k8s-azure-mysql
8+
spec:
9+
selector:
10+
matchLabels:
11+
app: k8s-azure-mysql
12+
tier: mysql
13+
strategy:
14+
type: Recreate
15+
template:
16+
metadata:
17+
labels:
18+
app: k8s-azure-mysql
19+
tier: mysql
20+
# Use Azure App Pod Pinding if cluster is configured in Azure
21+
# aadpodidbinding: POD_IDENTITY_NAME
22+
annotations:
23+
azure.opstree.secret.manager/enabled: "true"
24+
azure.opstree.secret.manager/vault-name: "vault-k8s-secret"
25+
spec:
26+
containers:
27+
- image: opstree/mysql:latest
28+
name: mysql
29+
# If running outside Azure
30+
env:
31+
- name: AZURE_CLIENT_SECRET
32+
valueFrom:
33+
secretKeyRef:
34+
name: azure-secret
35+
key: AZURE_CLIENT_SECRET
36+
- name: AZURE_CLIENT_ID
37+
valueFrom:
38+
secretKeyRef:
39+
name: azure-secret
40+
key: AZURE_CLIENT_ID
41+
- name: AZURE_TENANT_ID
42+
valueFrom:
43+
secretKeyRef:
44+
name: azure-secret
45+
key: AZURE_TENANT_ID
46+
ports:
47+
- containerPort: 3306
48+
name: mysql

main.go

+19-1
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,11 @@ func (mw *mutatingWebhook) mutateContainers(containers []corev1.Container, podSp
248248
container.Command = []string{"/k8s-secret/k8s-secret-injector"}
249249
container.Args = args
250250

251+
if secretManagerConfig.azure.config.enabled {
252+
container = secretManagerConfig.azure.mutateContainer(container)
253+
mutationInProgress = true
254+
}
255+
251256
if secretManagerConfig.aws.config.enabled {
252257
container = secretManagerConfig.aws.mutateContainer(container)
253258
mutationInProgress = true
@@ -341,6 +346,9 @@ func (mw *mutatingWebhook) parseSecretManagerConfig(obj metav1.Object) secretMan
341346
var smCfg secretManagerConfig
342347
annotations := obj.GetAnnotations()
343348

349+
smCfg.azure.config.enabled, _ = strconv.ParseBool(annotations[AnnotationAzureKeyVaultEnabled])
350+
smCfg.azure.config.azureKeyVaultName = annotations[AnnotationAzureKeyVaultName]
351+
344352
smCfg.aws.config.enabled, _ = strconv.ParseBool(annotations[AnnotationAWSSecretManagerEnabled])
345353
smCfg.aws.config.region = annotations[AnnotationAWSSecretManagerRegion]
346354
smCfg.aws.config.roleARN = annotations[AnnotationAWSSecretManagerRoleARN]
@@ -380,6 +388,16 @@ func (mw *mutatingWebhook) SecretsMutator(ctx context.Context, obj metav1.Object
380388

381389
switch v := obj.(type) {
382390
case *corev1.Pod:
391+
if smCfg.azure.config.enabled {
392+
mw.logger.Infof("Using Azure Key Vault")
393+
394+
if smCfg.azure.config.azureKeyVaultName == "" {
395+
return true, fmt.Errorf("Error getting azure key vault - make sure you set the annotation %s on the Pod", AnnotationAzureKeyVaultName)
396+
}
397+
398+
return false, mw.mutatePod(v, smCfg, whcontext.GetAdmissionRequest(ctx).Namespace, whcontext.IsAdmissionRequestDryRun(ctx))
399+
}
400+
383401
if smCfg.aws.config.enabled {
384402
mw.logger.Infof("Using AWS Secret Manager")
385403

@@ -461,7 +479,7 @@ func newK8SClient() (kubernetes.Interface, error) {
461479
}
462480

463481
func init() {
464-
viper.SetDefault("k8s_secret_injector_image", "quay.io/opstree/k8s-secret-injector:2.0")
482+
viper.SetDefault("k8s_secret_injector_image", "quay.io/opstree/k8s-secret-injector:3.0")
465483
viper.SetDefault("k8s_secret_injector_image_pull_policy", string(corev1.PullIfNotPresent))
466484
viper.SetDefault("k8s_secret_injector_image_pull_secret_name", "")
467485
viper.SetDefault("tls_cert_file", "")

static/k8s-vault-webhook-arc-aws.png

1.44 KB
Loading
352 KB
Loading

static/k8s-vault-webhook-arc.png

451 KB
Loading

types.go

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
type secretManagerConfig struct {
1010
vault
1111
aws
12+
azure
1213
// explicitSecrets bool // only get secrets that match the prefix `secret:`
1314
}
1415

version/version.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package version
22

3-
// version is a private field and should be set when compiling with --ldflags="-X github.com/innovia/secrets-consumer-env/pkg/version.version=X.Y.Z"
4-
var version = "1.0"
3+
// version is a private field
4+
var version = "3.0"
55

66
// GetVersion returns the current version
77
func GetVersion() string {

0 commit comments

Comments
 (0)