Course outline

21.3

SSM Parameter Store vs Secrets Manager

Hierarchies, tiers and policies, secret rotation, multi-Region secrets, and choosing between them.

20 min Reading + animations

Tip: tap or hover any dotted-underlined term to see what it means.

By the end of this lesson you will be able to

  • Explain why passwords, API keys and configuration do not belong in code, AMIs or environment files, and what the two AWS services for them are for.
  • Use SSM Parameter Store: parameter types (String, StringList, SecureString with KMS), hierarchies such as /shop/prod/db_url, IAM per path, GetParametersByPath, public AMI parameters and references to Secrets Manager.
  • Choose between the Standard and Advanced tiers (10,000 vs 100,000 parameters, 4 KB vs 8 KB, free vs 0.05 USD a month), know the default and higher throughput, and use parameter policies (Expiration, ExpirationNotification, NoChangeNotification).
  • Explain AWS Secrets Manager: secrets encrypted with KMS, automatic secret rotation (managed rotation or a Lambda function with four steps and three staging labels), the RDS integration, pricing, resource policies and multi-Region secrets.
  • Diagnose the classic failures: a role without kms:Decrypt, a rotation function with no network path, an application that caches a password forever, a secret that lives in only one Region.
  • Pick Parameter Store or Secrets Manager from the keywords of a scenario.

#Why: a password in the code is a password for everyone

Lessons 21.1 and 21.2 were about encrypting data and managing the keys. This lesson is about a smaller but more dangerous kind of data: the values an application needs in order to run. A database URL, a database password, a payment gateway API key, a feature flag, the AMI ID to launch.

#The problem

A Dhaka online shop, a small Daraz-style marketplace, started the usual way. The database password sat in config.py, the payment gateway key in a .env file baked into the AMI, and the developers copied production settings to their laptops to debug. Then three things happened in one year:

  • A contractor pushed the repository to a public Git host for a few hours. The password and the key were in its history forever.
  • The security auditor asked who had read the payment key in the last 90 days. Nobody could answer.
  • The bank behind the payment gateway asked them to change the key every 30 days. Changing it meant a new AMI and a redeployment each time.

The fix is to keep these values outside the application, in a service that stores them encrypted, decides with IAM who may read each one, logs every read in CloudTrail, and can change them without a redeployment. AWS offers two such services:

  • AWS Systems Manager Parameter Store (SSM Parameter Store): a cheap, simple, hierarchical store for configuration and secrets.
  • AWS Secrets Manager: a dedicated, paid service for secrets, whose headline feature is automatic rotation.

#SSM Parameter Store

#What it stores

Parameter Store is a tool of AWS Systems Manager (the wider service is lesson 25.3). It gives you secure, serverless, durable storage for configuration data and secrets, read through a simple SDK or CLI call. Each parameter is a name and a value of one of three types:

TypeWhat it holdsExample
StringPlain text/shop/prod/db_url = shop-prod.example:5432
StringListA comma-separated list/shop/prod/allowed_cities = Dhaka,Chattogram,Sylhet
SecureStringText encrypted with a KMS key: the AWS managed key aws/ssm by default, or a customer managed key you choose/shop/prod/db_password

Useful properties:

  • Encryption is optional and seamless. A SecureString is encrypted when stored and decrypted only when a caller asks with decryption on (--with-decryption) and is allowed to use the KMS key (lesson 21.2). Standard parameters are encrypted with KMS directly; Advanced ones use envelope encryption, one reason a parameter cannot move between tiers.
  • Versions. Every change creates a new version; Parameter Store keeps the last 100. You can read an old version (name:3) or attach a label such as approved to one.
  • Security through IAM. Who may read or write which parameter is decided by IAM policies on the parameter's ARN, and every call is logged in CloudTrail (lesson 19.6).
  • Notifications with EventBridge. Parameter changes and policy events can trigger rules (lesson 19.5).
  • Integration everywhere. CloudFormation, EC2 launch templates, ECS task definitions, Lambda, build pipelines and the other Systems Manager tools can read parameters directly.
  • Data type aws:ec2:image. A String parameter can be marked as holding an AMI ID; Parameter Store then checks that the ID exists before saving it.

