Skip to content

Feature: Reverse Injection/External Sink #347

@iAnomaly

Description

@iAnomaly

Describe the solution you'd like
There are use cases where Secrets created in Kubernetes are desired to be injected (ejected?) back out to the backing external secret store (Secrets Manager, SSM Parameter Store, etc.) Examples might include certificates created by cert-manager, connection details for infrastructure created by Crossplane, etc.

What is the added value?
Essentially the same as ExternalSecrets but in the opposite direction: any Secret whose source of truth originates in Kubernetes that would be useful via external system or process that does not have access to Kubernetes directly (but does to the external secret store).

Give us examples of the outcome

Perhaps a new CRD of type SecretSink?

apiVersion: external-secrets.io/v1alpha1
kind: SecretSink
metadata:
  name: "hello-world"

  labels:
    acme.org/owned-by: "q-team"
  annotations:
    acme.org/sha: 1234

spec:

  # SecretStoreRef defines which SecretStore to use when ejecting the secret data to the external store
  secretStoreRef:
    name: secret-store-name
    kind: SecretStore  # or ClusterSecretStore

  # We shouldn't need refreshInterval as Kubernetes API supports event hooks that should be used for updating the external store any time the Kubernetes Secret is modified.
  # refreshInterval: "1h"

  # the target describes the secret that shall be created in the external store
  # there can only be one target per SecretSink
  target:

    # The secret name in the external store
    # It is immutable
    name: my-secret

    # Enum with values: 'Owner', 'Merge', or 'None'
    # Default value of 'Owner'
    # Owner creates the secret (and maybe uses tagging for ownership?); fails if secret already exits in the external store
    # Merge does not create the secret, but merges in the data fields to the secret following the overwritePolicy
    creationPolicy: 'Merge'

    # Enum with values: 'Allow', 'Never'
    # Default value of 'Never'
    # Never will not create or update/write to a secret that already exists in the external secret store.
    # Allow permits updating specific fields or the entire secret content if it already exists (be careful!)
    overwritePolicy: 'Never'

    # Specify a blueprint for the resulting external secret content
    template:
      # Use inline templates to construct your desired property that contains your Secret mapped contents
      data:
        config.yml: |
          endpoints:
          - https://{{ .data.user }}:{{ .data.password }}@api.exmaple.com

      # Uses an existing template from configmap
      # Secret is read, merged and templated within the referenced configMap data
      # It does not update the configmap, it creates a secret with: data["alertmanager.yml"] = ...result...
      templateFrom:
      - configMap:
          name: alertmanager
          items:
          - key: alertmanager.yaml

  # Data defines the connection between the Kubernetes Secret keys and the Provider data
  data:
    - secretKey: kubernetes-secret-key
      remoteRef:
        property: provider-key-property

  # Used to reference all keys from the Secret
  # If multiple dataFrom are specified, secrets are merged in the specified order
  dataFrom:
  - property: provider-key-property

status:
  # refreshTime is the time and date the external secret was fetched and
  # the target secret updated
  refreshTime: "2019-08-12T12:33:02Z"
  # Standard condition schema
  conditions:
  # SecretSink ready condition indicates the secret is ready for use.
  # This is defined as:
  # - The target external secret exists
  # - The target external secret has been refreshed since the K8s Secret's last modification
  # - The target external secret content is up-to-date based on any target templates
  - type: Ready
    status: "True" # False if last refresh was not successful
    reason: "SecretSynced"
    message: "Secret was synced"
    lastTransitionTime: "2019-08-12T12:33:02Z"

Observations (Constraints, Context, etc):

This CRD is just an initial suggestion, would love to hear feedback/improvements to that.

Another possible interface for mapping existing K8s Secrets to a SecretSink might be via annotations applied to those Secrets instead of explicit references within the SecretSink itself.

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind/featureCategorizes issue or PR as related to a new feature.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions