From 470e1dd3720b08417984bb0c710c901a7ce0b479 Mon Sep 17 00:00:00 2001 From: Markus Date: Sat, 9 Apr 2022 15:05:56 +0200 Subject: [PATCH] fix: readme --- .projenrc.js | 2 +- .vscode/ltex.dictionary.en-US.txt | 5 ++ API.md | 2 + README.md | 87 +++++++++++++++++++------------ src/index.ts | 2 +- 5 files changed, 63 insertions(+), 35 deletions(-) create mode 100644 .vscode/ltex.dictionary.en-US.txt diff --git a/.projenrc.js b/.projenrc.js index 9dd50115..7ab3079e 100644 --- a/.projenrc.js +++ b/.projenrc.js @@ -17,7 +17,7 @@ const project = new awscdk.AwsCdkConstructLibrary({ npmignoreEnabled: true, autoApproveUpgrades: true, autoApproveOptions: { - allowedUsernames: ['markussiebert'] + allowedUsernames: ['markussiebert'], }, name: 'cdk-sops-secrets', repositoryUrl: 'https://github.com/markussiebert/cdk-sops-secrets.git', diff --git a/.vscode/ltex.dictionary.en-US.txt b/.vscode/ltex.dictionary.en-US.txt new file mode 100644 index 00000000..d3d2ea8b --- /dev/null +++ b/.vscode/ltex.dictionary.en-US.txt @@ -0,0 +1,5 @@ +SecretsManager +SopsSecret +SopsSync +projen +stringify diff --git a/API.md b/API.md index fcd4527c..022e80f1 100644 --- a/API.md +++ b/API.md @@ -540,6 +540,8 @@ The current versionId of the secret populated via this resource. ### SopsSyncProvider +- *Implements:* aws-cdk-lib.aws_iam.IGrantable + #### Initializers ```typescript diff --git a/README.md b/README.md index 78b5e8d0..7b86b0cb 100644 --- a/README.md +++ b/README.md @@ -7,20 +7,27 @@ https://img.shields.io/github/issues-search/markussiebert/cdk-sops-secrets?color=%23ff0000&label=security-vulnerabilities&query=is%3Aissue%20is%3Aopen%20label%3A%22security%20vulnerability%22)](https://github.com/markussiebert/cdk-sops-secrets/issues?q=is%3Aissue+is%3Aopen+label%3A%22security+vulnerability%22)   [![cdk-construct-hub](https://img.shields.io/badge/CDK-ConstructHub-blue)](https://constructs.dev/packages/cdk-sops-secrets)   -## Introducation +## Introduction -This construct library provides a replacement for CDK SecretsManager Secrets, with extended functionality for mozilla/sops. +This construct library provides a replacement for CDK SecretsManager secrets, with extended functionality for Mozilla/sops. -Using this library it is possible to populate Secrets with values from a mozilla/sops file without additional scripts and steps in the CI stage. Thereby transformations like JSON conversion of YAML files and transformation into a flat, JSONPath like structure can be done. +Using this library it is possible to populate Secrets with values from a Mozilla/sops file without additional scripts and steps in the CI stage. Thereby transformations like JSON conversion of YAML files and transformation into a flat, JSONPath like structure will be performed, but can be disabled. -Secrets filled in this way can be used immediately within the CloudFormation stack and dynamic references. This construct should handle all dependencies, if you use the ```secretValueFromJson``` call. +Secrets filled in this way can be used immediately within the CloudFormation stack and dynamic references. This construct should handle all dependencies, if you use the ```secretValueFromJson``` or ```secretValue``` call to access secret values. -This way, secrets can be securely stored in git repositories and easily synchronized into AWS SecretsManager Secrets. +This way, secrets can be securely stored in git repositories and easily synchronized into AWS SecretsManager secrets. + +## Prerequisites + ++ [AWS](https://aws.amazon.com/): I think you already knew it, but this construct will only work with an AWS account. +* [KMS Key](https://aws.amazon.com/kms/?nc1=h_ls): It makes most sense to encrypt your secrets with AWS KMS if you want to sync and use the secret content afterwards in your AWS account. +* [mozilla/sops](https://github.com/mozilla/sops): This construct assumes that you store your secrets encrypted via sops in your git repository. +* [CDK](https://aws.amazon.com/cdk/?nc1=h_ls): As this is a CDK construct, it's only useful if you use the CloudDevelopmentToolkit. ## Getting started -1. Create a mozilla sops secrets file (with kms) and place it somewhere in your git repository -2. Create a secret with the SopsSecret construct +1. Create a Mozilla/sops secrets file (encrypted with an already existing KMS key) and place it somewhere in your git repository +2. Create a secret with the SopsSecret construct inside your app ```ts const secret = new SopsSecret(stack, 'SopsComplexSecretJSON', { sopsFilePath: 'secets/sopsfile-encrypted.json', @@ -31,44 +38,58 @@ This way, secrets can be securely stored in git repositories and easily synchron secret.secretValueFromJson('json.path.dotted.notation.accessor[0]').toString(), ``` +## Advanced configuration examples -## Motivation +Even if using the main functionality should be done in 3 lines of code, there are more options to configure the constructs of this library. The most useful settings will be explained in the further chapters: -This project was created to solve a recurring problem of syncing mozilla/sops secrets into AWS SecretsManager in a convenient, secure way. - -Other than that, or perhaps more importantly, my goal was to learn new things: -- Write a golang lambda -- Writing unit tests incl. mocks in golang -- Reproducible builds of golang binaries (byte-by-byte identical) -- Build reproducible zips (byte-by-byte identical) -- Release an npm package -- Setting up projects with projen -- CI/CD with github actions -- CDK unit and integration tests +### I don't want any conversion magic on my secret content — How can I disable it? -## Other Tools like this - -The problem this Construct addresses is so good, already two other implementations exist: - -* [isotoma/sops-secretsmanager-cdk](https://github.com/isotoma/sops-secretsmanager-cdk): Does nearly the same. Uses CustomResource, wraps the sops cli, does not support flatten. Found it after I published my solution to npm :-/ -* [taimos/secretsmanager-versioning](https://github.com/taimos/secretsmanager-versioning): Different approach on the same problem. This is a cli tool with very nice integration into cdk and also handles git versioning information. +As default behavior, the SopsSecret (via the SopsSync) will convert all content to JSON and flatten its structure. This is useful, because the AWS SecretsManager has some limitations if it comes to YAML and/or complex objects and decimal values. Even if you can store YAML, complex objects and even binaries in AWS SecretsManager secrets, you can't access their values via the SecretsManager API — you can only return them as is. So accessing (nested) values or values from YAML files won't be possible via [dynamic references](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/dynamic-references.html) in CloudFormation (and CDK). That's why I decided that conversion to JSON, flatten the structure and stringify all values should be the default behavior. But you can turn off all of these conversion steps: -## Advanced Configuration - -There are more options to configure the Construct which will be explained in the further chapters +```typescript + const secret = new SopsSecret(this, 'SopsComplexSecretJSON', { + secretName: 'myCoolSecret', + convertToJSON: false, // disable converting the encrypted content to JSON + stringify: false, // disable stringifying all values + flatten: false, // disable flattening of the object structure + }); +``` -### Access the Lambda Role +### There are missing permissions — How can I modify the provider permissions? -You can access the Lambda Role by creating your own Provider +Sometimes it can be necessary to access the IAM role of the SopsSync provider. If this is the case, you should create the provider before creating the SopsSecret, and pass the provider to it like this: ```typescript - const myExtraKmsKey = Key.fromKeyArn(this, 'MyExtraKmsKey', 'YourKeyArn'); + // Create the provider const provider = new SopsSyncProvider(this, 'CustomSopsSyncProvider') - myExtraKmsKey.grantDecrypt(provider.role!) + // Grant whatever you need to the provider + const myExtraKmsKey = Key.fromKeyArn(this, 'MyExtraKmsKey', 'YourKeyArn'); + myExtraKmsKey.grantDecrypt(provider) + // create the secret and pass the the provider to it const secret = new SopsSecret(this, 'SopsComplexSecretJSON', { sopsProvider: provider, secretName: 'myCoolSecret', - description: "its extra cool", sopsFilePath: 'secrets/sopsfile-encrypted.json', }); ``` + +## Motivation + +I have created this project to solve a recurring problem of syncing Mozilla/sops secrets into AWS SecretsManager in a convenient, secure way. + +Other than that, or perhaps more importantly, my goal was to learn new things: +- Write a Golang lambda +- Writing unit tests incl. mocks in Golang +- Reproducible builds of Golang binaries (byte-by-byte identical) +- Build reproducible zips (byte-by-byte identical) +- Release a NPM package +- Setting up projects with projen +- CI/CD with GitHub actions +- CDK unit and integration tests + +## Other Tools like this + +The problem this Construct addresses is so good, already two other implementations exist: + +* [isotoma/sops-secretsmanager-cdk](https://github.com/isotoma/sops-secretsmanager-cdk): Does nearly the same. Uses CustomResource, wraps the sops CLI, does not support flatten. Found it after I published my solution to NPM :-/ +* [taimos/secretsmanager-versioning](https://github.com/taimos/secretsmanager-versioning): Different approach on the same problem. This is a CLI tool with very nice integration into CDK and also handles git versioning information. diff --git a/src/index.ts b/src/index.ts index 9b916e69..196f5da0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -209,7 +209,7 @@ export class SopsSync extends Construct { } } -export class SopsSyncProvider extends SingletonFunction { +export class SopsSyncProvider extends SingletonFunction implements IGrantable { private sopsAgeKeys: SecretValue[]; constructor(scope: Construct, id?: string) {