#Hierarchies and IAM

Parameter names can contain slashes, so you can organise them like folders, up to 15 levels deep. A common layout is application, then environment, then setting:

/shop/
    dev/
        db_url
        db_password          (SecureString)
        payment/mode
    prod/
        db_url
        db_password          (SecureString)
        payment/api_key      (SecureString)
/billing/
    prod/...

Two things follow from this:

  • Access per environment with one IAM line. A parameter's ARN contains its name, for example arn:aws:ssm:ap-southeast-1:111122223333:parameter/shop/prod/db_password. So a policy on parameter/shop/dev/* gives exactly the development folder and nothing else. The default IAM rule applies: no Allow means an implicit deny (lesson 2.2).
  • Load a whole folder in one call. GetParametersByPath with the path /shop/dev/ (and --recursive for sub-folders) returns every parameter under it, up to 10 per page, so the application needs no list of names. GetParameters returns up to 10 named parameters at once.

The role of the development EC2 instances only needs:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["ssm:GetParameter", "ssm:GetParameters", "ssm:GetParametersByPath"],
      "Resource": "arn:aws:ssm:ap-southeast-1:111122223333:parameter/shop/dev/*"
    },
    {
      "Effect": "Allow",
      "Action": "kms:Decrypt",
      "Resource": "arn:aws:kms:ap-southeast-1:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab"
    }
  ]
}

The second statement matters only for SecureString values encrypted with a customer managed key: reading the parameter and decrypting it are two separate permissions. With the AWS managed key aws/ssm, the key policy already lets principals of the same account use it through Parameter Store.

Reading configuration from Parameter Store

A Dhaka online shop keeps its settings under /shop/dev/ and /shop/prod/. Two EC2 apps with different IAM roles read them. Watch what IAM and KMS check on every call.

Scenario

The password is stored encrypted; Parameter Store asks KMS to decrypt it only for a caller who is allowed.

Dev approle dev-app
Prod approle prod-app
Parameter Store
IAM policy
KMSalias/shop-prod
get parameter

Request

Name

/shop/prod/db_password

With decryption

true

Step 1 of 4
1

At start-up the prod app asks for /shop/prod/db_password with decryption on. The password is not in the code, the AMI or a Git repository, so a leaked repository leaks nothing.

#Public parameters and references to Secrets Manager

Two special paths are worth knowing:

  • /aws/service/...: public parameters published by AWS. The best known are the newest AMI IDs, for example /aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64. They exist in every Region with that Region's ID, are free to read, and a launch template or CloudFormation template can name the parameter instead of a fixed AMI ID (lesson 4.3). AWS also publishes Region and service lists and other AMIs (Windows, Bottlerocket, ECS-optimised) this way.
  • /aws/reference/secretsmanager/<secret-name>: a pass-through to Secrets Manager. GetParameter (with decryption on) on this path returns the secret from Secrets Manager, so code or tools that already read Parameter Store can read a secret without a new SDK. Only GetParameter and GetParameters work on it (no GetParametersByPath, no writes, no versions), and the caller still needs permission on the secret. Parameter Store keeps nothing: the secret stays in Secrets Manager.

#Standard and Advanced tiers

Each parameter belongs to a tier, per account and Region:

StandardAdvanced
Maximum number of parameters (per account and Region)10,000100,000
Maximum value size4 KB8 KB
Parameter policiesNoYes
Share with other accounts (AWS Resource Access Manager)NoYes
Storage costNo charge0.05 USD per parameter per month (prorated hourly)
API calls at standard throughputNo charge0.05 USD per 10,000 interactions
Change tierCan be upgraded to AdvancedCannot go back to Standard

