GitOps - Part 2
In the previous?post, we looked at how to use fluxv2 for deploying apps through helm and kustomization. In this we will take a brief look at how to secure your app secrets using Mozilla SOPS. There are many ways for securing the secrets and one of the ways was to use the secret store CSI driver which was covered in this post and the other popular way is to use sealed secrets for which details can be found here. These approaches come with a step of installing the extra component which acts as a controller for securing the secret.
We will look at Mozilla SOPS which provides the CLI to encrypt secrets with all the major cloud provider without having to install additional component and we will see the steps for using the same in Azure.
Create a variables which will be used for the scripts.
export?GITHUB_TOKEN=xxxxxx
export?RESOURCE_GROUP_NAME=gitopssops
export?LOCATION=southeastasia
export?CLUSTER_NAME=gitopssops
export?GITHUB_USER=girishgouda
export?GITHUB_REPO=githubsops
Creation of AKS cluster with managed identity enabled
az?group?create?-n?$RESOURCE_GROUP_NAME?-l?$LOCATION
az?aks?create?-g?$RESOURCE_GROUP_NAME?-n?$CLUSTER_NAME?--enable-managed-identity
az?aks?get-credentials?-g?$RESOURCE_GROUP_NAME?-n?$CLUSTER_NAME
kubectl?get?nodes
Install or bootstrap flux?in the cluster.
kubectl?create?ns?flux-system
flux?bootstrap?github?\
--owner=$GITHUB_USER?\
--repository=$GITHUB_REPO?\
--branch=master?\
--path=./clusters/$CLUSTER_NAME
Create a kustomization which will point to manifests folder to synchronize yaml files to Kubernetes. This will be used to have encrypted secret.
flux?create?kustomization?demoapp?\
??--namespace=flux-system?\
??--source=flux-system?\
??--path="./manifests"?\
??--prune=true?\
??--validation=client?\
??--interval=5m?\
??--export?>?./clusters/$CLUSTER_NAME/demoapp-kustomization.yaml
Create a manifests directory
mkdir?manifests
Create a namespace called demoapp where the secret will be created
cat?>?./manifests/namespace.yaml?<<EOF
---
apiVersion:?v1
kind:?Namespace
metadata:
??name:?demoapp
EOF
Install the AAD pod identity using helm in a namespace aad-pod-idnetity as shown below.
cat?>?./clusters/gitops/aad-pod-identity.yaml?<<EOF
---
apiVersion:?v1
kind:?Namespace
metadata:
??name:?aad-pod-identity
---
apiVersion:?source.toolkit.fluxcd.io/v1beta1
kind:?HelmRepository
metadata:
??name:?aad-pod-identity
??namespace:?aad-pod-identity
spec:
??url:?https://raw.githubusercontent.com/Azure/aad-pod-identity/master/charts
??interval:?10m
---
apiVersion:?helm.toolkit.fluxcd.io/v2beta1
kind:?HelmRelease
metadata:
??name:?aad-pod-identity
??namespace:?aad-pod-identity
spec:
??interval:?5m
??chart:
????spec:
??????chart:?aad-pod-identity
??????version:?4.0.0
??????sourceRef:
????????kind:?HelmRepository
????????name:?aad-pod-identity
????????namespace:?aad-pod-identity
??????interval:?1m
??values:
????nmi:
??????allowNetworkPluginKubenet:?true
EOF
Push the changes to git repo and verify that the aad-pod-identity and demoapp are created.
Create a azure key vault and create a key which will be used for encryption and decryption of secret
export?KEY_VAULT_NAME=gitopsazurevault
az?keyvault?create?--name?$KEY_VAULT_NAME?--resource-group?$RESOURCE_GROUP_NAME?--location?$LOCATION
az?keyvault?key?create?--name?sops-key?--vault-name?$KEY_VAULT_NAME?--protection?software?--ops?encrypt?decrypt
az?keyvault?set-policy?--name?$KEY_VAULT_NAME?--resource-group?$RESOURCE_GROUP_NAME?--object-id?$OBJECT_ID?--key-permissions?encrypt?decrypt
az?keyvault?key?show?--name?sops-key?--vault-name?$KEY_VAULT_NAME?--query?key.kid
The last command will provide a key "https://gitopsazurevault.vault.azure.net/keys/sops-key/xxxxx" which will be used for encryption and decryption.
Next, we need to tell kustomize controller to use the managed identity of the cluster to access the key for decryption.
First, we create a azureidentity with the details of the cluster manged identity and then bind the identity to selector called sops-aks-decryptor as shown.
领英推è
cat?>?./clusters/gitops/sops-identity.yaml?<<EOF
---
apiVersion:?aadpodidentity.k8s.io/v1
kind:?AzureIdentity
metadata:
??name:?sops-akv-decryptor
??namespace:?flux-system
spec:
??clientID:?xxxxxx #client id of the cluster managed identity
??resourceID:?/subscriptions/subId/resourcegroups/MC_gitopssops_gitopssops_southeastasia/providers/Microsoft.ManagedIdentity/userAssignedIdentities/gitopssops-agentpool
??type:?0?#?user-managed?identity
---
apiVersion:?aadpodidentity.k8s.io/v1
kind:?AzureIdentityBinding
metadata:
??name:?sops-akv-decryptor-binding
??namespace:?flux-system
spec:
??azureIdentity:?sops-akv-decryptor
??selector:?sops-akv-decryptor??#?kustomize-controller?label?will?match?this?name
EOF
Note: we need to specify the clientId of the managed identity which was created with the cluster creation and also the resourceId of the managed identity.
Next, we patch the kustoimze controller by modifying the kustomization.yaml to include patch yaml as shown below.
apiVersion:?kustomize.config.k8s.io/v1beta1
kind:?Kustomization
resources:
-?gotk-components.yaml
-?gotk-sync.yaml
patchesStrategicMerge:
-?sops-kustomize-patch.yaml
The patch file will tell the kustomize controller to use azure msi for authentication.
--
apiVersion:?apps/v1
kind:?Deployment
metadata:
??name:?kustomize-controller
??namespace:?flux-system
spec:
??template:
????metadata:
??????labels:
????????aadpodidbinding:?sops-akv-decryptor??#?match?the?AzureIdentityBinding?selector
????spec:
??????containers:
??????-?name:?manager
????????env:
????????-?name:?AZURE_AUTH_METHOD
??????????value:?msi-
Note: The same selector sops-aks-decryptor is used for aadpodidbinding
Finally, we need to tell kustomize-controller to use SOPS as decryption provider as shown below.
Install SOPS and create a SOPS conf file which will be used for encrypting the secret. The configuration file contains the details of path and the sections of the files to be encrypted using the key as shown below.
cat > .sops.yaml <<EOF
creation_rules:
- path_regex: .*.yaml
encrypted_regex: ^(data|stringData)$
azure_keyvault: https://gitopsdemokeyvault.vault.azure.net/keys/sops-key/xxxxxx
EOF
Create a temporary secret file which will not be pushed to git.
cat > ./secret.yaml <<EOF
---
apiVersion: v1
kind: Secret
metadata:
name: demoapp-credentials
namespace: demoapp
type: Opaque
stringData:
username: admin
password: password
EOF
Note : SOPS CLI will use the logged in user in AZ CLI and hence make sure the logged in user has "encrypt" and "decrypt" key permissions.
Encrypt the secret.yam file as shown below.
sops --encrypt secret.yaml > ./manifests/secret.enc.yaml
The encrypted file will be as shown below.
apiVersion:?v1
kind:?Secret
metadata:
????name:?demoapp-credentials
????namespace:?demoapp
type:?Opaque
stringData:
????username:?ENC[AES256_GCM,data:BYkU34g=,iv:DMTnv3Ucd5xSGHGbEIBIeypKydHwxTnYl3enK0nKdjw=,tag:vagn0DVSfjOSaDGVRfLdMg==,type:str]
????password:?ENC[AES256_GCM,data:Fey4wZyIvB4Jvg==,iv:gFtSzrtuC5MfC9OVkPNIYZ4MiYGX9Xsy81fZPUsZzIM=,tag:GW4hSN9U+YcYYwytCZKHZQ==,type:str]
sops:
????kms:?[]
????gcp_kms:?[]
????azure_kv:
????????-?vault_url:?https://gitopsazurevault.vault.azure.net
??????????name:?sops-key
??????????version:?xxxxxxxxx
??????????created_at:?"2021-09-14T05:25:57Z"
??????????enc:?ODebW_-5BhT2LdEzWrC9NFxA4A6INoTEVesUmT_9ECA0hKb4-nSEj-QDcHigjJZpGh3qUm6jZSGbjQpcPdE8eHYLlpmgb8sU4nDn3P8_Gm9KBB1txSg3fDTgEl0HEs6Re3zu7VQo0gVTbnZN-qyLRZbVvqN6NnK7npWB2SXLJNDucHiqDqBDluJxkKhM0ngTh2qvPp7MzQZ1L9A9P0tLYrE8btBJYLzGUKRFc_pbfTPMPxtoei00TShWjFhtO3WNQ9tzqJz0Ajy7ITn5ntu2YDpbE9jqsAe3k6yqeKRIZ8TbHPHm329dNhlUiQFujpVVy-ypUkyg
????hc_vault:?[]
????age:?[]
????lastmodified:?"2021-09-14T05:26:00Z"
????mac:?ENC[AES256_GCM,data:P/54bG7GUxilkhJ2gbHlW2jUA9wcL7a8Wp4cyupyaOHdyB9hRtWYkFsnBblQLi7t5QMe7XJEOisZR45l1HOHZVgvZUg5ghI/4xLmc0eC/krkqv5CNeH5JyAEuq3yr9o/nLy0+EjgNIrc7tLl2Xo8Qn3VdR1KytWgLXpK0FORwcE=,iv:1FylnUvw3RBn/mR+ZhBwukIh+TbBxvD6irsoYUTRVCE=,tag:KI3qIxwyJWKAkkX9lctG4w==,type:str]
????pgp:?[]
????encrypted_regex:?^(data|stringData)$
????version:?3.7.1
We can now remove the secret.yaml and push the secret.enc.yaml to git
We can finally verify the sceret being created by using the folowing command
kubectl describe secret -n demoapp demoapp-credentials
This is how we can use sops in Fluxv2 to safely push the secrets to git. In the future articles, we will look at some more interesting features.
Also, if you're a visual learner, you can check out "The Power of GItOps" YouTube playlist here (where Flux Maintainers and Contributors walk you through Flux guides for various topics): https://youtube.com/playlist?list=PL9lTuCFNLaD3fI_g-NXWVxopnJ0adn65d Flux on Azure: https://youtu.be/K6OQ93UNSB8 Managing Kubernetes Secrets with Mozilla SOPS & Flux: https://youtu.be/8pbdXAd-F44