SaveMyCert
Log in
5 of 5 free questions left today·for unlimited practice
Security

Managing Sensitive Data: Secrets Manager vs Parameter Store

14 min readDVA-C02 · SecurityUpdated

Managing sensitive data in application code means keeping credentials, keys, and personal data out of your source, your images, and your logs — and retrieving them securely at runtime instead. On the DVA-C02 exam this is Domain 2, Task 2.3, and it centers on one comparison you must know cold: AWS Secrets Manager versus AWS Systems Manager Parameter Store. Around that core, the exam probes data classification (PII and PHI), encrypting Lambda environment variables, fetching and caching secrets with GetSecretValue and GetParameter, and the v2.1 additions — application-level data masking and data access patterns for multi-tenant applications. Most questions are decision questions: a scenario contains a trigger phrase like "automatic rotation," "no additional cost," or "hardcoded credentials," and you pick the service or pattern that fits. This lesson covers each skill, the comparison table those questions draw from, and a worked scenario for migrating a hardcoded database password to a rotated secret.

What you’ll learn
  • Classify data as PII or PHI and explain how classification drives handling requirements
  • Choose between AWS Secrets Manager and Systems Manager Parameter Store for any exam scenario
  • Eliminate hardcoded credentials by using IAM roles and the SDK credential provider chain
  • Encrypt sensitive Lambda environment variables and explain their limits versus a secrets service
  • Keep PII out of logs and API responses with masking, sanitization, and CloudWatch Logs data protection policies
  • Design tenant-isolated data access using dynamodb:LeadingKeys and scoped temporary credentials

Data classification: why PII and PHI change the rules

Data classification is the practice of labeling data by sensitivity so that its handling requirements follow automatically. The two categories the exam guide names are personally identifiable information (PII) — anything that identifies a specific person, such as names, email addresses, phone numbers, government ID numbers, or precise location data — and protected health information (PHI) — health data tied to an identifiable person, which in the United States is regulated under HIPAA.

Classification matters because it drives every downstream decision. Public data can sit in a plaintext configuration file. PII must be encrypted at rest and in transit, access-controlled, kept out of logs, and often retained or deleted on a schedule. PHI adds regulatory obligations on top: stricter access auditing, formal agreements with any service provider that touches it, and hard limits on where the data may flow. If you do not classify first, you cannot answer questions like "may this field appear in a log line?" or "does this response need masking?" — the classification is the requirement.

For a developer, classification shows up as concrete choices: which fields your schema marks as sensitive, which log statements must scrub or mask values, which API responses redact fields, and which data stores warrant a customer managed KMS key rather than a default. The exam rarely asks you to define PII in isolation. Instead it describes a scenario involving health records or customer identity data and expects you to recognize that classified data demands encryption, masking, and restricted access — and to pick the answer that treats it more carefully than ordinary application state.

Secrets Manager vs Parameter Store: the core comparison

AWS Secrets Manager and Systems Manager Parameter Store both store values encrypted with KMS, both are retrieved by API call, and both are governed by IAM — so the exam distinguishes them on a handful of axes you should know cold:

AxisAWS Secrets ManagerSSM Parameter Store
CostCharged per secret per month, plus per API callStandard tier is free; advanced tier is paid
Automatic rotationBuilt in — managed rotation for Amazon RDS (including Aurora), Amazon Redshift, and Amazon DocumentDB credentials; custom rotation via a Lambda function for anything elseNone — you rotate values yourself
Cross-account accessYes, via a resource-based policy attached to the secretLimited — advanced-tier parameters only, shared through AWS RAM
EncryptionEvery secret is encrypted with KMSOnly the SecureString type is KMS-encrypted; String and StringList are not
Size limitUp to 64 KB per secret4 KB standard, 8 KB advanced
Built forSecrets: database credentials, API keys, OAuth tokensConfiguration: feature flags, endpoints, license codes — plus SecureString for simple static secrets

The decision rule the exam applies: if the scenario says automatic rotation, rotate database credentials, or cross-account secret sharing, the answer is Secrets Manager. If it says no additional cost, free, or describes plain application configuration with at most a simple encrypted value, the answer is Parameter Store — usually a SecureString backed by KMS. Both are wrong answers to each other's question: Parameter Store cannot rotate anything on its own, and Secrets Manager is the expensive choice for storing a feature flag.

Keep credentials out of code: IAM roles and the provider chain