An Advanced parameter cannot be downgraded, because its value might be bigger than 4 KB, its policies would be lost and it uses a different form of encryption. To stop paying for it, delete it and create a new Standard parameter. The account also has a default tier setting (Standard, Advanced, or Intelligent-Tiering, which picks Advanced only when a request needs it, for example a value over 4 KB or a policy); it affects only new parameters.

#Throughput

Tiers control storage; throughput controls the request rate, and it is a separate setting:

  • Default throughput: up to 40 transactions per second, shared by GetParameter, GetParameters and GetParametersByPath, per account and Region. Free for Standard parameters.
  • Higher throughput (one setting for the account and Region): up to 10,000 GetParameter, 1,000 GetParameters and 100 GetParametersByPath calls per second. Every API interaction is then charged, 0.05 USD per 10,000, for Standard parameters too. An interaction is one parameter in one request, so a call that returns ten parameters counts as ten.
  • SecureString reads can additionally be limited by KMS request quotas in the Region.

The usual cause of throttling is an application that reads its parameters on every request. Read them once at start-up (or when a Lambda environment initialises) and cache them for a few minutes. For Lambda, the AWS Parameters and Secrets Lambda Extension is a ready-made local cache for both services.

#Parameter policies (Advanced only)

A parameter policy is a rule attached to an Advanced parameter, enforced by Parameter Store's periodic scans with no code on your side. Up to 10 policies per parameter, three types:

PolicyWhat it doesExample
ExpirationDeletes the parameter at a given date and time (a TTL for sensitive data)Delete the partner token on 1 December
ExpirationNotificationSends an EventBridge event a number of days or hours before the expirationWarn 15 days before
NoChangeNotificationSends an EventBridge event if the parameter has not been modified for a number of days or hoursAlert if the approved AMI ID is older than 60 days
[
  { "Type": "Expiration", "Version": "1.0", "Attributes": { "Timestamp": "2026-12-01T00:00:00.000Z" } },
  { "Type": "ExpirationNotification", "Version": "1.0", "Attributes": { "Before": "15", "Unit": "Days" } },
  { "Type": "NoChangeNotification", "Version": "1.0", "Attributes": { "After": "60", "Unit": "Days" } }
]

Two details trip people up: updating the parameter's value does not move its expiration date (change the policy for that), and a put-parameter with new policies replaces all existing policies on the parameter, so send the full list every time.

Tiers, parameter policies and throughput

The shop’s ops engineer stores bigger values, makes a partner token expire, and survives a flash sale. Watch where the Standard tier stops and the paid options begin.

Scenario

Standard parameters hold at most 4 KB. A bigger value needs the Advanced tier.

Ops engineer
Order functionsflash sale
Parameter Store
EventBridge
Ops email
put 6 KB

Request

Name

/shop/prod/payment/routing

Tier

Standard

Size

6 KB

Step 1 of 3
1

The engineer saves a 6 KB JSON with the payment gateway’s routing rules as a Standard parameter, the free default.

#AWS Secrets Manager

#What it is

AWS Secrets Manager is a service built only for secrets: database credentials, third-party API keys, OAuth client secrets, SSH keys. Compared with Parameter Store it adds the things a secret needs over its whole life:

  • A secret is a name plus a value, usually a JSON document of key-value pairs (for a database: engine, host, port, user name, password), up to 64 KB. It can also be binary.
  • Always encrypted with KMS: with the AWS managed key aws/secretsmanager, or a customer managed key you choose. Secrets Manager calls KMS for the caller, so a caller needs kms:Decrypt on a customer managed key as well as secretsmanager:GetSecretValue.
  • Versions and staging labels. Each value is a version; labels such as AWSCURRENT say which version is in use. A plain GetSecretValue returns the AWSCURRENT version.
  • Automatic rotation on a schedule, the headline feature (next section).
  • Random password generation (GetRandomPassword), so nobody has to invent a password.
  • Resource policies on a secret, for access from other accounts.
  • Audit: every read and change is in CloudTrail.
  • Integrations: RDS, Aurora, Redshift and DocumentDB can keep their admin password in it; RDS Proxy reads its credentials from it; ECS and EKS inject secrets into containers; CloudFormation reads them with dynamic references.

