Manage secrets in CDK via Mozilla SecretOPerationS (SOPS)

5 minute read
Content level: Intermediate
0

A guide to implement SopS into CDK.

Introduction

Managing secrets is a crucial task that must be addressed and appropriately done.

In the context of CDK, managing secrets could be more intuitive and challenging, especially when securely storing and sharing them across different environments.

A robust approach is represented by using Mozilla Secret Operations (SOPS). GitHub - Mozilla/sops: Simple and flexible tool for managing secrets

This article examines how to set up Mozilla SOPS for AWS CDK flows.

What’s SOPS

Sops is an editor of encrypted files that supports YAML, JSON, ENV, INI and BINARY formats and encrypts with AWS KMS, GCP KMS, Azure Key Vault, age, and PGP

In a nutshell, SOPS is a command-line tool that encrypts and decrypts YAML/JSON files using a symmetric key. It supports encryption algorithms and integrates seamlessly with popular cloud platforms such as AWS, Google Cloud, and Azure.

This article will encrypt secrets using Key Management System (KMS) symmetric AES-256 keys.

Install SOPS

  • Download the latest SOPS binaries exe file.

  • For Windows: Add environment variable EDITOR pointing to your editor of choice (e.g. Notepad++ “C:\Program Files\Notepad++\notepad++.exe”)

  • For Mac, ensure the command “code” is installed with the Shell command, and add environment EDITOR set to “code — wait.”

How to encrypt files

Once installed, follow these steps.

1. Create a KMS key

  • Set your [default] AWS credentials profile to the target environment of choice temporarily; you should point to the respective aws_access_key_id,aws_secret_access_key Pair.

  • Create a Symmetric KMS key in the chosen AWS account, as it will be used to encrypt the credentials: Creating keys

2. Generate SOPS file

Create a Sops folder under the CDK project:

Under that (CDK/sops) folder, run

sops --kms "KMS_KEY_ARN" FILE_NAME

where:

  • KMS_KEY_ARN is the KMS key ARN in the AWS Account.

  • FILE_NAME is the file name, with JSON extension, containing the secrets.

The full command would look like this:

sops -kms "arn:aws:kms:eu-west-1:123456789012:key/9c63b634-44ee-423e-8901-51c86a601077" encryptedSecretsDevelopment.sops.json

As a result, this command will open the file in your default editor and allow you to enter the secrets in the file. A default example is prompted to the user:

{
 "hello": "Welcome to SOPS! Edit this file as you please!",
 "example_key": "example_value",
 "example_array": [
  "example_value1",
  "example_value2"
 ],
 "example_number": 1234.56789,
 "example_booleans": [
  true,
  false
 ]
}

Modify the file, for instance, with the below info:

{
 "my_api_key": "MY_SECRET_API_KEY_HERE",
 "my_db_password": "MY_SECRET_DB_PASSWORD"
}

Upon saving the file (and potentially closing the editor), the file is modified by SOPS with encrypted secrets plus some SOPS metadata:

{
 "my_api_key": "ENC[AES256_GCM,data:Bgn8iXJ7cI4qAXB60CQ2FDxO6ICl2g==,iv:tGDIEKSPUZjM8vCZhKWz0dwv2M8ihS+zdfVXum3ka/o=,tag:TXLU2xFiLGI+dmdz2gbYPA==,type:str]",
 "my_db_password": "ENC[AES256_GCM,data:o7a6oOaasb7AjWKMz20iEkSsZ5hf,iv:h6g+K0O0sMHNKfyVvcJgGGa5xmISoG294Z0Ctk5wiaA=,tag:t552faza+GpEiD/AVkH6dA==,type:str]",
 "sops": {
  "kms": [
   {
    "arn": "arn:aws:kms:eu-west-1:123456789012:key/9c63b634-44ee-423e-8901-51c86a601077",
    "created_at": "2023-09-02T21:03:36Z",
    "enc": "AQICAHgofRgQw+eFPdlwmXSmK+tHDjNwCP/PI+Tf7UaaCoo7SwHhfHkSREH91FIoZ0sIq4DtAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMFPYp78VmomIPieSYAgEQgDsUsif0cSSeSniL1Q7N3YlTxEtcPIu3pGaEiwg/I2cCQVex9qVWVG2TVUY099B20kSBTsoGojEGikJ1kw==",
    "aws_profile": ""
   }
  ],
  "gcp_kms": null,
  "azure_kv": null,
  "hc_vault": null,
  "age": null,
  "lastmodified": "2023-09-02T21:15:14Z",
  "mac": "ENC[AES256_GCM,data:UMGmJihjAEE6DIP5DoP+EEQk8aNQ42pV9Lw3rey9/9HXJDOlkPwCWCWo6Hu/28WicNBW/PEqmL6cshbSrqP9Qyznu8+g2G9xVrI2avBJ+DQUI/QnTae3ElVyb4ZI7Uksmx1wwxkMYo7TZJXTAJlaJN+uhv826VUe9q1BMmI1CtY=,iv:bwHUJkDwvvRqP3bICMpHJVIbeL3ufOpsufpwup0Ic5w=,tag:iufUNLU5/P2WoO9MZST2Ng==,type:str]",
  "pgp": null,
  "unencrypted_suffix": "_unencrypted",
  "version": "3.7.3"
 }
}

The file now appears under the sops folder under the main CDK project, as shown below, and can be versioned and used for different environments:

3. How to use SOPS file with CDK

To use the SOPS file, we will leverage the SOPS Secrets construct: CDK-sops-secrets

This construct library replaces CDK SecretsManager secrets and allows storing secrets encrypted with SOPS in AWS Secrets Manager.

To use SOPS with CDK, load the encrypted secrets file with the SopsSecret construct and use it to refer to the secrets coming from the SecretsManager variable. Here’s an example:

import { SopsSecret } from "cdk-sops-secrets";

const sops = new SopsSecret(this, "SopsSecret", {
  secretName: "my-secrets-name",
  sopsFilePath: "sops/encryptedSecretsDevelopment.sops.json",
});

const decryptedSecret = sops.secretValueFromJson("my_api_key").toString();

// decryptedSecret ===> "MY_SECRET_API_KEY_HERE"

Upon deployment of CDK, the unencrypted secrets will be stored in Secrets Manager, while CDK code will deal with encrypted ones:

Of course, access to secrets should be managed via Segregation of Duties (SoD) when necessary, and generally following good practice to allow access can be seen here: Authentication and access control for AWS Secrets Manager

That’s it! By using SOPS to manage your secrets, you can keep them safe and secure while still being able to access them in your CDK code easily.

Lessons learnt / limitations

  • SOPS Installation could have been more intuitive, especially in Windows.

  • No matter what, **constantly **update all environment-encrypted variables by opening them via the SOPS tool.

  • Do not update the encrypted file directly to avoid corrupted data or mismatched MAC.

  • Do not update AWS Secrets in the console, but always rely on IaC.

Conclusion

Managing secrets in CDK is an essential task that requires careful consideration and proper tools. SOPS provides a simple and secure way to manage secrets in CDK by encrypting them using a symmetric key and allowing for granular access control and versioning.

Following the steps outlined in this article, you can use SOPS to manage your secrets in CDK and keep your cloud infrastructure secure.

1 Comment

Using toString throws an error in CDK, because it's un unsafe operation. Error: Resolution error: Synthing a secret value to environment/environmentVariables/SNYK_TOKEN/value. Using a SecretValue here risks exposing your secret. Only pass SecretValues to constructs that accept a SecretValue property, or call AWS Secrets Manager directly in your runtime code. Call 'secretValue.unsafeUnwrap()' if you understand and accept the risks..

In my cdk.json I have this flag : "@aws-cdk/core:checkSecretUsage": true I can set it to false off course, but is there an other way around this problem?

profile picture
replied 3 months ago