aws/aws-cdk

aws-secretsmanager: grantRead should add Decrypt Policy for kms key

Open

#20 087 ouverte le 26 avr. 2022

Voir sur GitHub
 (5 commentaires) (4 réactions) (0 assignés)TypeScript (3 530 forks)batch import
@aws-cdk/aws-secretsmanagerbugeffort/smallgood first issuep2

Métriques du dépôt

Stars
 (10 710 stars)
Métriques de merge PR
 (Merge moyen 14j 11h) (68 PRs mergées en 30 j)

Description

Describe the bug

When I use fromSecretAttributes and add a encryptionKey, cdk should automatically add a decrypt policy to the roles default policy when I grant a read access to a role. This is working for example on dynamodb Tables.

export interface TestStack2Props extends StackProps {
    secretArn: string,
    secretKeyArn: string,
}

export class TestStack2 extends Stack {
    public constructor(scope: Construct, id: string, props: TestStack2Props) {
        super(scope,id,props);

        const key = Key.fromKeyArn(this, 'key', props.secretKeyArn);

        const secret = Secret.fromSecretAttributes(this,'secret',{
            secretCompleteArn: props.secretArn,
            encryptionKey: key
        })

        const role = new Role(this,'role',{
            assumedBy: new AccountPrincipal('111122223333')
        })
        secret.grantRead(role);
        key.grantDecrypt(role); // <-- should not be necessary
    }
}

This solution with dynamo db is working well:

export interface TestStack2Props extends StackProps {
    tableName: string,
    tableKeyArn: string,
}

export class TestStack2 extends Stack {
    public constructor(scope: Construct, id: string, props: TestStack2Props) {
        super(scope, id, props);

        const key = Key.fromKeyArn(this, 'key', props.tableKeyArn);

        const table = Table.fromTableAttributes(this, 'table', {
            encryptionKey: key,
            tableName: props.tableName
        })

        const role = new Role(this, 'role', {
            assumedBy: new AccountPrincipal('111122223333')
        })
        table.grantReadData(role);
        // key.grantDecrypt(role); // <-- is not necessary
    }
}

Expected Behavior

This policy statement should exist in the template

            {
              "Action": "kms:Decrypt",
              "Effect": "Allow",
              "Resource": {
                "Fn::ImportValue": "stack1:ExportsOutputFnGetAttkeyFEDD6EC0Arn6AD68239"
              }
            }

Or other statements depending on the grant action.

Current Behavior

it does not add a policy statement to allow decryption of the secret using the given kms encryptionKey.

Reproduction Steps

import {App, Stack, StackProps} from "aws-cdk-lib";
import {Construct} from "constructs";
import {Secret} from "aws-cdk-lib/aws-secretsmanager";
import {AccountPrincipal, Role} from "aws-cdk-lib/aws-iam";
import {Key} from "aws-cdk-lib/aws-kms";

export class TestStack1 extends Stack {
    public secretArn: string;
    public secretKeyArn: string;

    public constructor(scope?: Construct, id?: string, props?: StackProps) {
        super(scope, id, props);

        const key = new Key(this, 'key')
        this.secretKeyArn = key.keyArn;
        const secret = new Secret(this, 'secret', {
            encryptionKey: key,
        })
        this.secretArn = secret.secretArn
    }
}

export interface TestStack2Props extends StackProps {
    secretArn: string,
    secretKeyArn: string,
}

export class TestStack2 extends Stack {
    public constructor(scope: Construct, id: string, props: TestStack2Props) {
        super(scope, id, props);

        const key = Key.fromKeyArn(this, 'key', props.secretKeyArn);

        const secret = Secret.fromSecretAttributes(this, 'secret', {
            secretCompleteArn: props.secretArn,
            encryptionKey: key
        })

        const role = new Role(this, 'role', {
            assumedBy: new AccountPrincipal('111122223333')
        })
        secret.grantRead(role);
        // key.grantDecrypt(role); // <-- should not be necessary
    }
}

const app = new App({
    outdir: 'cdk.test.out'
})
const stack1 = new TestStack1(app, 'stack1');
new TestStack2(app, 'stack2', {
    secretArn: stack1.secretArn,
    secretKeyArn: stack1.secretKeyArn,
})

app.synth();

Possible Solution

No response

Additional Information/Context

No response

CDK CLI Version

2.21.1 (build a6ee543)

Framework Version

No response

Node.js Version

v14.17.6

OS

Linux Ubuntu 21.10

Language

Typescript

Language Version

TypeScript (4.6.3)

Other information

No response

Guide contributeur