From c45dde0407e4407907d26d4e3bf26c752d2fc5c6 Mon Sep 17 00:00:00 2001 From: Martin Altmayer <141163644+MartinAltmayerTMH@users.noreply.github.com> Date: Wed, 4 Dec 2024 17:45:55 +0100 Subject: [PATCH] feat: Support placing the lambda into a VPC (#1078) * feat: Support placing the lambda into a VPC * docs: Add documentation for SopsSyncProviderProps * docs: Add example for lambda networking configuration --- API.md | 70 ++++++++++++++++++++++++++++++++++++++++++++++++- README.md | 24 ++++++++++++++++- src/SopsSync.ts | 30 ++++++++++++++++++++- 3 files changed, 121 insertions(+), 3 deletions(-) diff --git a/API.md b/API.md index b222fe53..4658531e 100644 --- a/API.md +++ b/API.md @@ -962,13 +962,14 @@ The current versionId of the secret populated via this resource. ```typescript import { SopsSyncProvider } from 'cdk-sops-secrets' -new SopsSyncProvider(scope: Construct, id?: string) +new SopsSyncProvider(scope: Construct, id?: string, props?: SopsSyncProviderProps) ``` | **Name** | **Type** | **Description** | | --- | --- | --- | | scope | constructs.Construct | *No description.* | | id | string | *No description.* | +| props | SopsSyncProviderProps | *No description.* | --- @@ -984,6 +985,12 @@ new SopsSyncProvider(scope: Construct, id?: string) --- +##### `props`Optional + +- *Type:* SopsSyncProviderProps + +--- + #### Methods | **Name** | **Description** | @@ -3388,6 +3395,67 @@ The secret that will be populated with the encrypted sops file content. --- +### SopsSyncProviderProps + +Configuration options for a custom SopsSyncProvider. + +#### Initializer + +```typescript +import { SopsSyncProviderProps } from 'cdk-sops-secrets' + +const sopsSyncProviderProps: SopsSyncProviderProps = { ... } +``` + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| securityGroups | aws-cdk-lib.aws_ec2.ISecurityGroup[] | Only if `vpc` is supplied: The list of security groups to associate with the Lambda's network interfaces. | +| vpc | aws-cdk-lib.aws_ec2.IVpc | VPC network to place Lambda network interfaces. | +| vpcSubnets | aws-cdk-lib.aws_ec2.SubnetSelection | Where to place the network interfaces within the VPC. | + +--- + +##### `securityGroups`Optional + +```typescript +public readonly securityGroups: ISecurityGroup[]; +``` + +- *Type:* aws-cdk-lib.aws_ec2.ISecurityGroup[] +- *Default:* A dedicated security group will be created for the lambda function. + +Only if `vpc` is supplied: The list of security groups to associate with the Lambda's network interfaces. + +--- + +##### `vpc`Optional + +```typescript +public readonly vpc: IVpc; +``` + +- *Type:* aws-cdk-lib.aws_ec2.IVpc +- *Default:* Lambda function is not placed within a VPC. + +VPC network to place Lambda network interfaces. + +--- + +##### `vpcSubnets`Optional + +```typescript +public readonly vpcSubnets: SubnetSelection; +``` + +- *Type:* aws-cdk-lib.aws_ec2.SubnetSelection +- *Default:* Subnets will be chosen automatically. + +Where to place the network interfaces within the VPC. + +--- + ## Enums diff --git a/README.md b/README.md index cff7c966..2ec0fd8d 100644 --- a/README.md +++ b/README.md @@ -127,6 +127,28 @@ const secret = new SopsSecret(this, 'SopsComplexSecretJSON', { }); ``` + +### Use a VPC for the Lambda Function + +Internally, SopsSync uses a lambda function. In some environments it may be necessary to place this lambda function into a VPC and configure subnets and/or security groups for it. +This can be done by creating a custom `SopsSyncProvider`, setting the required networking configuration and passing it to the secret like this: + +```typescript +// Create the provider +const provider = new SopsSyncProvider(this, 'CustomSopsSyncProvider', { + vpc: myVpc, + vpcSubnets: subnetSelection, + securityGroups: [mySecurityGroup], +}); +// create the secret and pass the the provider to it +const secret = new SopsSecret(this, 'SopsSecret', { + sopsProvider: provider, + secretName: 'myCoolSecret', + sopsFilePath: 'secrets/sopsfile-encrypted.json', +}); +``` + + ### UploadType: INLINE / ASSET I decided, that the default behavior should be "INLINE" because of the following consideration: @@ -247,4 +269,4 @@ The problem this Construct addresses is so good, already two other implementatio ## License -The Apache-2.0 license. Please have a look at the [LICENSE](LICENSE) and [LICENSE-3RD-PARTY](LICENSE-3RD-PARTY). \ No newline at end of file +The Apache-2.0 license. Please have a look at the [LICENSE](LICENSE) and [LICENSE-3RD-PARTY](LICENSE-3RD-PARTY). diff --git a/src/SopsSync.ts b/src/SopsSync.ts index 89c63aed..244d0976 100644 --- a/src/SopsSync.ts +++ b/src/SopsSync.ts @@ -9,6 +9,7 @@ import { CustomResource, FileSystem, } from 'aws-cdk-lib'; +import { ISecurityGroup, IVpc, SubnetSelection } from 'aws-cdk-lib/aws-ec2'; import { IGrantable, IRole, @@ -169,10 +170,34 @@ export interface SopsSyncProps extends SopsSyncOptions { readonly encryptionKey?: IKey; } +/** + * Configuration options for a custom SopsSyncProvider. + */ +export interface SopsSyncProviderProps { + /** + * VPC network to place Lambda network interfaces. + * + * @default - Lambda function is not placed within a VPC. + */ + readonly vpc?: IVpc; + /** + * Where to place the network interfaces within the VPC. + * + * @default - Subnets will be chosen automatically. + */ + readonly vpcSubnets?: SubnetSelection; + /** + * Only if `vpc` is supplied: The list of security groups to associate with the Lambda's network interfaces. + * + * @default - A dedicated security group will be created for the lambda function. + */ + readonly securityGroups?: ISecurityGroup[]; +} + export class SopsSyncProvider extends SingletonFunction implements IGrantable { private sopsAgeKeys: SecretValue[]; - constructor(scope: Construct, id?: string) { + constructor(scope: Construct, id?: string, props?: SopsSyncProviderProps) { super(scope, id ?? 'SopsSyncProvider', { code: Code.fromAsset( scope.node.tryGetContext('sops_sync_provider_asset_path') || @@ -190,6 +215,9 @@ export class SopsSyncProvider extends SingletonFunction implements IGrantable { ), }), }, + vpc: props?.vpc, + vpcSubnets: props?.vpcSubnets, + securityGroups: props?.securityGroups, }); this.sopsAgeKeys = []; }