Skip to content

AWS SecretsManager

Andreas Auernhammer edited this page Apr 29, 2020 · 15 revisions

This guide shows how to setup a KES server that uses AWS SecretsManager as a persistent key store protected by the AWS-KMS:

  1. AWS SecretsManager Configuration
  2. KES Server setup
                         ╔═══════════════════════════════════════════════════╗
┌────────────┐           ║  ┌────────────┐          ┌─────────────────────┐  ║
│ KES Client ├───────────╫──┤ KES Server ├──────────┤ AWS Secrets-Manager │  ║
└────────────┘           ║  └────────────┘          └──────────┬──────────┘  ║
                         ╚═════════════════════════════════════╪═════════════╝
                                                               |
                                                         ┌─────┴─────┐
                                                         |  AWS-KMS  |
                                                         └───────────┘

AWS SecretsManager

The AWS SecretsManager is basically a key-value store for secrets - like passwords, access tokens and cryptographic keys. AWS will encrypt these secrets via their AWS-KMS service.

To create, retrieve and delete secrets at/from the AWS SecretsManager you need an AWS IAM user - i.e. an AWS access key and AWS secret key pair with sufficient IAM policy permissions. If you already have an IAM user / the access key and secret key, you can skip the following to steps:

  1. Go to the AWS console and create a new user. Use the Programmatic access type to create a new access key / secret key pair.
  2. Attach policies to that user to grant access to the AWS SecretsManager and the AWS-KMS. AWS has predefined policies (SecretsManagerReadWrite and AWSKeyManagementServicePowerUser) that will work but also grant a lot of permissions that are not needed. Your AWS IAM user needs to have to following permissions:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Stmt1578498399136",
      "Action": [
        "secretsmanager:CreateSecret",
        "secretsmanager:DeleteSecret",
        "secretsmanager:GetSecretValue"
      ],
      "Effect": "Allow",
      "Resource": "*"
    },
    {
      "Sid": "Stmt1578498562539",
      "Action": [
        "kms:Decrypt",
        "kms:DescribeKey",
        "kms:Encrypt",
      ],
      "Effect": "Allow",
      "Resource": "*"
    }
  ]
}

Note that this example policy grants access to all KMS and SecretsManager resources. You can restrict that by specifying a AWS ARN as resource instead *.

KES Server setup

First, we need to generate a TLS private key and certificate for our KES server. A KES server can only be run with TLS - since secure-by-default. Here we use self-signed certificates for simplicity. For a production setup we highly recommend to use a certificate signed by CA (e.g. your internal CA or a public CA like Let's Encrypt)

  1. First, create the TLS private key:

    openssl ecparam -genkey -name prime256v1 | openssl ec -out server.key
  2. Then, create the corresponding TLS X.509 certificate:

    openssl req -new -x509 -days 30 -key server.key -out server.cert \
      -subj "/C=/ST=/L=/O=/CN=localhost" -addext "subjectAltName = IP:127.0.0.1"
  3. Now you have a server.key and server.cert file. Next, we create the root identity:

    kes tool identity new --key=root.key --cert=root.cert root

    Note that we create a private key (root.key) and a certificate (root.cert) for TLS client authentication. Again, the certificate is not signed by a CA that is trusted by the KES server. That is not a security issue per se since only clients with public keys/certificates that are known to the server can perform operations based on policies. However, we recommend to use client certificates that were issued by a trusted CA. Then the KES server does not even accept connections from untrusted clients.

    You can compute the root identity via:

    kes tool identity of root.cert
  4. Since we don't want to give our applications root capabilities we also create an app identity:

    kes tool identity new --key=app.key --cert=app.cert app

    You can compute the app identity via:

    kes tool identity of app.cert
  5. Now we have defined all entities in our demo setup. Let's wire everything together by creating the config file server-config.yml:

    address: 0.0.0.0:7373
    root:    <kes-tool-identity-of root.cert>
    
    tls:
      key : server.key
      cert: server.cert
    
    policy:
      my-app:
        paths:
        - /v1/key/create/my-app*
        - /v1/key/generate/my-app*
        - /v1/key/decrypt/my-app*
        identities:
        - <kes-tool-identity-of app.cert>
    
    keys:
      aws:
        secretsmanager:
          endpoint: secretsmanager.us-east-2.amazonaws.com  # Use the SecretsManager in your region.
          region:   us-east-2                               # Use your region
          kmskey:   ""                                      # Your AWS-KMS master key (CMK) - optional.
          credentials:
            accesskey: "" # Your AWS Access Key
            secretkey: "" # Your AWS Secret Key

    Please use your own root and app identity and access key / secret key pair.

  6. Finally we can start a KES server in a new window/tab:

    kes server --config=server-config.yml --auth=off

    --auth=off is required since our root.cert and app.cert certificates are self-signed

  7. In the previous window/tab we now can connect to the server by:

    export KES_CLIENT_TLS_CERT_FILE=app.cert
    export KES_CLIENT_TLS_KEY_FILE=app.key
    kes key create app-key -k

    -k is required because we use self-signed certificates

    Now, you should see a secret key inside the ./keys directory.

  8. Finally, we can derive and decrypt data keys from the previously created app-key:

    kes key derive app-key -k
    {
      plaintext : ...
      ciphertext: ...
    }
    kes key decrypt app-key -k <base64-ciphertext>
Clone this wiki locally