private createOnEventHandler()

in packages/static-website/src/cloudfront-web-acl.ts [118:228]


  private createOnEventHandler(stack: Stack, aclName: string): Function {
    // NB without manually defining a name, the cdk generated name for the Provider function can become too long and
    // deployments fail. This is because the Provider's name references the onEvent handler name and appends "-Provider"
    // rather than being generated by cdk and truncated appropriately
    const onEventHandlerName = `${PDKNag.getStackPrefix(stack)
      .split("/")
      .join("-")}AclEvent-${this.node.addr.slice(-6)}`;
    const onEventHandlerRole = new Role(this, "OnEventHandlerRole", {
      assumedBy: new ServicePrincipal("lambda.amazonaws.com"),
      inlinePolicies: {
        logs: new PolicyDocument({
          statements: [
            new PolicyStatement({
              effect: Effect.ALLOW,
              actions: [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents",
              ],
              resources: [
                `arn:aws:logs:${stack.region}:${stack.account}:log-group:/aws/lambda/${onEventHandlerName}`,
                `arn:aws:logs:${stack.region}:${stack.account}:log-group:/aws/lambda/${onEventHandlerName}:*`,
              ],
            }),
          ],
        }),
        wafv2: new PolicyDocument({
          statements: [
            new PolicyStatement({
              effect: Effect.ALLOW,
              actions: [
                "wafv2:CreateWebACL",
                "wafv2:DeleteWebACL",
                "wafv2:UpdateWebACL",
                "wafv2:GetWebACL",
              ],
              resources: [
                `arn:aws:wafv2:us-east-1:${stack.account}:global/ipset/${aclName}-IPSet/*`,
                `arn:aws:wafv2:us-east-1:${stack.account}:global/webacl/${aclName}/*`,
                `arn:aws:wafv2:us-east-1:${stack.account}:global/managedruleset/*/*`,
              ],
            }),
            new PolicyStatement({
              effect: Effect.ALLOW,
              actions: [
                "wafv2:CreateIPSet",
                "wafv2:DeleteIPSet",
                "wafv2:UpdateIPSet",
                "wafv2:GetIPSet",
              ],
              resources: [
                `arn:aws:wafv2:us-east-1:${stack.account}:global/ipset/${aclName}-IPSet/*`,
              ],
            }),
          ],
        }),
      },
    });

    const onEventHandler = new Function(
      this,
      "CloudfrontWebAclOnEventHandler",
      {
        code: Code.fromAsset(path.join(__dirname, "./webacl_event_handler")),
        role: onEventHandlerRole,
        functionName: onEventHandlerName,
        handler: "index.onEvent",
        runtime: Runtime.NODEJS_18_X,
        timeout: Duration.seconds(300),
      }
    );

    ["AwsSolutions-IAM5", "AwsPrototyping-IAMNoWildcardPermissions"].forEach(
      (RuleId) => {
        NagSuppressions.addResourceSuppressions(
          onEventHandlerRole,
          [
            {
              id: RuleId,
              reason:
                "WafV2 resources have been scoped down to the ACL/IPSet level, however * is still needed as resource id's are created just in time.",
              appliesTo: [
                {
                  regex: `/^Resource::arn:aws:wafv2:us-east-1:${PDKNag.getStackAccountRegex(
                    stack
                  )}:global/(.*)$/g`,
                },
              ],
            },
            {
              id: RuleId,
              reason:
                "Cloudwatch resources have been scoped down to the LogGroup level, however * is still needed as stream names are created just in time.",
              appliesTo: [
                {
                  regex: `/^Resource::arn:aws:logs:${PDKNag.getStackRegionRegex(
                    stack
                  )}:${PDKNag.getStackAccountRegex(
                    stack
                  )}:log-group:/aws/lambda/${onEventHandlerName}:\*/g`,
                },
              ],
            },
          ],
          true
        );
      }
    );

    return onEventHandler;
  }