Overview

SopsSecret — Sops to SecretsManager

Minimal example#

const secret = new SopsSecret(stack, 'MySopsSecret', {
  secretName: 'mySecret', // name of the secret in AWS SecretsManager
  sopsFilePath: 'secrets/sopsfile-encrypted-secret.json', // filepath to the sops encrypted file
});

The referenced SOPS file is synced to the Secrets Manager secret named mySecret. Two transformations apply for convenience:

  • Nested structures and arrays are resolved and flattened into JSONPath notation
  • All values are stored as strings

This is required by CDK's dynamic references and by the limitations of the Secrets Manager console's Key/Value view. So the stored secret actually looks like:

{
  "apiKey": "sk-1234567890abcdef",
  "database.user": "admin",
  "database.password": "P@ssw0rd!",
  "database.host": "db.example.com",
  "tokens[0].service": "github",
  "tokens[0].token": "ghp_abcd1234",
  "tokens[1].service": "aws",
  "tokens[1].token": "AKIAIOSFODNN7EXAMPLE",
  "someOtherKey": "base64:VGhpcyBpcyBhIHNlY3JldCBrZXk="
}

Access the flattened values from CDK:

secret.secretValueFromJson('"database.password"').toString(),
  secret.secretValueFromJson('"tokens[0].token"').toString();

Disabling the conversions#

If you don't want the flattening/stringify behavior, disable it with rawOutput:

const secret = new SopsSecret(stack, 'MySopsSecret', {
  rawOutput: RawOutput.STRING,
  ...
});

RawOutput.STRING places the decrypted content directly into the target secret with no conversion. RawOutput.BINARY does the same but populates the secret with binary data instead of a string.

Expiration notifications#

SopsSecret can synthesize one-time EventBridge Scheduler schedules for unencrypted expiration keys in a local SOPS file:

import * as subscriptions from 'aws-cdk-lib/aws-sns-subscriptions';
 
new SopsSecret(stack, 'MySopsSecret', {
  sopsFilePath: 'secrets/sopsfile-encrypted-secret.yaml',
  expirationNotification: {
    enabled: true,
    daysBeforeExpiration: [30, 60, 90],
    subscriber: new subscriptions.EmailSubscription('ops@example.com'),
  },
});

Expiration notifications are disabled by default. Once enabled, keys ending in _expiration are read directly by CDK from the local sopsFilePath, and matching schedules publish to SNS 14 days before the configured date. daysBeforeExpiration accepts a single number or a list such as [30, 60, 90] for multiple reminders per key. Expiration fields must remain unencrypted in the source file — for example via SOPS unencrypted_regex.

Upgrade note: upgrading from earlier versions may change the synthesized EventBridge Scheduler schedule names/logical IDs (now hash-suffixed), which causes CloudFormation to replace existing schedules during deployment. Plan for this schedule churn when rolling out the upgrade.

Example .sops.yaml configuration:

creation_rules:
  - path_regex: secrets/.*\.sops\.yaml
    unencrypted_suffix: _expiration
    age: age1yourrecipientpublickey

You can attach a subscriber to the created or provided SNS topic — for example EmailSubscription, UrlSubscription, LambdaSubscription, or SqsSubscription.

expirationNotification only supports local structured files (json, yaml, dotenv), doesn't support sopsS3Bucket / sopsS3Key, and can't be combined with rawOutput.