Keeping credentials out of code is the baseline discipline this task assumes everywhere else. Hardcoded credentials — access keys pasted into source, committed to a repository, baked into an AMI or a container image, or left in a bundled .env file — persist in version history and image layers long after you "remove" them, and anyone who can read the artifact owns the credential. The exam treats any hardcoded long-term key as a defect with two fixes: use an IAM role, and move real secrets to a secrets service.

Roles work because of the credential provider chain. Every AWS SDK resolves credentials by checking a sequence of sources in order — roughly: explicit client configuration, environment variables, the shared credentials file, web identity or SSO tokens, container credentials (the ECS task role), and finally the EC2 instance metadata service (the instance profile role). Code that simply constructs a client with no credentials at all will automatically pick up the role attached to wherever it runs — a Lambda execution role, an ECS task role, or an EC2 instance profile — and receive short-lived temporary credentials that AWS rotates for you. The same code works on a developer laptop using a profile in the shared credentials file, with no code change.

This is why "how should the application authenticate to AWS?" almost never has an answer containing access keys. Long-term access keys are for the rare cases with no role option; everything running on AWS compute should rely on the chain. When a question shows credentials in an environment variable or a config file inside an image, the expected fix is: attach a role for AWS API access, and fetch application secrets (database passwords, third-party API keys) from Secrets Manager or Parameter Store at runtime.

Encrypting Lambda environment variables

Lambda environment variables that contain sensitive data need two layers of thought: how they are encrypted, and whether they should hold the secret at all. At rest, Lambda always encrypts environment variables with KMS — by default using an AWS managed key, or with a customer managed key you specify if you need to control and audit decryption access through your own key policy. That default protects the stored configuration, but it does not hide values from people: anyone allowed to call GetFunctionConfiguration or view the function in the console sees the plaintext.

For console visibility, Lambda offers encryption helpers: you encrypt an individual variable's value client-side with a customer managed key before it is stored, so the console and configuration API show only ciphertext. The trade-off is that your function code must explicitly call KMS to decrypt the value at startup, and the execution role needs decrypt permission on that key.

Even fully encrypted, environment variables are the weaker home for a real secret, for reasons the exam expects you to articulate. They are set at deployment time, so changing a credential means redeploying every function that embeds it. They cannot rotate. They tend to leak — into deployment templates, CI logs, and stack descriptions. A secrets service inverts all of this: the function stores only the secret's name in its environment, fetches the current value at runtime, and rotation happens centrally with no redeploy. The exam pattern: environment variables are fine for non-secret configuration and acceptable for low-sensitivity values when encrypted with a customer managed key, but the best answer for database credentials or API keys is a reference to Secrets Manager or an SSM SecureString parameter.

Retrieving secrets in code: fetch, decrypt, cache

Retrieving a secret in code comes down to two API calls and one performance decision. From Secrets Manager, you call GetSecretValue with the secret's name or ARN; the response carries the plaintext (commonly a JSON string holding username and password fields, which you parse). From Parameter Store, you call GetParameter — and for a SecureString you must pass WithDecryption set to true, or you get ciphertext back. Both paths require IAM permission on the secret or parameter itself, and for customer managed keys, kms:Decrypt on the backing key. A working call that suddenly returns permission errors after switching to a customer managed key is a classic exam scenario: the execution role has the secret permission but lacks the key permission.

The performance decision is caching. Fetching the secret on every invocation adds latency and API cost to every request. The standard pattern is to fetch once during initialization — outside the handler, in code that runs on cold start — store the value in a variable in the execution environment, and reuse it across warm invocations. Pair the cache with a TTL so a rotated secret is picked up within minutes, and handle authentication failures by refetching, which covers the window where rotation has already changed the credential your cache still holds.

AWS also ships this pattern prebuilt: the AWS Parameters and Secrets Lambda Extension runs alongside your function as a Lambda extension, exposes a local HTTP endpoint, and caches both Parameter Store parameters and Secrets Manager secrets with a configurable TTL — your code makes a local call instead of an SDK call and gets caching without writing any. Client-side caching libraries for Secrets Manager do the same inside your process.

Worked scenario: retiring a hardcoded database password

Retiring a hardcoded password is the scenario this task is built around, so walk it end to end. The setup: a Lambda function connects to an Amazon RDS for MySQL database, and the password sits in the function's source code, committed to the team repository.

Step one: create the secret. In Secrets Manager, store the database credentials as a database secret — Secrets Manager keeps them as a JSON structure with the engine, host, username, and password, encrypted with KMS.

