Skip to content

AWS Parameter Store

aws sm

Parameter Store

A ParameterStore points to AWS SSM Parameter Store in a certain account within a defined region. You should define Roles that define fine-grained access to individual secrets and pass them to ESO using spec.provider.aws.role. This way users of the SecretStore can only access the secrets necessary.

apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: parameterstore
spec:
  provider:
    aws:
      service: ParameterStore
      # define a specific role to limit access
      # to certain secrets
      role: arn:aws:iam::123456789012:role/external-secrets
      region: eu-central-1
      auth:
        secretRef:
          accessKeyIDSecretRef:
            name: awssm-secret
            key: access-key
          secretAccessKeySecretRef:
            name: awssm-secret
            key: secret-access-key

NOTE: In case of a ClusterSecretStore, Be sure to provide namespace in accessKeyIDSecretRef and secretAccessKeySecretRef with the namespaces where the secrets reside.

API Pricing & Throttling

The SSM Parameter Store API is charged by throughput and is available in different tiers, see pricing. Please estimate your costs before using ESO. Cost depends on the RefreshInterval of your ExternalSecrets.

IAM Policy

Fetching Parameters

The example policy below shows the minimum required permissions for fetching SSM parameters. This policy permits pinning down access to secrets with a path matching dev-*. Other operations may require additional permission. For example, finding parameters based on tags will also require ssm:DescribeParameters and tag:GetResources permission with "Resource": "*". Generally, the specific permission required will be logged as an error if an operation fails.

For further information see AWS Documentation.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ssm:GetParameter*",
      ],
      "Resource": "arn:aws:ssm:us-east-2:1234567889911:parameter/dev-*"
    }
  ]
}

Pushing Parameters

The example policy below shows the minimum required permissions for pushing SSM parameters. Like with the fetching policy it restricts the path in which it can push secrets too.

{
    "Action": [
        "ssm:GetParameter*",
        "ssm:PutParameter*",
        "ssm:AddTagsToResource",
        "ssm:ListTagsForResource"
    ],
    "Effect": "Allow",
    "Resource": "arn:aws:ssm:us-east-2:1234567889911:parameter/dev-*"
}

JSON Secret Values

You can store JSON objects in a parameter. You can access nested values or arrays using gjson syntax:

Consider the following JSON object that is stored in the Parameter Store key friendslist:

{
  "name": {"first": "Tom", "last": "Anderson"},
  "friends": [
    {"first": "Dale", "last": "Murphy"},
    {"first": "Roger", "last": "Craig"},
    {"first": "Jane", "last": "Murphy"}
  ]
}

This is an example on how you would look up nested keys in the above json object:

apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: extract-data
spec:
  # [omitted for brevity]
  data:
  - secretKey: my_name
    remoteRef:
      key: friendslist
      property: name.first # Tom
  - secretKey: first_friend
    remoteRef:
      key: friendslist
      property: friends.1.first # Roger

  # metadataPolicy to fetch all the tags in JSON format
  - secretKey: tags
    remoteRef:
      metadataPolicy: Fetch
      key: database-credentials

  # metadataPolicy to fetch a specific tag (dev) from the source secret
  - secretKey: developer
    remoteRef:
      metadataPolicy: Fetch
      key: database-credentials
      property: dev

Parameter Versions

ParameterStore creates a new version of a parameter every time it is updated with a new value. The parameter can be referenced via the version property

SetSecret

The SetSecret method for the Parameter Store allows the user to set the value stored within the Kubernetes cluster to the remote AWS Parameter Store.

Creating a Push Secret

apiVersion: external-secrets.io/v1alpha1
kind: PushSecret
metadata:
  name: pushsecret-example # Customisable
  namespace: default # Same of the SecretStores
spec:
  updatePolicy: Replace # Policy to overwrite existing secrets in the provider on sync
  deletionPolicy: Delete # the provider' secret will be deleted if the PushSecret is deleted
  refreshInterval: 1h # Refresh interval for which push secret will reconcile
  secretStoreRefs: # A list of secret stores to push secrets to
    - name: aws-parameterstore
      kind: SecretStore
  selector:
    secret:
      name: pokedex-credentials # Source Kubernetes secret to be pushed
    # Alternatively, you can point to a generator that produces values to be pushed
    generatorRef:
      apiVersion: external-secrets.io/v1alpha1
      kind: ECRAuthorizationToken
      name: prod-registry-credentials
  template:
    metadata:
      annotations: { }
      labels: { }
    data:
      best-pokemon: "{{ .best-pokemon | toString | upper }} is the really best!"
    # Uses an existing template from configmap
    # Secret is fetched, 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: application-config-tmpl
          items:
            - key: config.yml
  data:
    - conversionStrategy: None # Also supports the ReverseUnicode strategy
      match:
        secretKey: best-pokemon # Source Kubernetes secret key to be pushed
        remoteRef:
          remoteKey: my-first-parameter # Remote reference (where the secret is going to be pushed)

Additional Metadata for PushSecret

Optionally, it is possible to configure additional options for the parameter such as Type and encryption Key. To control this behaviour you can set the following provider's metadata:

