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: age1yourrecipientpublickeyYou 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.