Price: 0.40 USD per secret per month (prorated for part of a month) plus 0.05 USD per 10,000 API calls. A replica in another Region is billed as a secret too. This is the main reason not to put every setting in Secrets Manager.

#Automatic rotation

The notes call this feature “automatic key rotation”. That is easy to misread: Secrets Manager rotates the secret value (the password or API key) and updates it in the database or service; it does not rotate a KMS key. Rotation of KMS key material is a separate KMS feature (lesson 21.2).

Schedule. A rate() or cron() expression in UTC, from every 4 hours up to every 999 days, with a rotation window (at least 1 hour) in which rotation happens. Turning rotation on rotates the secret immediately by default. A manual change of the value also counts as a rotation for the next date.

There are two ways the work gets done:

  • Managed rotation: the service that owns the secret rotates it, with no Lambda function in your account. Amazon RDS and Aurora (master user), Redshift (admin password) and DocumentDB (master user) offer it. Create the database with “manage master credentials in AWS Secrets Manager” (--manage-master-user-password) and the password is generated, stored and rotated every 7 days by default, schedule changeable (lesson 7.4).
  • Rotation by a Lambda function: for every other secret. AWS provides function templates for RDS and Aurora engines (MySQL, PostgreSQL, MariaDB, Oracle, SQL Server, Db2), Redshift, DocumentDB and ElastiCache; for anything else (a third-party API key) you write the function from a generic template.

A rotation function is called four times, once per step, and uses staging labels to keep the application safe:

  1. createSecret

    Generate a new password and store it as a new version labelled AWSPENDING. Nothing reads AWSPENDING, so no application uses it yet.

  2. setSecret

    Log in to the database (or service) and change the credentials to the AWSPENDING value.

  3. testSecret

    Log in with the AWSPENDING value to prove it works.

  4. finishSecret

    Move AWSCURRENT to the new version. Secrets Manager puts AWSPREVIOUS on the old one, the last known good value.

If any step fails, AWSCURRENT has not moved, so the application keeps the old, still-working credentials; Secrets Manager retries during the window and records the failure in CloudTrail, which an EventBridge rule can turn into an alert.

Two rotation strategies for database users:

  • Single user: one user, whose password is changed in place. Simple; but between setSecret and the moment an application refreshes its copy, a new login with the old password fails. Fine for most applications that retry after re-reading the secret.
  • Alternating users: two users (app_user and app_user_clone) take turns. Each rotation changes the user that is not current, so credentials an application already holds stay valid until the next rotation. It needs a separate admin secret the function uses to change passwords. Best for high availability.

Secret rotation, label by label

The shop’s orders database user is rotated every 30 days. Follow the secret’s versions and their staging labels, the password the database accepts, and the application.

Scenario

Four steps: createSecret, setSecret, testSecret, finishSecret. The label AWSCURRENT moves only at the end.

Who acts

nobody yet

Database accepts

password A

Application

logs in with password A

Secret versions and labels

v1 · password A

AWSCURRENT
Step 1 of 6
1

Day 0: the secret has one version, v1, labelled AWSCURRENT. GetSecretValue returns AWSCURRENT unless you ask for another label, so the application uses password A.

#Using a secret from an application