Step two: grant access. Add secretsmanager:GetSecretValue on that secret's ARN to the function's execution role — nothing broader. If the secret uses a customer managed key, also grant kms:Decrypt on the key.

Step three: change the code. Delete the literal password. During initialization, call GetSecretValue, parse the JSON, build the database connection, and cache the connection and credentials in the execution environment for warm invocations. On an authentication failure, refetch the secret and reconnect — that handles rotation windows.

Step four: enable rotation. Because this is RDS, Secrets Manager's built-in rotation support applies: a rotation Lambda function changes the database password and updates the secret on your schedule — for example every 30 days — with no redeploy of your application.

Step five: rotate immediately and scrub. The old password lives in the repository's history, so treat it as compromised: run rotation now so the leaked value stops working. Removing it from the current source is not enough — history retains it.

The end state hits every marker the exam looks for: no credentials in code, least-privilege retrieval through an IAM role, caching for performance, and automatic rotation.

Sanitizing data: keep PII out of logs and responses

Sanitizing sensitive data means making sure values like PII never travel further than they must — into logs, error messages, traces, or API responses. The most common failure is logging: a debug statement that dumps a whole request object, or an exception message that embeds an email address, silently copies PII into CloudWatch Logs, where retention, access control, and downstream export are all governed separately from your database.

The first line of defense is discipline in code. Validate and scrub input at the boundary, and use structured logging — emitting logs as fields rather than free text — so sensitive fields can be deliberately excluded or masked before the log call, instead of hoping string interpolation never catches one. Mask values at write time: log the last four digits of a card number, a hashed user identifier instead of an email, a token's ID rather than the token.

The backstop is CloudWatch Logs data protection policies: you attach a policy to a log group, it detects sensitive data such as PII using managed data identifiers, and it masks those values in the log events; only principals granted a specific unmask permission can view the originals, and findings can be audited. Know it at concept level — and know that it is a safety net, not a substitute for not logging PII in the first place.

The same sanitization thinking applies to API responses, which leads into masking: a response should carry the fields the caller needs, with sensitive fields redacted or truncated — an account endpoint returns the card's last four digits, never the stored number. Error responses deserve equal care: return a calm, generic message to the client and keep the detailed error, minus sensitive values, in server-side logs.

Masking, tokenization, and multi-tenant data access

Application-level masking and multi-tenant access patterns are the two skills version 2.1 added to this task, and they share a theme: protecting sensitive data inside the application layer. Know three transformations and how they differ. Masking irreversibly obscures a value for display — showing only the last four digits. Tokenization replaces the value with a meaningless token and keeps the token-to-value mapping in a secured vault, so most of your system handles only tokens and the real value is recoverable only through the vault. Encryption transforms the value reversibly with a key — anyone with decrypt access can recover it. Exam cue: "display safely" points at masking, "remove the sensitive value from most systems but keep it recoverable" points at tokenization, and reversible protection under key control is encryption.

Multi-tenant applications add an isolation question: how do you guarantee tenant A can never read tenant B's rows? Two models frame it. The silo model gives each tenant separate resources — a table or database per tenant — with strong isolation at higher operational cost. The pool model shares one resource across tenants, with every item carrying a tenant identifier; it scales cheaply but makes isolation your job.

For a pooled DynamoDB table, the pattern is to make the tenant ID the leading partition key value and enforce it with IAM: a policy condition on dynamodb:LeadingKeys restricts a caller to items whose partition key begins with their tenant ID. Scope temporary credentials per tenant — assume a role per request with the tenant ID bound into a session tag or session policy that the condition references — so the guarantee is enforced by IAM on every data-plane call, not by a WHERE clause your application code must remember. Row-level isolation in application code alone is the wrong answer when an IAM-enforced option is offered.

Tip. Expect scenario questions that hinge on a trigger phrase: "automatic rotation" or rotating RDS credentials points to Secrets Manager, while "no additional cost" or simple encrypted configuration points to a Parameter Store SecureString. "Hardcoded credentials" in code, an AMI, or a container image is always answered with an IAM role plus a secrets service — never with encrypting the file or moving the key to another variable. Lambda questions probe whether you know environment variables are KMS-encrypted at rest yet readable by anyone who can view the configuration, and that fetch-and-cache with GetSecretValue or GetParameter with WithDecryption is the retrieval pattern. The v2.1 additions appear as "tenant isolation" scenarios expecting the dynamodb:LeadingKeys leading-key condition with tenant-scoped temporary credentials, and masking questions distinguishing masking, tokenization, and encryption.

