Sealed Secretsは数年前に試したことがあるが、もう一度試すメモ。
以前試したときの記事は以下。
コンポーネント | バージョン |
---|---|
EKS | 1.21 |
プラットフォームバージョン | eks.3 |
eksctl | 0.75.0 |
Sealed Secrets | v0.16.0 |
Sealed Secrets チャート | 1.16.1 |
クラスターの作成
1.21でクラスターを作成する。ノードなしで作成する。
CLUSTER_NAME="sealedsecrets" cat << EOF > cluster.yaml apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: ${CLUSTER_NAME} region: ap-northeast-1 version: "1.21" vpc: cidr: "10.0.0.0/16" availabilityZones: - ap-northeast-1a - ap-northeast-1c cloudWatch: clusterLogging: enableTypes: ["*"] iam: withOIDC: true EOF
eksctl create cluster -f cluster.yaml
ノードを作成する。
CLUSTER_NAME="sealedsecrets" cat << EOF > managed-ng-1.yaml apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: ${CLUSTER_NAME} region: ap-northeast-1 managedNodeGroups: - name: managed-ng-1 minSize: 2 maxSize: 10 desiredCapacity: 2 privateNetworking: true iam: attachPolicyARNs: - arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore EOF
eksctl create nodegroup -f managed-ng-1.yaml
Adminロールにも権限をつけておく。
CLUSTER_NAME="sealedsecrets" USER_NAME="Admin:{{SessionName}}" AWS_ACCOUNT_ID=$(aws sts get-caller-identity --output text --query Account) ROLE_ARN="arn:aws:iam::${AWS_ACCOUNT_ID}:role/Admin" eksctl create iamidentitymapping --cluster ${CLUSTER_NAME} --arn ${ROLE_ARN} --username ${USER_NAME} --group system:masters
Sealed Secretsのデプロイ
Helmチャートでインストールする。
helm repo add sealed-secrets https://bitnami-labs.github.io/sealed-secrets helm repo update
$ helm search repo sealed-secrets NAME CHART VERSION APP VERSION DESCRIPTION sealed-secrets/sealed-secrets 1.16.1 v0.16.0 Helm chart for the sealed-secrets controller. stable/sealed-secrets 1.12.2 0.13.1 DEPRECATED - A Helm chart for Sealed Secrets
$ helm inspect values sealed-secrets/sealed-secrets image: repository: quay.io/bitnami/sealed-secrets-controller tag: v0.16.0 pullPolicy: IfNotPresent pullSecret: "" resources: {} nodeSelector: {} tolerations: [] affinity: {} controller: # controller.create: `true` if Sealed Secrets controller should be created create: true # controller.labels: Extra labels to be added to controller deployment labels: {} # controller.service: Configuration options for controller service service: # controller.service.labels: Extra labels to be added to controller service labels: {} # namespace: Namespace to deploy the controller. namespace: "" serviceAccount: # serviceAccount.create: Whether to create a service account or not create: true # serviceAccount.labels: Extra labels to be added to service account labels: {} # serviceAccount.name: The name of the service account to create or use name: "" rbac: # rbac.create: `true` if rbac resources should be created create: true # rbac.labels: Extra labels to be added to rbac resources labels: {} pspEnabled: false # secretName: The name of the TLS secret containing the key used to encrypt secrets secretName: "sealed-secrets-key" ingress: enabled: false annotations: {} # kubernetes.io/ingress.class: nginx # kubernetes.io/tls-acme: "true" path: /v1/cert.pem hosts: - chart-example.local tls: [] # - secretName: chart-example-tls # hosts: # - chart-example.local crd: # crd.create: `true` if the crd resources should be created create: true # crd.keep: `true` if the sealed secret CRD should be kept when the chart is deleted keep: true networkPolicy: false securityContext: # securityContext.runAsUser defines under which user the operator Pod and its containers/processes run. runAsUser: 1001 # securityContext.fsGroup defines the filesystem group fsGroup: 65534 podAnnotations: {} podLabels: {} priorityClassName: "" serviceMonitor: # Enables ServiceMonitor creation for the Prometheus Operator create: false # How frequently Prometheus should scrape the ServiceMonitor interval: # Extra labels to apply to the sealed-secrets ServiceMonitor labels: # The namespace where the ServiceMonitor is deployed, defaults to the installation namespace namespace: # The timeout after which the scrape is ended scrapeTimeout: dashboards: # If enabled, sealed-secrets will create a configmap with a dashboard in json that's going to be picked up by grafana # See https://github.com/helm/charts/tree/master/stable/grafana#configuration - `sidecar.dashboards.enabled` create: false # Extra labels to apply to the dashboard configmaps labels: # The namespace where the dashboards are deployed, defaults to the installation namespace namespace:
デフォルトでインストールする。
$ helm upgrade -i sealed-secrets sealed-secrets/sealed-secrets -n kube-system Release "sealed-secrets" does not exist. Installing it now. NAME: sealed-secrets LAST DEPLOYED: Wed Dec 1 07:17:09 2021 NAMESPACE: kube-system STATUS: deployed REVISION: 1 TEST SUITE: None NOTES: You should now be able to create sealed secrets. 1. Install client-side tool into /usr/local/bin/ GOOS=$(go env GOOS) GOARCH=$(go env GOARCH) wget https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.16.0/kubeseal-$GOOS-$GOARCH sudo install -m 755 kubeseal-$GOOS-$GOARCH /usr/local/bin/kubeseal 2. Create a sealed secret file # note the use of `--dry-run` - this does not create a secret in your cluster kubectl create secret generic secret-name --dry-run --from-literal=foo=bar -o [json|yaml] | \ kubeseal \ --controller-name=sealed-secrets \ --controller-namespace=kube-system \ --format [json|yaml] > mysealedsecret.[json|yaml] The file mysealedsecret.[json|yaml] is a commitable file. If you would rather not need access to the cluster to generate the sealed secret you can run kubeseal \ --controller-name=sealed-secrets \ --controller-namespace=kube-system \ --fetch-cert > mycert.pem to retrieve the public cert used for encryption and store it locally. You can then run 'kubeseal --cert mycert.pem' instead to use the local cert e.g. kubectl create secret generic secret-name --dry-run --from-literal=foo=bar -o [json|yaml] | \ kubeseal \ --controller-name=sealed-secrets \ --controller-namespace=kube-system \ --format [json|yaml] --cert mycert.pem > mysealedsecret.[json|yaml] 3. Apply the sealed secret kubectl create -f mysealedsecret.[json|yaml] Running 'kubectl get secret secret-name -o [json|yaml]' will show the decrypted secret that was generated from the sealed secret. Both the SealedSecret and generated Secret must have the same name and namespace.
Podを確認する。
$ k get po -n kube-system NAME READY STATUS RESTARTS AGE aws-node-7ksm5 1/1 Running 0 30m aws-node-8b76r 1/1 Running 0 30m coredns-76f4967988-6jsh9 1/1 Running 0 45m coredns-76f4967988-dsqcl 1/1 Running 0 45m kube-proxy-6jv8f 1/1 Running 0 30m kube-proxy-zrv6n 1/1 Running 0 30m sealed-secrets-7569f57679-jjxwz 1/1 Running 0 3m
Secretを確認する。
$ k get secret -n kube-system --show-labels| grep sealed sealed-secrets-keyzkf9n kubernetes.io/tls 2 17m sealedsecrets.bitnami.com/sealed-secrets-key=active sealed-secrets-token-fflwb kubernetes.io/service-account-token 3 17m <none> sh.helm.release.v1.sealed-secrets.v1 helm.sh/release.v1 1 17m modifiedAt=1638310631,name=sealed-secrets,owner=helm,status=deployed,version=1
sealed-secrets-keyzkf9n
がSealing Keyで、30日毎に増えていくと思われる。
Deploymentをeditしてローテーション間隔を1hにする。
$ k -n kube-system edit deploy sealed-secrets spec: containers: - args: - --key-prefix - sealed-secrets-key - --key-renew-period=1h command: - controller
その後しばらくするとこのように鍵が増えた。
$ k get secret -n kube-system --show-labels| grep sealed sealed-secrets-keyww7cc kubernetes.io/tls 2 7m58s sealedsecrets.bitnami.com/sealed-secrets-key=active sealed-secrets-keyzkf9n kubernetes.io/tls 2 67m sealedsecrets.bitnami.com/sealed-secrets-key=active sealed-secrets-token-fflwb kubernetes.io/service-account-token 3 68m <none> sh.helm.release.v1.sealed-secrets.v1 helm.sh/release.v1 1 68m modifiedAt=1638310631,name=sealed-secrets,owner=helm,status=deployed,version=1
Sealed Secretsの作成
ローカルにyamlを作成する。
kubectl create secret generic secret-name --dry-run --from-literal=foo=bar -o yaml | \ kubeseal \ --controller-name=sealed-secrets \ --controller-namespace=kube-system \ --format yaml > mysealedsecret.yaml
これでこんなyamlができた。
apiVersion: bitnami.com/v1alpha1 kind: SealedSecret metadata: creationTimestamp: null name: secret-name namespace: default spec: encryptedData: foo: AgBYsvMwOApbU62E51gYMlKuu+l32NYl9BJkNA1mvBaxXBLs4DhKbARGaLQCdatZwOXEfCV62Ud9x3M+QSJ/j1JvQPuKV6EzNDjk5ksmFGVP8UrFZBT2xGE+FZKUlwyR1sxpS9aWOFS4J2tZx8gvHy4zTCZ4ROQDf0WkbPRKULMdyIzzGBGD7+TN9j7L5b7U32aL5J1pDGTGnDsWmDS1T/pNtNiNpdsG8h26XVsMXTAjyLoZ+ZTeeA432qvNKPbcmeYrxRWnQl6O4A5jmXNcw2APtlidzM9jRH5Msd0zfkCsywRxfBH5Eo0Yp6EaIxic8Op6W0ojpt/b4/HNo13+zJL/C+BCU6UUHMSRCSRtY983dI+AWzzx681wmE4AwvJRBC7uhoEhEEWxGY6zBCjBA6R+J3PdN9KNEnOLd0GRZcO0T+bXFTn1EDpPhXqre/uAnFdFsM4LvHhi43K5DbwVTal7gN6VloSU0z2xNk/qXbGUcBa5LeJPobYy+tz+D8pXpfB38/JqhKyZCRaZ6jPJiOkEr+PMqo3tn7oTELs8EkwRmvuAblP5SsnOM3xfRD87vSXJ0VnJ1AqeP2SfpHmX6UV1CYlbX5e+wW+2rzmyJckcm9/A1NaQmo8a5Fw/J90bAw0L+eMDB/Glmd8Mx3yGORjAbp771oYDb2ls5vHkLMRhvMY1xWeA0tdRFf4Zem+MIpnbxT0= template: data: null metadata: creationTimestamp: null name: secret-name namespace: default
これをapplyする。
$ k apply -f mysealedsecret.yaml sealedsecret.bitnami.com/secret-name created
確認する。
$ k get sealedsecret,secret NAME AGE sealedsecret.bitnami.com/secret-name 40s NAME TYPE DATA AGE secret/default-token-v5tmb kubernetes.io/service-account-token 3 55m secret/secret-name Opaque 1 40s
他のNamespaceだと復号されないことを確認する。Namespaceを作成する。
$ k create ns test namespace/test created
先ほどのyamlを編集してNamespaceだけ変える。
apiVersion: bitnami.com/v1alpha1 kind: SealedSecret metadata: creationTimestamp: null name: secret-name namespace: test spec: encryptedData: foo: AgBYsvMwOApbU62E51gYMlKuu+l32NYl9BJkNA1mvBaxXBLs4DhKbARGaLQCdatZwOXEfCV62Ud9x3M+QSJ/j1JvQPuKV6EzNDjk5ksmFGVP8UrFZBT2xGE+FZKUlwyR1sxpS9aWOFS4J2tZx8gvHy4zTCZ4ROQDf0WkbPRKULMdyIzzGBGD7+TN9j7L5b7U32aL5J1pDGTGnDsWmDS1T/pNtNiNpdsG8h26XVsMXTAjyLoZ+ZTeeA432qvNKPbcmeYrxRWnQl6O4A5jmXNcw2APtlidzM9jRH5Msd0zfkCsywRxfBH5Eo0Yp6EaIxic8Op6W0ojpt/b4/HNo13+zJL/C+BCU6UUHMSRCSRtY983dI+AWzzx681wmE4AwvJRBC7uhoEhEEWxGY6zBCjBA6R+J3PdN9KNEnOLd0GRZcO0T+bXFTn1EDpPhXqre/uAnFdFsM4LvHhi43K5DbwVTal7gN6VloSU0z2xNk/qXbGUcBa5LeJPobYy+tz+D8pXpfB38/JqhKyZCRaZ6jPJiOkEr+PMqo3tn7oTELs8EkwRmvuAblP5SsnOM3xfRD87vSXJ0VnJ1AqeP2SfpHmX6UV1CYlbX5e+wW+2rzmyJckcm9/A1NaQmo8a5Fw/J90bAw0L+eMDB/Glmd8Mx3yGORjAbp771oYDb2ls5vHkLMRhvMY1xWeA0tdRFf4Zem+MIpnbxT0= template: data: null metadata: creationTimestamp: null name: secret-name namespace: test
applyする。
$ k apply -f mysealedsecret-test.yaml sealedsecret.bitnami.com/secret-name created
この場合は復号されない。
$ k get sealedsecret,secret -n test NAME AGE sealedsecret.bitnami.com/secret-name 39s NAME TYPE DATA AGE secret/default-token-5tkzz kubernetes.io/service-account-token 3 2m53s