apiVersion: external-secrets.io/v1alpha1
kind: PushSecret
metadata:
  name: pushsecret-example # Customisable
  namespace: default # Same of the SecretStores
spec:
  deletionPolicy: Delete # the provider' secret will be deleted if the PushSecret is deleted
  refreshInterval: 1h # Refresh interval for which push secret will reconcile
  secretStoreRefs: # A list of secret stores to push secrets to
    - name: aws-parameterstore
      kind: SecretStore
  selector:
    secret:
      name: pokedex-credentials # Source Kubernetes secret to be pushed
  data:
    - match:
        remoteRef:
          remoteKey: my-first-parameter # Remote reference (where the secret is going to be pushed)
      metadata:
        parameterStoreType: "SecureString"
        parameterStoreKeyID: "bb123123-b2b0-4f60-ac3a-44a13f0e6b6c"

parameterStoreType takes three options. String, StringList, and SecureString, where String is the default.

parameterStoreKeyID takes a KMS Key $ID or $ARN (in case a key source is created in another account) as a string, where alias/aws/ssm is the default. This property is only used if parameterStoreType is set as SecureString.

Check successful secret sync

To be able to check that the secret has been succesfully synced you can run the following command:

kubectl get pushsecret pushsecret-example

If the secret has synced successfully it will show the status as "Synced".

Test new secret using AWS CLI

To View your parameter on AWS Parameter Store using the AWS CLI, install and login to the AWS CLI using the following guide: AWS CLI.

Run the following commands to get your synchronized parameter from AWS Parameter Store:

aws ssm get-parameter --name=my-first-parameter --region=us-east-1

You should see something similar to the following output:

{
    "Parameter": {
        "Name": "my-first-parameter",
        "Type": "String",
        "Value": "charmander",
        "Version": 4,
        "LastModifiedDate": "2022-09-15T13:04:31.098000-03:00",
        "ARN": "arn:aws:ssm:us-east-1:1234567890123:parameter/my-first-parameter",
        "DataType": "text"
    }
}

AWS Authentication

Controller's Pod Identity

Pod Identity Authentication

Note: If you are using Parameter Store replace service: SecretsManager with service: ParameterStore in all examples below.

This is basicially a zero-configuration authentication method that inherits the credentials from the runtime environment using the aws sdk default credential chain.

You can attach a role to the pod using IRSA, kiam or kube2iam. When no other authentication method is configured in the Kind=Secretstore this role is used to make all API calls against AWS Secrets Manager or SSM Parameter Store.

Based on the Pod's identity you can do a sts:assumeRole before fetching the secrets to limit access to certain keys in your provider. This is optional.

apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: team-b-store
spec:
  provider:
    aws:
      service: SecretsManager
      region: eu-central-1
      # optional: do a sts:assumeRole before fetching secrets
      role: team-b

Access Key ID & Secret Access Key

SecretRef

You can store Access Key ID & Secret Access Key in a Kind=Secret and reference it from a SecretStore.

apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: team-b-store
spec:
  provider:
    aws:
      service: SecretsManager
      region: eu-central-1
      # optional: assume role before fetching secrets
      role: team-b
      auth:
        secretRef:
          accessKeyIDSecretRef:
            name: awssm-secret
            key: access-key
          secretAccessKeySecretRef:
            name: awssm-secret
            key: secret-access-key

NOTE: In case of a ClusterSecretStore, Be sure to provide namespace in accessKeyIDSecretRef, secretAccessKeySecretRef with the namespaces where the secrets reside.

EKS Service Account credentials

Service Account

This feature lets you use short-lived service account tokens to authenticate with AWS. You must have Service Account Volume Projection enabled - it is by default on EKS. See EKS guide on how to set up IAM roles for service accounts.

The big advantage of this approach is that ESO runs without any credentials.

apiVersion: v1
kind: ServiceAccount
metadata:
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/team-a
  name: my-serviceaccount
  namespace: default

Reference the service account from above in the Secret Store:

apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: secretstore-sample
spec:
  provider:
    aws:
      service: SecretsManager
      region: eu-central-1
      auth:
        jwt:
          serviceAccountRef:
            name: my-serviceaccount

NOTE: In case of a ClusterSecretStore, Be sure to provide namespace for serviceAccountRef with the namespace where the service account resides.

Custom Endpoints

You can define custom AWS endpoints if you want to use regional, vpc or custom endpoints. See List of endpoints for Secrets Manager, Secure Systems Manager and Security Token Service.

Use the following environment variables to point the controller to your custom endpoints. Note: All resources managed by this controller are affected.

ENV VAR DESCRIPTION
AWS_SECRETSMANAGER_ENDPOINT Endpoint for the Secrets Manager Service. The controller uses this endpoint to fetch secrets from AWS Secrets Manager.
AWS_SSM_ENDPOINT Endpoint for the AWS Secure Systems Manager. The controller uses this endpoint to fetch secrets from SSM Parameter Store.
AWS_STS_ENDPOINT Endpoint for the Security Token Service. The controller uses this endpoint when creating a session and when doing assumeRole or assumeRoleWithWebIdentity calls.