Key takeaways
  • "Automatic rotation" or rotating database credentials means Secrets Manager; "free" or "no additional cost" configuration means Parameter Store standard tier.
  • Parameter Store SecureString values are encrypted with KMS but never rotate themselves; retrieving one requires GetParameter with WithDecryption set to true.
  • Cross-account secret access is a Secrets Manager resource-based policy — Parameter Store sharing is limited to advanced-tier parameters via AWS RAM.
  • Never hardcode credentials in code, repos, AMIs, or container images — attach an IAM role and let the SDK credential provider chain supply temporary credentials.
  • Lambda environment variables are KMS-encrypted at rest by default, but anyone who can read the function configuration sees the values — store a secret's name there, not the secret.
  • Fetch secrets during initialization, cache them in the execution environment with a TTL, and refetch on authentication failure to survive rotation; the Parameters and Secrets Lambda Extension provides this caching prebuilt.
  • Mask or redact PII before it is logged; CloudWatch Logs data protection policies mask detected PII in log groups as a backstop.
  • Pool-model tenant isolation in DynamoDB = tenant ID as the leading partition key plus an IAM dynamodb:LeadingKeys condition on per-tenant scoped temporary credentials.

Frequently asked questions

What is the difference between AWS Secrets Manager and Parameter Store?

Both store values encrypted with KMS and retrievable by API under IAM control. Secrets Manager is purpose-built for secrets: it charges per secret per month, supports automatic rotation with built-in support for RDS, Redshift, and DocumentDB credentials, allows cross-account access via resource-based policies, and holds secrets up to 64 KB. Parameter Store is for configuration: its standard tier is free, values up to 4 KB (8 KB advanced), SecureString gives KMS encryption, but there is no automatic rotation. Choose Secrets Manager when rotation or cross-account sharing is required; choose Parameter Store for configuration and simple encrypted values at no additional cost.

Are AWS Lambda environment variables encrypted?

Yes — Lambda always encrypts environment variables at rest with KMS, using an AWS managed key by default or a customer managed key you choose. However, anyone with permission to view the function configuration still sees the plaintext values. Encryption helpers let you encrypt individual values client-side with a customer managed key so the console shows only ciphertext, but your code must then call KMS to decrypt them. For real secrets like database passwords, store only the secret's name in the environment variable and fetch the value from Secrets Manager or Parameter Store at runtime.

How do I retrieve a secret from Secrets Manager in my application code?

Call the GetSecretValue API with the secret's name or ARN, then parse the returned secret string — database secrets are stored as JSON containing fields like username and password. The calling role needs secretsmanager:GetSecretValue permission on that secret, plus kms:Decrypt on the backing key if it is a customer managed key. Fetch the secret once during initialization and cache it in the execution environment rather than calling the API on every invocation, refresh it on a TTL, and refetch if authentication fails so your code survives rotation.

Should I cache secrets in Lambda or fetch them on every invocation?

Cache them. Fetching on every invocation adds latency and per-call cost to every request. The standard pattern is to fetch during initialization, hold the value in the execution environment across warm invocations, expire it on a TTL, and refetch on an authentication failure so rotation is handled. The AWS Parameters and Secrets Lambda Extension packages this pattern: it runs beside your function, exposes a local HTTP endpoint, and caches Secrets Manager secrets and Parameter Store parameters with a configurable TTL, so your code makes a fast local call instead of an SDK call.

How do I keep PII out of CloudWatch Logs?

Primarily by not logging it: validate and scrub input, use structured logging so sensitive fields are deliberately excluded, and mask values at write time — last four digits, hashed identifiers, token IDs. As a backstop, attach a data protection policy to the log group: CloudWatch Logs then detects sensitive data such as PII using managed data identifiers and masks it in the stored events, with only principals holding the unmask permission able to view originals. Treat the policy as a safety net; the plan is code that never emits PII.

How does dynamodb:LeadingKeys isolate tenants in a shared DynamoDB table?

In a pooled multi-tenant table, every item's partition key begins with the tenant ID. An IAM policy condition on dynamodb:LeadingKeys restricts the caller to items whose partition key matches their tenant's value — typically referenced from a session tag or policy variable. The application assumes a role per request with credentials scoped to that tenant, so DynamoDB itself rejects any read or write against another tenant's items. This enforces row-level isolation at the IAM layer instead of relying on application code to always filter correctly.

Test yourself on this topic
Practice questions with full explanations.
Practice now

Sign up free to mark lessons complete, bookmark topics and track your exam readiness.