项目作者: contentful-labs

项目描述 :
A Kubernetes operator to sync secrets from AWS Secrets Manager
高级语言: Go
项目地址: git://github.com/contentful-labs/kube-secret-syncer.git
创建时间: 2020-03-15T21:18:51Z
项目社区:https://github.com/contentful-labs/kube-secret-syncer

开源协议:Apache License 2.0

下载


Kube-secret-syncer

Kube-secret-syncer is a Kubernetes operator developed
using the Kubebuilder framework that keeps the values of Kubernetes
Secrets synchronised to secrets in AWS Secrets Manager.

This mapping is described in a Kubernetes custom resource called SyncedSecret. The operator polls AWS for changes in
secret values at regular intervals, and upon detecting changes, updates the Kubernetes Secrets.

WARNING: updating the value of a secret in AWS SecretsManager will override secrets in Kubernetes, therefore
can be a destructive action.

Comparison to existing projects

Kube-secret-syncer is similar to other projects such as:

Kube-secret-syncer improves on this approach:

  • uses caching to only retrieve the value of secrets when they have changed, substantially reducing
    costs when syncing a large number of secrets.
  • enables sophisticated access control to secrets in AWS SecretsManager using IAM roles - see our
    security model
  • supports templated fields for Kubernetes secrets - enabling the use of values from multiple AWS
    SecretsManager secrets in one Kubernetes Secret

Defining mapping between an AWS SecretsManager secret and a Kubernetes Secret

The following resource will map the AWS Secret secretsyncer/secret/sample to the Kubernetes Secret
demo-service-secret, and copy all key-value pairs from the AWS SecretsManager secret to the Kubernetes secret For
this example, the AWS SecretsManager secret needs to be a valid JSON consisting only of key-value pairs.

To access the secrets, kube-secret-syncer will assume the role iam_role to poll the secret. Note: that role must be
assumed by the Kubernetes cluster/node where the operator runs, eg part of the kube2iam annotation on the namespace.

  1. apiVersion: secrets.contentful.com/v1
  2. kind: SyncedSecret
  3. metadata:
  4. name: demo-service-secret
  5. namespace: kube-secret-syncer
  6. spec:
  7. IAMRole: iam_role
  8. dataFrom:
  9. secretRef:
  10. name: secretsyncer/secret/sample

If you only need to retrieve select keys in a single AWS secret, or multiple keys from different AWS secrets, you
can use the following syntax:

  1. apiVersion: secrets.contentful.com/v1
  2. kind: SyncedSecret
  3. metadata:
  4. name: demo-service-secret
  5. namespace: kube-secret-syncer
  6. spec:
  7. IAMRole: iam_role
  8. data:
  9. # Sets the key mysql_user for the Kubernetes Secret "demo-service-secret" to "contentful"
  10. - name: mysql_user
  11. value: "contentful"
  12. # Takes the value for key "password" from the Secrets Manager secret "mysql", assign to the
  13. # key "mysql_pw" of the Kubernetes secret "demo-service-secret"
  14. - name: mysql_pw
  15. valueFrom:
  16. secretKeyRef:
  17. name: mysql
  18. key: password
  19. - name: datadog_access_key
  20. valueFrom:
  21. secretKeyRef:
  22. name: datadog
  23. key: access_key

You can also chose to store non-JSON values in AWS Secret Manager, which might be more convenient for data such
as certificates.

  1. apiVersion: secrets.contentful.com/v1
  2. kind: SyncedSecret
  3. metadata:
  4. name: demo-service-secret
  5. namespace: kube-secret-syncer
  6. spec:
  7. IAMRole: iam_role
  8. data:
  9. # Sets the key ssl-certificate for the Kubernetes Secret "demo-service-secret"
  10. # to the value of the secret "apache/ssl-cert"
  11. - name: ssl-certificate
  12. valueFrom:
  13. secretRef:
  14. name: apache/ssl-cert

Templated fields

Kube-secret-syncer supports templated fields. This allows, for example, to iterate over a list of secrets that
share the same tag, to output a configuration file, such as in the following example:

  1. apiVersion: secrets.contentful.com/v1
  2. kind: SyncedSecret
  3. metadata:
  4. name: pgbouncer.txt
  5. namespace: kube-secret-syncer
  6. spec:
  7. IAMRole: iam_role
  8. data:
  9. - name: pgbouncer-hosts
  10. valueFrom:
  11. template: |
  12. {{- $cfg := "" -}}
  13. {{- range $secretID, $_ := filterByTagKey .Secrets "tag1" -}}
  14. {{- $secretValue := getSecretValueMap $secretID -}}
  15. {{- $cfg = printf "%shost=%s user=%s password=%s\n" $cfg $secretValue.host $secretValue.user $secretValue.password -}}
  16. {{- end -}}
  17. {{- $cfg -}}

This iterates over all secrets kube-secret-syncer has access to, select those that have the tag “tag1” set,
and for each of these, add a configuration line to $cfg. $cfg is then assigned to the key “pgbouncer-hosts” of
the Kubernetes secret pgbouncer.txt.

The template is a Go template with the following elements defined:

  • .Secrets - a map containing all listed secrets (without their value)
  • filterByTagKey - a helper function to filter the secrets by tag
  • getSecretValue - will retrieve the raw value of a Secret in SecretsManager, given its secret ID
  • getSecretValueMap - will retrieve the value of a Secret in SecretsManager that contains a JSON, given its secret ID -
    as a map

Caching

Kube-secret-syncer maintains both the list of AWS Secrets as well as their values in cache. The list is updated every
POLL_INTERVAL_SEC, and values are retrieved whenever their VersionID changed.

Security model

By default, kube-secret-syncer will use the Kubernetes node’s IAM role to list and retrieve the secrets. However, when
synced secrets have an IAMRole field defined, kube-secret-syncer will assume that role before retrieving the secret. This
implies that the role specified by IAMRole can be assumed by the role of the Kubernetes node kube-secret-syncer runs on.

To ensure a specific namespace only has access to the secrets it needs to, kube-secret-syncer will use the
“iam.amazonaws.com/allowed-roles” annotation on the namespace (originally used by kube2iam) to validate that this
role can be assumed for that namespace.

The secret synchronisation will be allowed if:

  • the annotation is set on the namespace and contains the secrets IAMRole
  • no annotation is set on the namespace and the secret has a IAMRole set
  • no annotation is set on the namespace and the secret has no IAMRole set

The secret sync will be denied if:

  • the annotation is set on the namespace and does not contains the secrets IAMRole
  • the annotation is set on the namespace and the secret has no IAMRole set

Configuration

Kube-secret-syncer supports the following environment variables:

  • POLL_INTERVAL_SEC: how often the list of secrets in cache is refreshed (default: 300)
  • SYNC_INTERVAL_SEC: how often we will write to a Kubernetes secret (default: 120)
  • NS_ANNOTATION: the annotation on the namespace that contains a list of IAM roles kube-secret-syncer is allowed
    to assume (default: iam.amazonaws.com/allowed-roles)
  • METRICS_LISTEN: what interface/port the metrics server shoult listen on (default: :8080)

Note - when a secret in Secrets Manager is updated, the secret in Kubernetes will not be updated
until both the list of secrets is refreshed AND the sync_interval expires - therefore it might take up
to POLL_INTERVAL_SEC + SYNC_INTERVAL_SEC.

Local development

Please refer to the local development documentation.

Examples

See sample configurations and deployment example.