The flow is always the same: the application's IAM role calls GetSecretValue, Secrets Manager checks IAM and the secret's resource policy, KMS decrypts, the value returns over TLS. What matters in practice:

  • Cache. Read the secret at start-up and refresh it every few minutes, and read it again whenever a login fails with an authentication error (that covers the moment after a rotation). The AWS SDKs offer caching clients; the AWS Parameters and Secrets Lambda Extension does it for Lambda; the Secrets Manager Agent (2024) does it on EC2, containers and on premises. BatchGetSecretValue reads up to 20 secrets in one call.
  • Network. Secrets Manager is reached at a public Regional endpoint. A function or instance in a private subnet needs an interface VPC endpoint for Secrets Manager (private DNS keeps the normal name) or a NAT gateway; without one, the call simply hangs until it times out (lesson 15.3, lesson 22.2). A rotation function needs two paths: to Secrets Manager and to the database port.
  • Containers. An ECS task definition can name a Secrets Manager secret or a Parameter Store parameter in its secrets section, and ECS injects the value as an environment variable when the task starts (lesson 14.2); EKS uses the Secrets Store CSI driver. An injected value does not change when the secret rotates, so the task must be restarted or the app must read the secret itself.
  • RDS Proxy reads the database credentials from Secrets Manager itself and picks up rotations, so a Lambda function only needs IAM authentication to the proxy (lesson 7.4).
  • CloudFormation dynamic references keep secrets out of templates (lesson 25.1): {{resolve:secretsmanager:prod/shop/orders-db:SecretString:password}} for a secret, {{resolve:ssm:/shop/prod/db_url}} for a String parameter, and {{resolve:ssm-secure:/shop/prod/db_password}} for a SecureString, which only some resource properties accept. A resource such as AWS::RDS::DBCluster can also simply set ManageMasterUserPassword: true.

An application reads a secret

The shop’s order function and its rotation function run in private subnets with no NAT gateway. Secrets Manager is reached through an interface VPC endpoint.

Scenario

One GetSecretValue call, a KMS decrypt, then the database login. The value is cached, not fetched per request.

VPC, private subnets
Order function
Rotation function
Endpoint
Orders DB
Secrets Manager
KMSalias/shop-secrets
GetSecretValue
Step 1 of 5
1

A new Lambda environment starts and asks for the secret prod/shop/orders-db. Private DNS makes the normal Secrets Manager name resolve to the endpoint’s private IP, so the code does not change.

#Access from another account

A secret can carry a resource policy that allows a principal in another account, for example a Lambda role in account 444455556666 reading prod/shop/orders-db in account 111122223333. Three things must all allow it:

  1. The secret's resource policy allows secretsmanager:GetSecretValue for the other account's role.
  2. The secret is encrypted with a customer managed key whose key policy allows that role kms:Decrypt. The AWS managed key aws/secretsmanager cannot be used from another account, so a secret encrypted with it cannot be shared.
  3. The role's own IAM policy allows both actions on those ARNs.

Parameter Store has no resource policies. Advanced parameters can be shared with other accounts through AWS Resource Access Manager (read-only, by full ARN), but the exam's cross-account secret answer is Secrets Manager with a resource policy.

#Multi-Region secrets

An application that runs in two Regions, for example active-active, or a warm standby for disaster recovery on an Aurora global database (lesson 7.3), needs the same credentials in both. Multi-Region secrets:

  • You create the secret in a primary Region and add replica Regions. Secrets Manager copies the encrypted value and its metadata (tags, resource policy) and keeps the replicas in sync with the primary.
  • A replica has the same name; its ARN differs only in the Region. So code in each Region reads the same name from its local endpoint, with low latency and no dependency on another Region.
  • Each replica is encrypted with a KMS key in its own Region (aws/secretsmanager there, or a customer managed key you name, for example a multi-Region key from lesson 21.2).
  • Rotation runs on the primary only; the new value propagates to every replica.
  • In a disaster you can promote a replica to a standalone secret: it becomes an ordinary secret in that Region that you can change, rotate, and later replicate again.

Multi-Region secrets

A telco runs its self-care app in Singapore with a warm standby in Mumbai, on an Aurora global database. Both Regions need the same database password.

Scenario

One secret, replicated to another Region and kept in sync by Secrets Manager.

Singaporeap-southeast-1
Mumbaiap-south-1
App
Aurora
Primary secret
Aurora
App
Replica secretin sync
replicate
Step 1 of 3
1

The secret is created in Singapore with a replica Region of Mumbai. The replica has the same name, and its ARN differs only in the Region.

#Parameter Store or Secrets Manager?

