|
| 1 | +import {NagMessageLevel, NagPack, NagPackProps} from "cdk-nag" |
| 2 | +import {IConstruct} from "constructs" |
| 3 | +import {CfnResource} from "aws-cdk-lib" |
| 4 | +import {ApiGatewayMutualTls} from "../rules" |
| 5 | +import {LambdaFunctionPublicAccessProhibited} from "cdk-nag/lib/rules/lambda" |
| 6 | +import {CloudWatchLogGroupEncrypted} from "cdk-nag/lib/rules/cloudwatch" |
| 7 | +import {ALBHttpDropInvalidHeaderEnabled, ELBLoggingEnabled, ELBTlsHttpsListenersOnly} from "cdk-nag/lib/rules/elb" |
| 8 | +import {APIGWAccessLogging, APIGWStructuredLogging} from "cdk-nag/lib/rules/apigw" |
| 9 | +import { |
| 10 | + IAMNoInlinePolicy, |
| 11 | + IAMPolicyNoStatementsWithAdminAccess, |
| 12 | + IAMPolicyNoStatementsWithFullAccess |
| 13 | +} from "cdk-nag/lib/rules/iam" |
| 14 | +import {S3BucketPublicReadProhibited, S3BucketPublicWriteProhibited, S3DefaultEncryptionKMS} from "cdk-nag/lib/rules/s3" |
| 15 | +import {SecretsManagerUsingKMSKey} from "cdk-nag/lib/rules/secretsmanager" |
| 16 | +import {SNSEncryptedKMS} from "cdk-nag/lib/rules/sns" |
| 17 | +import {VPCDefaultSecurityGroupClosed, VPCFlowLogsEnabled} from "cdk-nag/lib/rules/vpc" |
| 18 | +import {WAFv2LoggingEnabled} from "cdk-nag/lib/rules/waf" |
| 19 | + |
| 20 | +// Nag pack implementing EPS specific rules |
| 21 | +// It implements API gateway must have mutual TLS enabled |
| 22 | +// and rules from https://github.com/cdklabs/cdk-nag/blob/main/RULES.md that are not in aws-solutions pack |
| 23 | + |
| 24 | +export class EpsNagPack extends NagPack { |
| 25 | + constructor(props?: NagPackProps) { |
| 26 | + super(props) |
| 27 | + this.packName = "EpsNagPack" |
| 28 | + } |
| 29 | + |
| 30 | + public visit(node: IConstruct): void { |
| 31 | + if (node instanceof CfnResource) { |
| 32 | + this.applyRule({ |
| 33 | + ruleSuffixOverride: "EPS1", |
| 34 | + info: "API Gateway must does not use mutual TLS.", |
| 35 | + explanation: "All non pull request deployments must enforce mutual TLS on api gateways.", |
| 36 | + level: NagMessageLevel.ERROR, |
| 37 | + rule: ApiGatewayMutualTls, |
| 38 | + node: node |
| 39 | + }) |
| 40 | + this.applyRule({ |
| 41 | + ruleSuffixOverride: "EPS2", |
| 42 | + info: "The Lambda function permission grants public access.", |
| 43 | + explanation: |
| 44 | + "Public access allows anyone on the internet to perform unauthenticated actions on the function.", |
| 45 | + level: NagMessageLevel.ERROR, |
| 46 | + rule: LambdaFunctionPublicAccessProhibited, |
| 47 | + node: node |
| 48 | + }) |
| 49 | + this.applyRule({ |
| 50 | + ruleSuffixOverride: "EPS3", |
| 51 | + info: "The CloudWatch Log Group is not encrypted with an AWS KMS key.", |
| 52 | + explanation: |
| 53 | + "To help protect sensitive data at rest, ensure encryption is enabled for your Amazon CloudWatch Log Groups.", |
| 54 | + level: NagMessageLevel.ERROR, |
| 55 | + rule: CloudWatchLogGroupEncrypted, |
| 56 | + node: node |
| 57 | + }) |
| 58 | + this.applyRule({ |
| 59 | + ruleSuffixOverride: "EPS4", |
| 60 | + info: "The ALB does not have invalid HTTP header dropping enabled.", |
| 61 | + explanation: |
| 62 | + "Ensure that your Application Load Balancers (ALB) are configured to drop http headers.", |
| 63 | + level: NagMessageLevel.ERROR, |
| 64 | + rule: ALBHttpDropInvalidHeaderEnabled, |
| 65 | + node: node |
| 66 | + }) |
| 67 | + this.applyRule({ |
| 68 | + ruleSuffixOverride: "EPS5", |
| 69 | + info: "The WAFv2 web ACL does not have logging enabled.", |
| 70 | + explanation: |
| 71 | + // eslint-disable-next-line max-len |
| 72 | + "AWS WAF logging provides detailed information about the traffic that is analyzed by your web ACL. The logs record the time that AWS WAF received the request from your AWS resource, information about the request, and an action for the rule that each request matched.", |
| 73 | + level: NagMessageLevel.ERROR, |
| 74 | + rule: WAFv2LoggingEnabled, |
| 75 | + node: node |
| 76 | + }) |
| 77 | + |
| 78 | + this.applyRule({ |
| 79 | + ruleSuffixOverride: "EPS6", |
| 80 | + info: "The API does not have access logging enabled.", |
| 81 | + explanation: |
| 82 | + "Enabling access logs helps operators view who accessed an API and how the caller accessed the API.", |
| 83 | + level: NagMessageLevel.ERROR, |
| 84 | + rule: APIGWAccessLogging, |
| 85 | + node: node |
| 86 | + }) |
| 87 | + this.applyRule({ |
| 88 | + ruleSuffixOverride: "EPS7", |
| 89 | + info: "The API Gateway logs are not configured for the JSON format.", |
| 90 | + explanation: |
| 91 | + "JSON Structured logging makes it easier to derive queries to answer questions about your application.", |
| 92 | + level: NagMessageLevel.ERROR, |
| 93 | + rule: APIGWStructuredLogging, |
| 94 | + node: node |
| 95 | + }) |
| 96 | + this.applyRule({ |
| 97 | + ruleSuffixOverride: "EPS8", |
| 98 | + info: "The ELB does not have access logs enabled.", |
| 99 | + explanation: |
| 100 | + "Access logs allow operators to analyze traffic patterns and identify and troubleshoot security issues.", |
| 101 | + level: NagMessageLevel.ERROR, |
| 102 | + rule: ELBLoggingEnabled, |
| 103 | + node: node |
| 104 | + }) |
| 105 | + this.applyRule({ |
| 106 | + ruleSuffixOverride: "EPS9", |
| 107 | + info: "The ELB listener is not configured for secure (HTTPs or SSL) protocols for client communication.", |
| 108 | + explanation: |
| 109 | + // eslint-disable-next-line max-len |
| 110 | + "The SSL protocols enable secure communication by encrypting the communication between the client and the load balancer.", |
| 111 | + level: NagMessageLevel.ERROR, |
| 112 | + rule: ELBTlsHttpsListenersOnly, |
| 113 | + node: node |
| 114 | + }) |
| 115 | + this.applyRule({ |
| 116 | + ruleSuffixOverride: "EPS10", |
| 117 | + info: "The IAM Group, User, or Role contains an inline policy.", |
| 118 | + explanation: |
| 119 | + // eslint-disable-next-line max-len |
| 120 | + "AWS recommends to use managed policies instead of inline policies. The managed policies allow reusability, versioning and rolling back, and delegating permissions management.", |
| 121 | + level: NagMessageLevel.ERROR, |
| 122 | + rule: IAMNoInlinePolicy, |
| 123 | + node: node |
| 124 | + }) |
| 125 | + this.applyRule({ |
| 126 | + ruleSuffixOverride: "EPS11", |
| 127 | + // eslint-disable-next-line max-len |
| 128 | + info: "The IAM policy grants admin access, meaning the policy allows a principal to perform all actions on all resources.", |
| 129 | + explanation: |
| 130 | + // eslint-disable-next-line max-len |
| 131 | + 'AWS Identity and Access Management (IAM) can help you incorporate the principles of least privilege and separation of duties with access permissions and authorizations, restricting policies from containing "Effect": "Allow" with "Action": "*" over "Resource": "*". Allowing users to have more privileges than needed to complete a task may violate the principle of least privilege and separation of duties.', |
| 132 | + level: NagMessageLevel.ERROR, |
| 133 | + rule: IAMPolicyNoStatementsWithAdminAccess, |
| 134 | + node: node |
| 135 | + }) |
| 136 | + this.applyRule({ |
| 137 | + ruleSuffixOverride: "EPS12", |
| 138 | + // eslint-disable-next-line max-len |
| 139 | + info: "The IAM policy grants full access, meaning the policy allows a principal to perform all actions on individual resources.", |
| 140 | + explanation: |
| 141 | + // eslint-disable-next-line max-len |
| 142 | + "Ensure IAM Actions are restricted to only those actions that are needed. Allowing users to have more privileges than needed to complete a task may violate the principle of least privilege and separation of duties.", |
| 143 | + level: NagMessageLevel.ERROR, |
| 144 | + rule: IAMPolicyNoStatementsWithFullAccess, |
| 145 | + node: node |
| 146 | + }) |
| 147 | + this.applyRule({ |
| 148 | + ruleSuffixOverride: "EPS13", |
| 149 | + // eslint-disable-next-line max-len |
| 150 | + info: "The S3 Bucket does not prohibit public read access through its Block Public Access configurations and bucket ACLs.", |
| 151 | + explanation: |
| 152 | + "The management of access should be consistent with the classification of the data.", |
| 153 | + level: NagMessageLevel.ERROR, |
| 154 | + rule: S3BucketPublicReadProhibited, |
| 155 | + node: node |
| 156 | + }) |
| 157 | + this.applyRule({ |
| 158 | + ruleSuffixOverride: "EPS14", |
| 159 | + // eslint-disable-next-line max-len |
| 160 | + info: "The S3 Bucket does not prohibit public write access through its Block Public Access configurations and bucket ACLs.", |
| 161 | + explanation: |
| 162 | + "The management of access should be consistent with the classification of the data.", |
| 163 | + level: NagMessageLevel.ERROR, |
| 164 | + rule: S3BucketPublicWriteProhibited, |
| 165 | + node: node |
| 166 | + }) |
| 167 | + this.applyRule({ |
| 168 | + ruleSuffixOverride: "EPS15", |
| 169 | + info: "The S3 Bucket is not encrypted with a KMS Key by default.", |
| 170 | + explanation: |
| 171 | + // eslint-disable-next-line max-len |
| 172 | + "Ensure that encryption is enabled for your Amazon Simple Storage Service (Amazon S3) buckets. Because sensitive data can exist at rest in an Amazon S3 bucket, enable encryption at rest to help protect that data.", |
| 173 | + level: NagMessageLevel.ERROR, |
| 174 | + rule: S3DefaultEncryptionKMS, |
| 175 | + node: node |
| 176 | + }) |
| 177 | + this.applyRule({ |
| 178 | + ruleSuffixOverride: "EPS16", |
| 179 | + info: "The secret is not encrypted with a KMS Customer managed key.", |
| 180 | + explanation: |
| 181 | + // eslint-disable-next-line max-len |
| 182 | + "To help protect data at rest, ensure encryption with AWS Key Management Service (AWS KMS) is enabled for AWS Secrets Manager secrets. Because sensitive data can exist at rest in Secrets Manager secrets, enable encryption at rest to help protect that data.", |
| 183 | + level: NagMessageLevel.ERROR, |
| 184 | + rule: SecretsManagerUsingKMSKey, |
| 185 | + node: node |
| 186 | + }) |
| 187 | + this.applyRule({ |
| 188 | + ruleSuffixOverride: "EPS17", |
| 189 | + info: "The SNS topic does not have KMS encryption enabled.", |
| 190 | + explanation: |
| 191 | + // eslint-disable-next-line max-len |
| 192 | + "Because sensitive data can exist at rest in published messages, enable encryption at rest to help protect that data.", |
| 193 | + level: NagMessageLevel.ERROR, |
| 194 | + rule: SNSEncryptedKMS, |
| 195 | + node: node |
| 196 | + }) |
| 197 | + this.applyRule({ |
| 198 | + ruleSuffixOverride: "EPS18", |
| 199 | + info: "The VPC's default security group allows inbound or outbound traffic.", |
| 200 | + explanation: |
| 201 | + // eslint-disable-next-line max-len |
| 202 | + "When creating a VPC through CloudFormation, the default security group will always be open. Therefore it is important to always close the default security group after stack creation whenever a VPC is created. Restricting all the traffic on the default security group helps in restricting remote access to your AWS resources.", |
| 203 | + level: NagMessageLevel.ERROR, |
| 204 | + rule: VPCDefaultSecurityGroupClosed, |
| 205 | + node: node |
| 206 | + }) |
| 207 | + this.applyRule({ |
| 208 | + ruleSuffixOverride: "EPS19", |
| 209 | + info: "The VPC does not have an associated Flow Log.", |
| 210 | + explanation: |
| 211 | + // eslint-disable-next-line max-len |
| 212 | + "The VPC flow logs provide detailed records for information about the IP traffic going to and from network interfaces in your Amazon Virtual Private Cloud (Amazon VPC). By default, the flow log record includes values for the different components of the IP flow, including the source, destination, and protocol.", |
| 213 | + level: NagMessageLevel.ERROR, |
| 214 | + rule: VPCFlowLogsEnabled, |
| 215 | + node: node |
| 216 | + }) |
| 217 | + } |
| 218 | + } |
| 219 | +} |
0 commit comments