cdklabs / cdk-nag

Check CDK applications for best practices using a combination of available rule packs
Apache License 2.0
809 stars 58 forks source link

Failed to suppress a finding #1012

Closed greenpau closed 1 year ago

greenpau commented 2 years ago

General Issue

Failed to suppress a finding

The Question

I have the following construct:

/**
 * Copyright 2021 Amazon.com, Inc. and its affiliates. All Rights Reserved.
 *
 * Licensed under the Amazon Software License (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *   http://aws.amazon.com/asl/
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

import * as cdk from "aws-cdk-lib";
import * as lambda from "aws-cdk-lib/aws-lambda";
import { Construct } from "constructs";
import { spawnSync } from "child_process";
// import { NagSuppressions } from "cdk-nag";

/* eslint-disable @typescript-eslint/no-empty-interface */
export interface CsharpLambdaConstructProps {
    codePath: string;
    environment?: { [key: string]: string };
    name?: string;
    timeout?: cdk.Duration;
    vpc: cdk.aws_ec2.Vpc;
    runtime?: lambda.Runtime;
    handler: string;
    memorySize?: number;
}

const defaultProps: Partial<CsharpLambdaConstructProps> = {
    timeout: cdk.Duration.minutes(1),
    runtime: lambda.Runtime.DOTNET_6,
    memorySize: 1024,
};

/**
 * Deploys C# Lambda function in a particular VPC.
 */
export class CsharpLambdaConstruct extends Construct {
    public instance: lambda.Function;
    public config: CsharpLambdaConstructProps;

    constructor(parent: Construct, name: string, props: CsharpLambdaConstructProps) {
        super(parent, name);

        props = { ...defaultProps, ...props };

        const lambdaFunc = new lambda.Function(this, "Instance", {
            /* eslint-disable @typescript-eslint/no-non-null-assertion */
            runtime: props.runtime!,
            handler: props.handler,
            code: lambda.Code.fromAsset(props.codePath, {
                bundling: {
                    local: new CsharpBundler(props.codePath),
                    image: props.runtime!.bundlingImage,
                    command: [
                        "bash",
                        "-c",
                        ["dotnet publish -c Release -o /asset-output"].join(" && "),
                    ],
                    user: "root", // ~/.dotnet is only accessible by root
                },
            }),
            timeout: props.timeout,
            environment: props.environment,
            vpc: props.vpc,
            memorySize: props.memorySize,
        });

        // NagSuppressions.addResourceSuppressions(
        //     lambdaFunc,
        //     [
        //         {
        //             id: "AwsSolutions-IAM5",
        //             reason: "Disregard IAM issue to default role assigned to a lambda.",
        //         },
        //     ],
        //     true
        // );

        // Assign Cfn Outputs
        new cdk.CfnOutput(this, "InstanceName", {
            value: lambdaFunc.functionName,
        });

        // Assign public properties
        this.instance = lambdaFunc;
        this.config = props;
    }
}

/**
 * Bundles a C# Lambda function locally for auto-deployment.
 */
class CsharpBundler implements cdk.ILocalBundling {
    private codePath: string;

    constructor(codePath: string) {
        this.codePath = codePath;
    }

    public tryBundle(outputDir: string): boolean {
        // Note that we _must_ specify the target runtime as linux-x64
        // because .NET Lambda functions run on top of Amazon Linux 2
        // On non-Linux operating systems, we're effectively cross-compiling
        const args = [
            "publish",
            "-c",
            "Release",
            "-o",
            outputDir,
            "--runtime",
            "linux-x64",
            "--no-self-contained",
        ];

        try {
            spawnSync("dotnet", args, {
                cwd: this.codePath,
                stdio: ["ignore", process.stderr, "inherit"],
            });
        } catch {
            return false;
        }

        return true;
    }
}

One of the findings is:

"AwsSolutions-IAM5","Lambda/Instance/ServiceRole/DefaultPolicy/Resource","Non-Compliant","N/A","Error","The IAM entity contains wildcard permissions and does not have a cdk-nag rule suppression with evidence for those permission."

I attempted to suppress it:

         NagSuppressions.addResourceSuppressions(
             lambdaFunc,
             [
                 {
                     id: "AwsSolutions-IAM5",
                     reason: "Disregard IAM issue to default role assigned to a lambda.",
                 },
             ],
             true
        );

However, the suppression did not work. Any advice?

cdk-nag version

2.15.3

Language

Typescript

Other information

No response

dontirun commented 2 years ago

this.instance = lambdaFunc;

Are you adding permissions to the lambda function outside of the construct? It doesn't look like you've added any permissions to the Lambda function at the time of suppression so we may be seeing an error related to order of operations.

greenpau commented 2 years ago

Are you adding permissions to the lambda function outside of the construct?

@dontirun , I am adding suppression inside the construct.

It doesn't look like you've added any permissions to the Lambda function at the time of suppression so we may be seeing an error related to order of operations.

These permission are there by default. The role for cloudwatch logs with default policy (ServiceRole/DefaultPolicy/Resource) gets created as part of lambda.Function.

dontirun commented 2 years ago

I tried recreating this locally ,but I'm not seeing any AwsSolutions-IAM5 errors. Do you have a snippet for the stack that is using this construct?

dontirun commented 1 year ago

Closing due to inactivity