SSM Parameter StoreAWS Secrets Manager
Built forConfiguration and simple secretsSecrets (credentials, API keys)
EncryptionOptional (SecureString with KMS)Always, with KMS
Automatic rotationNoYes (managed, or Lambda function)
Expiry and change alertsParameter policies (Advanced)No such policies; rotation instead
Maximum value size4 KB (Standard), 8 KB (Advanced)64 KB
Maximum count per Region10,000 (Standard), 100,000 (Advanced)500,000
CostStandard: free storage and standard throughput; Advanced: 0.05 USD a month each0.40 USD per secret a month + 0.05 USD per 10,000 calls
Hierarchy and GetParametersByPathYesNo folders (names may contain slashes); BatchGetSecretValue
Cross-account accessAdvanced parameters shared through AWS Resource Access ManagerResource policy on the secret + customer managed key
Cross-Region replicationNoMulti-Region secrets
Native database integrationNoRDS, Aurora, Redshift, DocumentDB, RDS Proxy
Public AWS dataAMI IDs and more under /aws/service/No
CloudFormation dynamic referencessm, ssm-securesecretsmanager

A common, sensible split is to use both: configuration and cheap static secrets in Parameter Store, credentials that must rotate in Secrets Manager, and the /aws/reference/secretsmanager/ path when one piece of code should read everything through Parameter Store.

Parameter Store or Secrets Manager?

Each card is a requirement from a scenario. Pick the service that fits best and read why.

1.Keep 200 feature flags and the database URLs for dev and prod, at the lowest possible cost.

2.The RDS for PostgreSQL password must be rotated automatically every 30 days for compliance.

3.A launch template must always use the newest Amazon Linux 2023 AMI in each Region.

4.Store a 30 KB bundle of partner credentials as one value.

5.The same database credentials must exist in Singapore and Mumbai and stay in sync automatically for disaster recovery.

6.A temporary courier token must be deleted after 30 days, with an email 7 days before, without writing code.

7.RDS Proxy must log in to the database without credentials in the application.

8.An SMS gateway API key must be stored encrypted. It never needs rotation, and the budget is tight.

9.A 6 KB application configuration file, not secret, must be stored centrally.

10.A Lambda function in account 444455556666 must read a database password owned by account 111122223333, using a resource policy on the stored value.

Right first time: 0 / 0 (10)

