AWS Systems Manager Parameter Store is a more integrated solution for managing secrets than using encrypted Git.

Here’s how it works in a typical CI/CD pipeline:

Imagine a deployment script that needs a database password.

#!/bin/bash
DB_PASSWORD=$(aws ssm get-parameter --name /myapp/prod/db/password --with-decryption --query Parameter.Value --output text)

# Now use $DB_PASSWORD in your deployment...
echo "Deploying with password (not really, just for demo)"
# kubectl apply -f deployment.yaml

This script pulls the secret directly from SSM Parameter Store. The aws ssm get-parameter command, when used with --with-decryption, fetches the plaintext secret after it’s decrypted by SSM.

Let’s break down how this fits into a larger picture:

The Problem: Secrets in Code and Config

Historically, developers would hardcode credentials directly into application code or configuration files. This is a massive security risk. If that code is committed to Git, the credentials are now in version history, accessible to anyone with read access. Even if you remove it later, it’s still in the history.

The Solution: Centralized, Encrypted Stores

  • HashiCorp Vault: A powerful, open-source tool that acts as a dedicated secrets management system. It offers dynamic secrets (credentials that are generated on-demand and expire), encryption-as-a-service, and integrates with many other systems. It’s a comprehensive solution but can have a steeper learning curve and operational overhead.
  • AWS SSM Parameter Store: A service within AWS that allows you to store configuration data and secrets in a hierarchical manner. It has two tiers: Standard and Advanced. For secrets, you’ll use the SecureString type, which automatically encrypts the data using AWS KMS. It’s deeply integrated with other AWS services (IAM, Lambda, EC2, ECS, EKS), making it very convenient if you’re already in the AWS ecosystem.
  • Encrypted Git (e.g., git-crypt, SOPS): These tools allow you to encrypt specific files within your Git repository. When you commit, the files are encrypted. When you checkout, they are decrypted. This keeps secrets out of plain text in history but requires managing encryption keys and ensuring everyone on the team has them. It’s a good option for smaller teams or projects that aren’t heavily invested in cloud-specific secret managers.

How SSM Parameter Store Works for Secrets

  1. Storing a Secret: You can store a secret using the AWS CLI:

    aws ssm put-parameter \
        --name "/myapp/prod/db/password" \
        --value "mySuperSecretPassword123!" \
        --type SecureString \
        --key-id "alias/aws/ssm" # Or a custom KMS key ARN
    
    • --name: A hierarchical path for your parameter. Good practice to include environment and application.
    • --value: The actual secret.
    • --type SecureString: This is crucial. It tells SSM to encrypt the value.
    • --key-id: Specifies which KMS key to use for encryption. alias/aws/ssm uses the default AWS-managed KMS key for SSM. You can create and use your own customer-managed KMS keys for more control.
  2. Accessing a Secret: As shown in the initial script, you use aws ssm get-parameter --with-decryption.

    DB_PASSWORD=$(aws ssm get-parameter --name "/myapp/prod/db/password" --with-decryption --query Parameter.Value --output text)
    
    • --with-decryption: This flag is essential. Without it, you’d get the encrypted ciphertext.
    • --query Parameter.Value --output text: This extracts just the plaintext secret value into the DB_PASSWORD shell variable.
  3. IAM Permissions: The identity (user, role, service account) that needs to access the secret must have an IAM policy granting ssm:GetParameter permission for the specific parameter name (or a pattern like /myapp/prod/*).

    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Action": "ssm:GetParameter",
                "Resource": "arn:aws:ssm:us-east-1:123456789012:parameter/myapp/prod/db/password"
            },
            {
                "Effect": "Allow",
                "Action": "ssm:GetParameter",
                "Resource": "arn:aws:ssm:us-east-1:123456789012:parameter/myapp/prod/api/key"
            }
        ]
    }
    

    This is the core of security: your CI/CD runner (e.g., an EC2 instance role, an EKS service account) has permission to fetch only the secrets it needs.

Why SSM is Often Better Than Encrypted Git

While encrypted Git keeps secrets out of plain text history, it has limitations:

  • Key Management: You have to securely distribute and manage the encryption keys for all developers and CI/CD systems. This can become complex.
  • Granularity: You encrypt entire files. If a file contains both a secret and non-secret configuration, the non-secret parts are also encrypted, which can be inconvenient.
  • CI/CD Integration: CI/CD systems need access to the decryption keys, adding another layer of secret management for the CI/CD system itself.

SSM Parameter Store, on the other hand, leverages AWS IAM for granular access control and KMS for robust encryption. The CI/CD system only needs IAM credentials that allow it to call ssm:GetParameter for specific parameters. The decryption happens automatically within AWS.

The most surprising true thing about managing secrets with tools like SSM Parameter Store is that you don’t actually manage the encryption yourself; you delegate it to a specialized, highly secure service (KMS) and control access through a robust identity and access management system (IAM). The complexity of key rotation, algorithm choice, and secure storage is handled by AWS.

When you first start using SSM Parameter Store, you might find yourself needing to fetch multiple parameters for different parts of your application. You’ll likely discover the aws ssm get-parameters-by-path command, which can retrieve all parameters under a given path, making your scripts cleaner.

Want structured learning?

Take the full DevOps & Platform Engineering course →