#What goes wrong

  • AccessDeniedException although ssm:GetParameter or secretsmanager:GetSecretValue is allowed: the value is encrypted with a customer managed key and the role has no kms:Decrypt on it (or the key policy does not trust it). Add the KMS permission.
  • The dev servers can read production values: the IAM policy uses parameter/* instead of parameter/shop/dev/*. Fix the resource ARN; consider separate accounts for production (lesson 20.1).
  • A SecureString comes back as a long encrypted string: the call did not ask for decryption (--with-decryption / WithDecryption=true).
  • ValidationException on a 5 KB value: the parameter is Standard (4 KB). Use Advanced, or for values over 8 KB, Secrets Manager or S3.
  • ThrottlingException from Parameter Store at peak: 40 TPS default, shared by all get calls. Cache values, load once per Lambda environment, or enable higher throughput (paid).
  • A parameter vanished: an Expiration policy deleted it. Use ExpirationNotification to warn first, and renew before the date.
  • Old parameter policies disappeared after adding a new one: a new policy list replaces the old list. Send all policies every time.
  • Rotation fails with a timeout: the rotation function is not in the database's VPC, its security group is not allowed on the database port, or it has no endpoint or NAT gateway to reach Secrets Manager. AWSCURRENT stays on the old value, so the application keeps working, but the password is not rotated. Alert on rotation failures with EventBridge.
  • “Password authentication failed” days after a successful rotation: an application read the secret once and cached it forever, and only noticed at its next new connection (a failover, a restart of the pool). Cache with a time limit, re-read on authentication errors, or use RDS Proxy or alternating users.
  • ECS tasks still use the old password: values injected as environment variables are read only when the task starts. Restart tasks after rotation, or have the app read the secret.
  • The standby Region cannot log in during a disaster: the secret existed only in the failed Region. Replicate it to every Region the application runs in.
  • Another account cannot read a shared secret: the secret is encrypted with aws/secretsmanager, or the key policy, the resource policy or the caller's IAM policy is missing. All three must allow.
  • A surprising Secrets Manager bill: hundreds of plain settings stored as secrets, or a secret read on every request. Move configuration to Parameter Store and cache reads.

#In system design

Patterns you will meet:

  • Twelve-factor configuration: no configuration in the build; the same AMI or container image runs in dev and prod and reads /app/<env>/... at start-up.
  • Golden AMI pipelines: an EC2 Image Builder pipeline writes the newest approved AMI ID to a parameter; launch templates and Auto Scaling groups refer to the parameter.
  • Serverless data access: Lambda → RDS Proxy (IAM auth) → database, with the database credentials in Secrets Manager (lesson 15.3).
  • Multi-account: secrets live in the workload account; a central security account audits reads through an organization trail.
  • Disaster recovery: every secret the application needs is replicated to the recovery Region, and the runbook includes promoting it.

#Try it yourself

The commands use the AWS CLI v2 in ap-southeast-1. Secrets cost 0.40 USD a month each and Advanced parameters 0.05 USD a month, so delete them at the end. All values below are made-up examples.

# 1. Plain and encrypted parameters in a hierarchy (Standard tier, no charge)
aws ssm put-parameter --name /shop/dev/db_url --type String --value "shop-dev.example:5432"
aws ssm put-parameter --name /shop/dev/db_password --type SecureString --value "EXAMPLE-dev-pass"
aws ssm put-parameter --name /shop/dev/payment/mode --type String --value sandbox

# 2. Read the whole dev folder, decrypted
aws ssm get-parameters-by-path --path /shop/dev --recursive --with-decryption \
  --query 'Parameters[].[Name,Type,Value]' --output table
# -------------------------------------------------------------
# |                    GetParametersByPath                    |
# +---------------------------+--------------+----------------+
# |  /shop/dev/db_password    |  SecureString|  EXAMPLE-dev-pass
# |  /shop/dev/db_url         |  String      |  shop-dev.example:5432
# |  /shop/dev/payment/mode   |  String      |  sandbox       |
# +---------------------------+--------------+----------------+

# 3. The newest Amazon Linux 2023 AMI from a public parameter
aws ssm get-parameter --name /aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64 \
  --query Parameter.Value --output text
# ami-0abcdef1234567890

# 4. An Advanced parameter with an expiry, a warning 15 days before, and a no-change alert
aws ssm put-parameter --name /shop/prod/courier/token --type SecureString --tier Advanced \
  --value "EXAMPLE-courier-token" \
  --policies '[{"Type":"Expiration","Version":"1.0","Attributes":{"Timestamp":"2026-12-01T00:00:00.000Z"}},
               {"Type":"ExpirationNotification","Version":"1.0","Attributes":{"Before":"15","Unit":"Days"}},
               {"Type":"NoChangeNotification","Version":"1.0","Attributes":{"After":"20","Unit":"Days"}}]'
aws ssm describe-parameters --parameter-filters "Key=Name,Values=/shop/prod/courier/token" \
  --query 'Parameters[0].[Tier,Policies[].PolicyType]'
# [ "Advanced", [ "Expiration", "ExpirationNotification", "NoChangeNotification" ] ]

# 5. A secret with a generated password, and a 30-day rotation using an existing rotation function
PW=$(aws secretsmanager get-random-password --password-length 32 --exclude-punctuation \
  --query RandomPassword --output text)
aws secretsmanager create-secret --name prod/shop/orders-db \
  --secret-string "{\"engine\":\"postgres\",\"host\":\"orders.example\",\"port\":5432,\"username\":\"app_user\",\"password\":\"$PW\"}"
aws secretsmanager rotate-secret --secret-id prod/shop/orders-db \
  --rotation-lambda-arn arn:aws:lambda:ap-southeast-1:111122223333:function:shop-rotate-postgres \
  --rotation-rules '{"ScheduleExpression":"rate(30 days)","Duration":"3h"}'

# 6. See the versions and their staging labels after a rotation
aws secretsmanager describe-secret --secret-id prod/shop/orders-db --query VersionIdsToStages
# { "a1b2c3d4-1111-2222-3333-444455556666": [ "AWSPREVIOUS" ],
#   "e5f6a7b8-7777-8888-9999-000011112222": [ "AWSCURRENT" ] }

# 7. Read the current value, and the same secret through Parameter Store
aws secretsmanager get-secret-value --secret-id prod/shop/orders-db --query SecretString --output text
aws ssm get-parameter --name /aws/reference/secretsmanager/prod/shop/orders-db --with-decryption \
  --query Parameter.Value --output text

# 8. Replicate to Mumbai, and promote the replica (run in the replica Region) during a DR test
aws secretsmanager replicate-secret-to-regions --secret-id prod/shop/orders-db \
  --add-replica-regions Region=ap-south-1
aws secretsmanager stop-replication-to-replica --secret-id prod/shop/orders-db --region ap-south-1

# 9. An RDS instance whose master password RDS manages in Secrets Manager
aws rds create-db-instance --db-instance-identifier orders-demo --engine postgres \
  --db-instance-class db.t4g.micro --allocated-storage 20 \
  --master-username admin_user --manage-master-user-password

# 10. Clean up
aws ssm delete-parameters --names /shop/dev/db_url /shop/dev/db_password /shop/dev/payment/mode /shop/prod/courier/token
aws secretsmanager delete-secret --secret-id prod/shop/orders-db --force-delete-without-recovery --region ap-south-1
aws secretsmanager delete-secret --secret-id prod/shop/orders-db --recovery-window-in-days 7
aws rds delete-db-instance --db-instance-identifier orders-demo --skip-final-snapshot

Also try in the console: open Parameter Store, choose Create parameter, and compare what the Advanced tier unlocks (parameter policies). Then open a Secrets Manager secret, choose Rotation, and look at the schedule expression and the rotation window.

#Summary

Key takeaways

  • Keep configuration and secrets outside code and AMIs, in a service with IAM per value, KMS encryption and CloudTrail audit.
  • SSM Parameter Store: String, StringList, SecureString (KMS); versions; hierarchies (/shop/prod/db_url) with IAM on parameter/shop/dev/* and GetParametersByPath; public AMI parameters under /aws/service/; secrets readable through /aws/reference/secretsmanager/.
  • Tiers: Standard 10,000 parameters, 4 KB, free; Advanced 100,000, 8 KB, 0.05 USD a month, parameter policies, sharing; no downgrade. Throughput: 40 TPS default, higher throughput is charged.
  • Parameter policies (Advanced only): Expiration (deletes), ExpirationNotification and NoChangeNotification (EventBridge events).
  • Secrets Manager: secrets up to 64 KB, always KMS-encrypted, 0.40 USD per secret a month + API calls; automatic rotation of the secret (not of a KMS key) from every 4 hours; managed rotation for RDS, Aurora, Redshift, DocumentDB, otherwise a Lambda function with createSecret → setSecret → testSecret → finishSecret and labels AWSPENDING → AWSCURRENT → AWSPREVIOUS.
  • A rotation function needs a network path to the database and to Secrets Manager (endpoint or NAT); a failed rotation leaves AWSCURRENT unchanged.
  • Cross-account: resource policy on the secret + customer managed key. Multi-Region secrets: replicas kept in sync, same name, local KMS key, promote to standalone for DR.
  • Exam keywords: cost-effective configuration, hierarchy, 5–8 KB, expiry policies → Parameter Store; automatic rotation, RDS integration, multi-Region sync, cross-account secret → Secrets Manager.