HITRUST CSF 11.5 - AWS
This page lists all 130 policies in the HITRUST CSF 11.5 pack for AWS, as published in hitrust-aws version 2.6.4.
Policies by control
01.a Access Control Policy — All users shall have a unique identifier for their personal and sole use so that users can be linked to and made responsible for their actions.
- api-gateway-authorization
- iam-role-session-duration
- kms-grant-access-control
- kms-key-policy-access-control
- rds-iam-authentication
01.b User Registration — User registration shall be used for authorizing and enabling access to information systems and services and for revoking access rights.
01.c Privilege Management — The allocation and use of privileges shall be restricted and controlled. The use of privileged utility programs shall be restricted and tightly controlled.
- iam-group-policy-least-privilege
- iam-password-policy-minimum-password-length
- iam-password-policy-prevent-reuse
- iam-policy-least-privilege
- iam-role-least-privilege
- iam-role-policy-least-privilege
- iam-user-policy-least-privilege
- lambda-permission-configure-source-arn
- pubsub-least-privilege-iam
01.d User Password Management — The allocation and management of passwords shall be controlled through a formal process, including requirements for password encryption, storage separate from application system data, and prevention of hardcoded credentials in scripts and configuration.
01.p Secure Log-on Procedures — Log-on procedures shall be designed to minimize the opportunity for unauthorized access. Log-on procedures shall reveal the minimum of information necessary to allow authorized users to recognize that they have accessed the appropriate system.
01.u Limitation of Connection Time — Inactive sessions shall shut down after a defined period of inactivity.
01.v Information Access Restriction — Access to systems and applications shall be restricted in accordance with the access control policy.
06.d Data Protection and Privacy of Covered Information — Covered information shall be protected against unauthorized disclosure, modification and destruction. For the purpose of this control, covered information includes protected health information, cardholder data, and other sensitive information.
- athena-database-disallow-unencrypted-database
- athena-workgroup-disallow-unencrypted-workgroup
- ebs-volume-disallow-unencrypted-volume
- ec2-instance-disallow-unencrypted-block-device
- ec2-instance-disallow-unencrypted-root-block-device
- ec2-launch-configuration-disallow-unencrypted-block-device
- ec2-launch-configuration-disallow-unencrypted-root-block-device
- ec2-launch-template-disallow-unencrypted-block-device
- ecr-repository-disallow-unencrypted-repository
- efs-file-system-disallow-unencrypted-file-system
- eks-cluster-enable-cluster-encryption-config
- kinesis-stream-retention
- rds-cluster-configure-customer-managed-key
- rds-cluster-disallow-unencrypted-storage
- rds-cluster-secure-master-credentials
- rds-instance-configure-customer-managed-key
- rds-instance-disallow-unencrypted-storage
- rds-secure-master-credentials
- s3-bucket-encryption
- s3-bucket-lifecycle
- s3-bucket-macie-access
- s3-bucket-versioning
- sqs-encryption
- sqs-message-retention
09.aa Audit Logging — The organization shall ensure that audit logs are enabled and monitored for sensitive systems.
09.b Change Management — Changes to systems, applications and supporting infrastructure shall be controlled.
09.d Separation of Development, Test, and Operational Environments — Development, testing, and operational environments shall be separated to reduce the risks of unauthorized access or changes to the operational environment.
09.e Service Delivery — Policy ensures compliance with HITRUST security requirements.
09.m Network Controls — Networks shall be managed and controlled in order to protect the organization from threats and to maintain security for the systems and applications using the network, including information in transit.
- api-gateway-waf-association
- appsync-waf-association
- cloudfront-distribution-configure-waf
- cloudfront-waf-association
- database-strict-network-access
- ec2-instance-disallow-public-ip
- ec2-launch-configuration-disallow-public-ip
- ec2-launch-template-disallow-public-ip
- ec2-security-group-disallow-inbound-http-traffic
- eks-cluster-disallow-api-endpoint-public-access
- load-balancer-waf-association
- neptune-clusterinstance-no-public-access
- rds-cluster-instance-disallow-public-access
- rds-instance-disallow-public-access
- rds-private-subnet-validation
- s3-bucket-disallow-public-read
- s3-bucket-public-access-block
- security-group-default-deny
- security-group-strict
- subnet-multi-az
- waf-association-validation
09.z Publicly Available Information — Publicly available information shall be protected against unauthorized modification or deletion.
- api-gateway-access-logging
- api-gateway-v2-access-logging
- api-gateway-v2-stage-configure-access-logging
- api-gateway-v2-stage-enable-access-logging
- centralized-os-app-logging
- cloudfront-distribution-configure-access-logging
- cloudfront-distribution-enable-access-logging
- elb-load-balancer-configure-access-logging
- rds-audit-logging
- vpc-subnet-flow-logs
10.c Control of Internal Processing — Input data validation and output controls shall be applied to safeguard against errors, loss, unauthorized modification or misuse of information in applications.
10.d Message Integrity — Integrity shall be applied to messages using cryptography or digital signatures, where deemed appropriate.
10.e Output Data Validation — Output data from applications shall be validated to ensure that the processing of stored information is correct and appropriate to the circumstances.
10.f Policy on the Use of Cryptographic Controls — Cryptographic controls shall be used in compliance with all relevant agreements, legislation and regulations, and risk assessments shall consider the organization
- api-gateway-domain-name-configure-security-policy
- api-gateway-v2-domain-name-configure-domain-name-security-policy
- api-gateway-v2-domain-name-enable-domain-name-configuration
- appflow-connector-profile-configure-customer-managed-key
- appflow-flow-configure-customer-managed-key
- athena-database-configure-customer-managed-key
- athena-workgroup-configure-customer-managed-key
- cloudfront-distribution-configure-secure-tls
- cloudfront-distribution-configure-secure-tls-to-origin
- cloudfront-distribution-disallow-unencrypted-traffic
- cloudfront-distribution-enable-tls-to-origin
- ebs-volume-configure-customer-managed-key
- ec2-launch-template-configure-customer-managed-key
- ecr-repository-configure-customer-managed-key
- efs-file-system-configure-customer-managed-key
- elb-load-balancer-disallow-unencrypted-traffic
- kms-key-creation
- kms-key-deletion-lifecycle
- kms-key-enable-key-rotation
- rds-clusterinstance-ssl-encryption
- rds-instance-ssl-encryption
- secrets-manager-secret-configure-customer-managed-key
- security-group-ssh-rdp
10.h Control of Operational Software — The installation of software on operational systems shall be controlled.
- athena-workgroup-enforce-configuration
- ecr-repository-disallow-mutable-image
- lambda-runtime-restrictions
10.k Change Control Procedures — Changes to systems within the development lifecycle shall be controlled by the use of formal change control procedures.
- docdb-clusterinstance-managed-service-patching
- neptune-clusterinstance-managed-service-patching
- rds-clusterinstance-managed-service-patching
- rds-instance-managed-service-patching
10.m Control of Technical Vulnerabilities — Information about technical vulnerabilities of information systems being used shall be obtained in a timely fashion, the organization
- anti-malware-edr
- ecr-image-scanning
- ecr-repository-configure-image-scan
- ecr-repository-enable-image-scan
- ecs-task-definition-image-scanning
12.a Including Information Security in the Business Continuity Management — Information security shall be a central part of the organization
- elb-load-balancer-configure-multi-availability-zone
- elb-load-balancer-enable-health-check
- kinesis-event-source-mapping-dlq
- rds-cluster-disallow-single-availability-zone
- rds-cluster-enable-backup-retention
- rds-instance-enable-backup-retention
- rds-instance-high-availability
- s3-bucket-replication
- sns-subscription-dead-letter-queue
- sqs-dead-letter-queue
Policy details
anti-malware-edr
Severity: high · Enforcement: advisory
Ensures EC2 instances have anti-malware/EDR agents deployed
- 10.m Control of Technical Vulnerabilities — Information about technical vulnerabilities of information systems being used shall be obtained in a timely fashion, the organization
Remediation
Fix: Deploy Anti-Malware/EDR Agent via User Data
Include anti-malware or EDR agent installation commands in the instance’s userData:
const instance = new aws.ec2.Instance("protected-instance", {
instanceType: "t3.medium",
ami: "ami-0c55b159cbfafe1f0",
userData: "#!/bin/bash\nyum install -y amazon-ssm-agent\nsystemctl enable amazon-ssm-agent\nsystemctl start amazon-ssm-agent", // Install SSM agent
subnetId: subnet.id,
});
api-gateway-access-logging
Severity: medium · Enforcement: advisory
Ensures API Gateway stages have access logging enabled
- 09.z Publicly Available Information — Publicly available information shall be protected against unauthorized modification or deletion.
Remediation
Fix: Enable Access Logging for API Gateway Stage
Configure the accessLogSettings property with a CloudWatch Log Group ARN to enable comprehensive audit logging:
const logGroup = new aws.cloudwatch.LogGroup("api-logs", {
retentionInDays: 30,
});
const stage = new aws.apigateway.Stage("my-stage", {
restApi: api.id,
stageName: "prod",
deployment: deployment.id,
accessLogSettings: { // Enable access logging
destinationArn: logGroup.arn, // Specify CloudWatch Log Group
format: "$context.requestId",
},
});
api-gateway-authorization
Severity: high · Enforcement: advisory
Ensures API Gateway methods use strong authorization instead of NONE
- 01.a Access Control Policy — All users shall have a unique identifier for their personal and sole use so that users can be linked to and made responsible for their actions.
Remediation
Fix: Enable Strong Authorization for API Gateway Method
Set the authorization property to a strong authorization type (AWS_IAM, COGNITO_USER_POOLS, CUSTOM, or JWT) instead of “NONE”:
const method = new aws.apigateway.Method("my-method", {
restApi: api.id,
resourceId: resource.id,
httpMethod: "GET",
authorization: "AWS_IAM", // Use strong authorization instead of "NONE"
// For CUSTOM authorization, also specify the authorizer:
// authorizerId: authorizer.id,
});
api-gateway-domain-name-configure-security-policy
Severity: high · Enforcement: advisory
Checks that ApiGateway Domain Name Security Policy uses secure/modern TLS encryption.
- 10.f Policy on the Use of Cryptographic Controls — Cryptographic controls shall be used in compliance with all relevant agreements, legislation and regulations, and risk assessments shall consider the organization
Remediation
Fix: Configure TLS 1.2 Security Policy
Set the securityPolicy to “TLS_1_2” to ensure the API Gateway domain name uses secure TLS encryption:
const domainName = new apigateway.DomainName("my-domain", {
domainName: "api.example.com",
certificateArn: cert.arn,
securityPolicy: "TLS_1_2", // Use TLS 1.2 for secure encryption
});
api-gateway-v2-access-logging
Severity: medium · Enforcement: advisory
Ensures API Gateway V2 stages have access logging enabled
- 09.z Publicly Available Information — Publicly available information shall be protected against unauthorized modification or deletion.
Remediation
Fix: Enable Access Logging for API Gateway V2 Stage
Configure the accessLogSettings property with a CloudWatch Log Group ARN to enable comprehensive audit logging:
const logGroup = new aws.cloudwatch.LogGroup("api-v2-logs", {
retentionInDays: 30,
});
const stage = new aws.apigatewayv2.Stage("my-stage", {
apiId: api.id,
name: "prod",
accessLogSettings: { // Enable access logging
destinationArn: logGroup.arn, // Specify CloudWatch Log Group
format: "$context.requestId",
},
});
api-gateway-v2-domain-name-configure-domain-name-security-policy
Severity: high · Enforcement: advisory
Checks that any ApiGatewayV2 Domain Name Security Policy uses secure/modern TLS encryption.
- 10.f Policy on the Use of Cryptographic Controls — Cryptographic controls shall be used in compliance with all relevant agreements, legislation and regulations, and risk assessments shall consider the organization
Remediation
Fix: Set TLS 1.2 Security Policy for API Gateway V2 Domain Name
Configure the securityPolicy to “TLS_1_2” in the domain name configuration to enforce modern TLS encryption:
const domainName = new aws.apigatewayv2.DomainName("my-domain", {
domainName: "api.example.com",
domainNameConfiguration: {
certificateArn: certificate.arn,
endpointType: "REGIONAL",
securityPolicy: "TLS_1_2", // Use TLS 1.2 for secure encryption
},
});
api-gateway-v2-domain-name-enable-domain-name-configuration
Severity: high · Enforcement: advisory
Checks that any ApiGatewayV2 Domain Name Configuration is enabled.
- 10.f Policy on the Use of Cryptographic Controls — Cryptographic controls shall be used in compliance with all relevant agreements, legislation and regulations, and risk assessments shall consider the organization
Remediation
Fix: Configure Domain Name Configuration for API Gateway V2
Add the domainNameConfiguration property with the required TLS settings to enable secure custom domain name configuration:
const domainName = new apigatewayv2.DomainName("my-domain", {
domainName: "api.example.com",
domainNameConfiguration: { // Enable domain name configuration
certificateArn: certificate.arn,
endpointType: "REGIONAL",
securityPolicy: "TLS_1_2",
},
});
api-gateway-v2-stage-configure-access-logging
Severity: medium · Enforcement: advisory
Checks that any ApiGatewayV2 Stages have access logging configured.
- 09.z Publicly Available Information — Publicly available information shall be protected against unauthorized modification or deletion.
Remediation
Fix: Configure Access Logging for API Gateway V2 Stage
Set the accessLogSettings property with both destinationArn (pointing to a CloudWatch Log Group) and format (defining the log format):
const logGroup = new aws.cloudwatch.LogGroup("api-logs", {
retentionInDays: 30,
});
const stage = new aws.apigatewayv2.Stage("api-stage", {
apiId: api.id,
name: "prod",
accessLogSettings: { // Configure access logging
destinationArn: logGroup.arn, // CloudWatch Log Group ARN
format: JSON.stringify({ // Log format specification
requestId: "$context.requestId",
ip: "$context.identity.sourceIp",
requestTime: "$context.requestTime",
httpMethod: "$context.httpMethod",
routeKey: "$context.routeKey",
status: "$context.status",
}),
},
});
api-gateway-v2-stage-enable-access-logging
Severity: medium · Enforcement: advisory
Checks that any ApiGatewayV2 Stages have access logging enabled.
- 09.z Publicly Available Information — Publicly available information shall be protected against unauthorized modification or deletion.
Remediation
Fix: Enable Access Logging for API Gateway V2 Stage
Configure the accessLogSettings property to enable access logging by specifying a CloudWatch Logs destination ARN:
const stage = new aws.apigatewayv2.Stage("my-stage", {
apiId: api.id,
name: "prod",
accessLogSettings: { // Enable access logging
destinationArn: logGroup.arn,
format: "$context.requestId",
},
});
api-gateway-waf-association
Severity: critical · Enforcement: advisory
Ensures public-facing API Gateways have WAF associations
- 09.m Network Controls — Networks shall be managed and controlled in order to protect the organization from threats and to maintain security for the systems and applications using the network, including information in transit.
Remediation
Fix: Associate WAF Web ACL with API Gateway Stage
Create a WAF Web ACL association for your API Gateway stage:
// Create a WAF Web ACL association for the API Gateway stage
const wafAssociation = new aws.wafv2.WebAclAssociation("api-waf-association", {
resourceArn: pulumi.interpolate`arn:aws:apigateway:${region}::/restapis/${restApi.id}/stages/${stage.stageName}`, // Stage ARN
webAclArn: webAcl.arn, // Reference the WAF Web ACL ARN
});
appflow-connector-profile-configure-customer-managed-key
Severity: low · Enforcement: advisory
Check that AppFlow ConnectorProfile uses a customer-managed KMS key.
- 10.f Policy on the Use of Cryptographic Controls — Cryptographic controls shall be used in compliance with all relevant agreements, legislation and regulations, and risk assessments shall consider the organization
Remediation
Fix: Configure Customer-Managed KMS Key for AppFlow Connector Profile
Set the kmsArn property to reference a customer-managed KMS key:
const connectorProfile = new aws.appflow.ConnectorProfile("my-connector-profile", {
connectorProfileName: "salesforce-connector",
connectorType: "Salesforce",
connectionMode: "Public",
kmsArn: kmsKey.arn, // Specify customer-managed KMS key ARN
connectorProfileConfig: {
connectorProfileCredentials: {
salesforce: {
accessToken: salesforceAccessToken,
refreshToken: salesforceRefreshToken,
oauthRequest: {
authCode: authCode,
redirectUri: redirectUri,
},
},
},
},
});
appflow-flow-configure-customer-managed-key
Severity: low · Enforcement: advisory
Check that AppFlow Flow uses a customer-managed KMS key.
- 10.f Policy on the Use of Cryptographic Controls — Cryptographic controls shall be used in compliance with all relevant agreements, legislation and regulations, and risk assessments shall consider the organization
Remediation
Fix: Configure Customer-Managed KMS Key for AppFlow Flow
Set the kmsArn property to specify a customer-managed KMS key for encrypting the AppFlow Flow:
const flow = new aws.appflow.Flow("my-flow", {
name: "my-appflow",
kmsArn: kmsKey.arn, // Configure customer-managed KMS key
sourceFlowConfig: {
connectorType: "S3",
sourceConnectorProperties: {
s3: {
bucketName: sourceBucket.bucket,
bucketPrefix: "data/",
},
},
},
destinationFlowConfigs: [{
connectorType: "S3",
destinationConnectorProperties: {
s3: {
bucketName: destBucket.bucket,
},
},
}],
tasks: [{
taskType: "Map_all",
sourceFields: [],
connectorOperator: {
s3: "NO_OP",
},
}],
triggerConfig: {
triggerType: "OnDemand",
},
});
appsync-waf-association
Severity: critical · Enforcement: advisory
Ensures public-facing AppSync GraphQL APIs have WAF associations
- 09.m Network Controls — Networks shall be managed and controlled in order to protect the organization from threats and to maintain security for the systems and applications using the network, including information in transit.
Remediation
Fix: Associate WAF Web ACL with AppSync GraphQL API
Create a WAF Web ACL association to protect your AppSync GraphQL API:
// Create a WAF Web ACL association for the AppSync GraphQL API
const wafAssociation = new aws.wafv2.WebAclAssociation("appsync-waf-association", {
resourceArn: graphqlApi.arn, // Reference the GraphQL API ARN
webAclArn: webAcl.arn, // Reference the WAF Web ACL ARN
});
athena-database-configure-customer-managed-key
Severity: low · Enforcement: advisory
Checks that Athena Databases storage uses a customer-managed-key.
- 10.f Policy on the Use of Cryptographic Controls — Cryptographic controls shall be used in compliance with all relevant agreements, legislation and regulations, and risk assessments shall consider the organization
Remediation
Fix: Configure Customer-Managed Key Encryption for Athena Database
Set the encryptionOption to “SSE_KMS” and specify a KMS key ARN in the encryptionConfiguration:
const athenaDatabase = new aws.athena.Database("my-database", {
name: "my_database",
bucket: myBucket.id,
encryptionConfiguration: {
encryptionOption: "SSE_KMS", // Use customer-managed KMS key
kmsKey: myKmsKey.arn, // Specify the KMS key ARN
},
});
athena-database-disallow-unencrypted-database
Severity: high · Enforcement: advisory
Checks that Athena Databases storage is encrypted.
- 06.d Data Protection and Privacy of Covered Information — Covered information shall be protected against unauthorized disclosure, modification and destruction. For the purpose of this control, covered information includes protected health information, cardholder data, and other sensitive information.
Remediation
Fix: Enable Encryption for Athena Database
Configure the encryptionConfiguration property to encrypt query results and data catalog:
const athenaDatabase = new aws.athena.Database("my-database", {
name: "my_database",
bucket: dataBucket.id,
encryptionConfiguration: { // Enable encryption
encryptionOption: "SSE_S3", // Use SSE-S3, SSE-KMS, or CSE-KMS
},
});
athena-workgroup-configure-customer-managed-key
Severity: low · Enforcement: advisory
Checks that Athena Workgroups use a customer-managed-key.
- 10.f Policy on the Use of Cryptographic Controls — Cryptographic controls shall be used in compliance with all relevant agreements, legislation and regulations, and risk assessments shall consider the organization
Remediation
Fix: Configure Customer-Managed Key Encryption for Athena Workgroup
Set the encryptionOption to “SSE_KMS” in the workgroup’s result configuration to enable customer-managed key encryption:
const workgroup = new athena.Workgroup("my-workgroup", {
name: "my-workgroup",
configuration: {
resultConfiguration: {
outputLocation: "s3://my-bucket/query-results/",
encryptionConfiguration: {
encryptionOption: "SSE_KMS", // Enable customer-managed key encryption
kmsKey: kmsKey.arn, // Optional: specify a specific KMS key
},
},
},
});
athena-workgroup-disallow-unencrypted-workgroup
Severity: high · Enforcement: advisory
Checks that Athena Workgroups are encrypted.
- 06.d Data Protection and Privacy of Covered Information — Covered information shall be protected against unauthorized disclosure, modification and destruction. For the purpose of this control, covered information includes protected health information, cardholder data, and other sensitive information.
Remediation
Fix: Enable Encryption for Athena Workgroup Query Results
Configure encryption for query results by adding an encryptionConfiguration within the workgroup’s resultConfiguration:
const workgroup = new athena.Workgroup("my-workgroup", {
name: "example-workgroup",
configuration: {
resultConfiguration: {
outputLocation: "s3://my-query-results-bucket/",
encryptionConfiguration: { // Add encryption configuration
encryptionOption: "SSE_KMS", // or "SSE_S3" or "CSE_KMS"
kmsKey: kmsKey.arn, // Required when using SSE_KMS or CSE_KMS
},
},
},
});
athena-workgroup-enforce-configuration
Severity: high · Enforcement: advisory
Checks that Athena Workgroups enforce their configuration to their clients.
- 10.h Control of Operational Software — The installation of software on operational systems shall be controlled.
Remediation
Fix: Enable Workgroup Configuration Enforcement
Set enforceWorkgroupConfiguration to true in the Athena Workgroup configuration to ensure clients use the workgroup’s settings:
const workgroup = new athena.Workgroup("my-workgroup", {
name: "my-workgroup",
configuration: {
enforceWorkgroupConfiguration: true, // Enforce workgroup configuration on clients
resultConfiguration: {
outputLocation: "s3://my-query-results/",
},
},
});
centralized-os-app-logging
Severity: medium · Enforcement: advisory
Ensures EC2 instances have logging agents configured to forward OS/application logs to central system
- 09.z Publicly Available Information — Publicly available information shall be protected against unauthorized modification or deletion.
Remediation
Fix: Configure Logging Agent in EC2 Instance User Data
Add a logging agent installation and configuration script to the instance’s userData to forward OS and application logs to a central logging system:
const instance = new aws.ec2.Instance("web-server", {
ami: "ami-0c55b159cbfafe1f0",
instanceType: "t3.micro",
userData: `#!/bin/bash
##### Install and configure CloudWatch Agent for centralized logging
wget https://s3.amazonaws.com/amazoncloudwatch-agent/amazon_linux/amd64/latest/amazon-cloudwatch-agent.rpm
rpm -U ./amazon-cloudwatch-agent.rpm
##### Configure agent to forward logs
/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl \
-a fetch-config -m ec2 -s -c ssm:AmazonCloudWatch-Config
`, // Add logging agent to userData
iamInstanceProfile: instanceProfile.name,
subnetId: subnet.id,
});
cloudfront-distribution-configure-access-logging
Severity: medium · Enforcement: advisory
Checks that any CloudFront distributions have access logging configured.
- 09.z Publicly Available Information — Publicly available information shall be protected against unauthorized modification or deletion.
Remediation
Fix: Configure CloudFront Access Logging
Configure the loggingConfig property with an S3 bucket to store CloudFront access logs:
const distribution = new cloudfront.Distribution("my-distribution", {
enabled: true,
loggingConfig: {
bucket: logBucket.bucketDomainName, // S3 bucket for access logs
includeCookies: false,
prefix: "cloudfront-logs/",
},
// ... other distribution configuration
});
cloudfront-distribution-configure-secure-tls
Severity: high · Enforcement: advisory
Checks that CloudFront distributions uses secure/modern TLS encryption.
- 10.f Policy on the Use of Cryptographic Controls — Cryptographic controls shall be used in compliance with all relevant agreements, legislation and regulations, and risk assessments shall consider the organization
Remediation
Fix: Configure Secure TLS Protocol Version for CloudFront
Set the minimumProtocolVersion to “TLSv1.2_2021” in the viewer certificate configuration:
const distribution = new cloudfront.Distribution("my-distribution", {
enabled: true,
origins: [/* ... */],
defaultCacheBehavior: {/* ... */},
viewerCertificate: {
cloudfrontDefaultCertificate: true,
minimumProtocolVersion: "TLSv1.2_2021", // Use secure TLS 1.2 with modern cipher suites
},
});
cloudfront-distribution-configure-secure-tls-to-origin
Severity: high · Enforcement: advisory
Checks that CloudFront distributions communicate with custom origins using TLS 1.2 encryption only.
- 10.f Policy on the Use of Cryptographic Controls — Cryptographic controls shall be used in compliance with all relevant agreements, legislation and regulations, and risk assessments shall consider the organization
Remediation
Fix: Configure TLS 1.2 for CloudFront Custom Origins
Set the originSslProtocols in your custom origin configuration to only allow TLS 1.2:
const distribution = new cloudfront.Distribution("my-distribution", {
enabled: true,
origins: [{
domainName: "my-origin.example.com",
originId: "myCustomOrigin",
customOriginConfig: {
httpPort: 80,
httpsPort: 443,
originProtocolPolicy: "https-only",
originSslProtocols: ["TLSv1.2"], // Only allow TLS 1.2
},
}],
defaultCacheBehavior: {
targetOriginId: "myCustomOrigin",
viewerProtocolPolicy: "redirect-to-https",
allowedMethods: ["GET", "HEAD"],
cachedMethods: ["GET", "HEAD"],
forwardedValues: {
queryString: false,
cookies: { forward: "none" },
},
},
});
cloudfront-distribution-configure-waf
Severity: high · Enforcement: advisory
Checks that any CloudFront distribution has a WAF ACL associated.
- 09.m Network Controls — Networks shall be managed and controlled in order to protect the organization from threats and to maintain security for the systems and applications using the network, including information in transit.
Remediation
Fix: Associate WAF Web ACL with CloudFront Distribution
Set the webAclId property to attach a WAF Web ACL to your CloudFront distribution:
const distribution = new aws.cloudfront.Distribution("my-distribution", {
enabled: true,
webAclId: webAcl.arn, // Associate WAF Web ACL for protection
origins: [{
domainName: bucket.bucketRegionalDomainName,
originId: "myS3Origin",
}],
defaultCacheBehavior: {
targetOriginId: "myS3Origin",
viewerProtocolPolicy: "redirect-to-https",
allowedMethods: ["GET", "HEAD"],
cachedMethods: ["GET", "HEAD"],
forwardedValues: {
queryString: false,
cookies: { forward: "none" },
},
},
});
cloudfront-distribution-disallow-unencrypted-traffic
Severity: critical · Enforcement: advisory
Checks that CloudFront distributions only allow encypted ingress traffic.
- 10.f Policy on the Use of Cryptographic Controls — Cryptographic controls shall be used in compliance with all relevant agreements, legislation and regulations, and risk assessments shall consider the organization
Remediation
Fix: Enforce HTTPS for CloudFront Distribution
Set the viewerProtocolPolicy to “redirect-to-https” or “https-only” for both default and ordered cache behaviors to ensure all traffic is encrypted:
const distribution = new cloudfront.Distribution("my-distribution", {
enabled: true,
defaultCacheBehavior: {
targetOriginId: origin.originId,
viewerProtocolPolicy: "redirect-to-https", // Enforce HTTPS for all traffic
allowedMethods: ["GET", "HEAD"],
cachedMethods: ["GET", "HEAD"],
forwardedValues: {
queryString: false,
cookies: { forward: "none" },
},
},
orderedCacheBehaviors: [{
pathPattern: "/api/*",
targetOriginId: origin.originId,
viewerProtocolPolicy: "https-only", // Enforce HTTPS-only for API paths
allowedMethods: ["GET", "HEAD", "OPTIONS"],
cachedMethods: ["GET", "HEAD"],
forwardedValues: {
queryString: true,
cookies: { forward: "none" },
},
}],
origins: [origin],
viewerCertificate: {
cloudfrontDefaultCertificate: true,
},
});
cloudfront-distribution-enable-access-logging
Severity: medium · Enforcement: advisory
Checks that any CloudFront distributions have access logging enabled.
- 09.z Publicly Available Information — Publicly available information shall be protected against unauthorized modification or deletion.
Remediation
Fix: Enable Access Logging for CloudFront Distribution
Configure the loggingConfig property to enable access logging and specify an S3 bucket to store the logs:
const distribution = new aws.cloudfront.Distribution("my-distribution", {
enabled: true,
origins: [{
domainName: bucket.bucketRegionalDomainName,
originId: "myS3Origin",
}],
defaultCacheBehavior: {
targetOriginId: "myS3Origin",
viewerProtocolPolicy: "redirect-to-https",
allowedMethods: ["GET", "HEAD"],
cachedMethods: ["GET", "HEAD"],
forwardedValues: {
queryString: false,
cookies: { forward: "none" },
},
},
loggingConfig: { // Enable access logging
bucket: logBucket.bucketDomainName, // S3 bucket for logs
includeCookies: false,
prefix: "cloudfront-logs/",
},
restrictions: {
geoRestriction: {
restrictionType: "none",
},
},
viewerCertificate: {
cloudfrontDefaultCertificate: true,
},
});
cloudfront-distribution-enable-tls-to-origin
Severity: critical · Enforcement: advisory
Checks that CloudFront distributions communicate with custom origins using TLS encryption.
- 10.f Policy on the Use of Cryptographic Controls — Cryptographic controls shall be used in compliance with all relevant agreements, legislation and regulations, and risk assessments shall consider the organization
Remediation
Fix: Enable HTTPS-Only Protocol for CloudFront Custom Origins
Set the originProtocolPolicy to “https-only” in the customOriginConfig for all custom origins to ensure encrypted communication:
const distribution = new cloudfront.Distribution("my-distribution", {
enabled: true,
origins: [{
domainName: "my-custom-origin.example.com",
originId: "my-custom-origin",
customOriginConfig: {
httpPort: 80,
httpsPort: 443,
originProtocolPolicy: "https-only", // Enforce TLS encryption to origin
originSslProtocols: ["TLSv1.2"],
},
}],
defaultCacheBehavior: {
targetOriginId: "my-custom-origin",
viewerProtocolPolicy: "redirect-to-https",
allowedMethods: ["GET", "HEAD"],
cachedMethods: ["GET", "HEAD"],
forwardedValues: {
queryString: false,
cookies: { forward: "none" },
},
},
});
cloudfront-waf-association
Severity: critical · Enforcement: advisory
Ensures CloudFront distributions have WAF associations
- 09.m Network Controls — Networks shall be managed and controlled in order to protect the organization from threats and to maintain security for the systems and applications using the network, including information in transit.
Remediation
Fix: Associate WAF Web ACL with CloudFront Distribution
Set the webAclId property to associate your CloudFront distribution with a WAF Web ACL:
const distribution = new aws.cloudfront.Distribution("my-distribution", {
enabled: true,
webAclId: webAcl.arn, // Associate the WAF Web ACL with the distribution
origins: [{
domainName: bucket.bucketRegionalDomainName,
originId: "S3Origin",
}],
defaultCacheBehavior: {
targetOriginId: "S3Origin",
viewerProtocolPolicy: "redirect-to-https",
allowedMethods: ["GET", "HEAD"],
cachedMethods: ["GET", "HEAD"],
forwardedValues: {
queryString: false,
cookies: { forward: "none" },
},
},
});
database-strict-network-access
Severity: critical · Enforcement: advisory
Ensures RDS instances have strict network access controls
- 09.m Network Controls — Networks shall be managed and controlled in order to protect the organization from threats and to maintain security for the systems and applications using the network, including information in transit.
Remediation
Fix: Configure Strict Network Access for Database Resources
Restrict database access to specific internal sources only. Never allow public access (0.0.0.0/0) to database ports.
// Create a security group with restricted ingress
const dbSecurityGroup = new aws.ec2.SecurityGroup("db-sg", {
vpcId: vpc.id,
ingress: [{
protocol: "tcp",
fromPort: 3306,
toPort: 3306,
cidrBlocks: ["10.0.0.0/16"], // Restrict to internal VPC CIDR only
}],
});
// Associate security group with RDS instance
const db = new aws.rds.Instance("my-db", {
engine: "mysql",
instanceClass: "db.t3.micro",
allocatedStorage: 20,
vpcSecurityGroupIds: [dbSecurityGroup.id], // Attach security group
dbSubnetGroupName: dbSubnetGroup.name,
});
// Ensure subnet group has at least 2 subnets
const dbSubnetGroup = new aws.rds.SubnetGroup("db-subnet-group", {
subnetIds: [privateSubnet1.id, privateSubnet2.id], // Minimum 2 subnets
});
docdb-clusterinstance-managed-service-patching
Severity: medium · Enforcement: advisory
Ensures DocumentDB cluster instances have automated minor version upgrades enabled
- 10.k Change Control Procedures — Changes to systems within the development lifecycle shall be controlled by the use of formal change control procedures.
Remediation
Fix: Enable Automatic Minor Version Upgrades for DocumentDB Cluster Instance
Set the autoMinorVersionUpgrade property to true to enable automated patching for managed service security updates:
const clusterInstance = new aws.docdb.ClusterInstance("my-cluster-instance", {
clusterIdentifier: cluster.id,
instanceClass: "db.r5.large",
autoMinorVersionUpgrade: true, // Enable automatic minor version upgrades
});
dynamodb-streams-enabled
Severity: medium · Enforcement: advisory
Enforces that all DynamoDB tables have Stream settings enabled to capture all changes
- 10.c Control of Internal Processing — Input data validation and output controls shall be applied to safeguard against errors, loss, unauthorized modification or misuse of information in applications.
Remediation
Fix: Enable DynamoDB Streams
Set the streamEnabled property to true on your DynamoDB table:
const table = new aws.dynamodb.Table("my-table", {
name: "my-table",
attributes: [
{ name: "id", type: "S" },
],
hashKey: "id",
streamEnabled: true, // Enable DynamoDB Streams
billingMode: "PAY_PER_REQUEST",
});
ebs-volume-configure-customer-managed-key
Severity: low · Enforcement: advisory
Check that encrypted EBS volumes use a customer-managed KMS key.
- 10.f Policy on the Use of Cryptographic Controls — Cryptographic controls shall be used in compliance with all relevant agreements, legislation and regulations, and risk assessments shall consider the organization
Remediation
Fix: Configure Customer-Managed KMS Key for EBS Volume
Specify a customer-managed KMS key using the kmsKeyId property when creating an encrypted EBS volume:
const volume = new aws.ebs.Volume("my-volume", {
availabilityZone: "us-west-2a",
size: 100,
encrypted: true,
kmsKeyId: customerKey.arn, // Use customer-managed KMS key instead of default AWS-managed key
});
ebs-volume-disallow-unencrypted-volume
Severity: high · Enforcement: advisory
Checks that EBS volumes are encrypted.
- 06.d Data Protection and Privacy of Covered Information — Covered information shall be protected against unauthorized disclosure, modification and destruction. For the purpose of this control, covered information includes protected health information, cardholder data, and other sensitive information.
Remediation
Fix: Enable EBS Volume Encryption
Set the encrypted property to true on the EBS volume:
const volume = new aws.ebs.Volume("my-volume", {
availabilityZone: "us-west-2a",
size: 100,
encrypted: true, // Enable encryption for the volume
});
ec2-instance-disallow-public-ip
Severity: high · Enforcement: advisory
Checks that EC2 instances do not have a public IP address.
- 09.m Network Controls — Networks shall be managed and controlled in order to protect the organization from threats and to maintain security for the systems and applications using the network, including information in transit.
Remediation
Fix: Disable Public IP Address Assignment
Set associatePublicIpAddress to false to prevent the instance from receiving a public IP address:
const instance = new ec2.Instance("my-instance", {
instanceType: "t3.micro",
ami: "ami-12345678",
associatePublicIpAddress: false, // Disable public IP assignment
subnetId: privateSubnet.id,
});
ec2-instance-disallow-unencrypted-block-device
Severity: high · Enforcement: advisory
Checks that EC2 instances do not have unencrypted block devices.
- 06.d Data Protection and Privacy of Covered Information — Covered information shall be protected against unauthorized disclosure, modification and destruction. For the purpose of this control, covered information includes protected health information, cardholder data, and other sensitive information.
Remediation
Fix: Enable Encryption for EBS Block Devices
Set the encrypted property to true for all EBS block devices attached to EC2 instances:
const instance = new aws.ec2.Instance("my-instance", {
ami: "ami-12345678",
instanceType: "t3.micro",
ebsBlockDevices: [{
deviceName: "/dev/sdf",
volumeSize: 20,
encrypted: true, // Enable encryption for the EBS volume
}],
});
ec2-instance-disallow-unencrypted-root-block-device
Severity: high · Enforcement: advisory
Checks that EC2 instances does not have unencrypted root volumes.
- 06.d Data Protection and Privacy of Covered Information — Covered information shall be protected against unauthorized disclosure, modification and destruction. For the purpose of this control, covered information includes protected health information, cardholder data, and other sensitive information.
Remediation
Fix: Enable Encryption for Root Block Device
Set the encrypted property to true in the rootBlockDevice configuration:
const instance = new aws.ec2.Instance("my-instance", {
instanceType: "t3.micro",
ami: "ami-12345678",
rootBlockDevice: {
encrypted: true, // Enable encryption for root volume
},
});
ec2-launch-configuration-disallow-public-ip
Severity: high · Enforcement: advisory
Checks that EC2 Launch Configurations do not have a public IP address.
- 09.m Network Controls — Networks shall be managed and controlled in order to protect the organization from threats and to maintain security for the systems and applications using the network, including information in transit.
Remediation
Fix: Disable Public IP Assignment for Launch Configuration
Set the associatePublicIpAddress property to false to prevent instances from receiving public IP addresses:
const launchConfig = new aws.ec2.LaunchConfiguration("my-launch-config", {
imageId: "ami-12345678",
instanceType: "t3.micro",
associatePublicIpAddress: false, // Disable public IP assignment
securityGroups: [securityGroup.id],
});
ec2-launch-configuration-disallow-unencrypted-block-device
Severity: high · Enforcement: advisory
Checks that EC2 Launch Configurations do not have unencrypted block devices.
- 06.d Data Protection and Privacy of Covered Information — Covered information shall be protected against unauthorized disclosure, modification and destruction. For the purpose of this control, covered information includes protected health information, cardholder data, and other sensitive information.
Remediation
Fix: Enable EBS Block Device Encryption
Set the encrypted property to true for all EBS block devices in the Launch Configuration:
const launchConfig = new aws.ec2.LaunchConfiguration("my-launch-config", {
imageId: "ami-12345678",
instanceType: "t3.medium",
ebsBlockDevices: [{
deviceName: "/dev/sdf",
volumeSize: 100,
encrypted: true, // Enable encryption for all EBS block devices
}],
});
ec2-launch-configuration-disallow-unencrypted-root-block-device
Severity: high · Enforcement: advisory
Checks that EC2 launch configuration do not have unencrypted root block device.
- 06.d Data Protection and Privacy of Covered Information — Covered information shall be protected against unauthorized disclosure, modification and destruction. For the purpose of this control, covered information includes protected health information, cardholder data, and other sensitive information.
Remediation
Fix: Enable Encryption for Root Block Device
Set the encrypted property to true in the rootBlockDevice configuration:
const launchConfig = new ec2.LaunchConfiguration("my-launch-config", {
imageId: "ami-0c55b159cbfafe1f0",
instanceType: "t2.micro",
rootBlockDevice: {
encrypted: true, // Enable encryption for root block device
},
});
ec2-launch-template-configure-customer-managed-key
Severity: low · Enforcement: advisory
Check that encrypted EBS volume uses a customer-managed KMS key.
- 10.f Policy on the Use of Cryptographic Controls — Cryptographic controls shall be used in compliance with all relevant agreements, legislation and regulations, and risk assessments shall consider the organization
Remediation
Fix: Specify Customer-Managed KMS Key for Encrypted EBS Volumes
Add the kmsKeyId property to encrypted EBS block device mappings in your Launch Template:
const launchTemplate = new aws.ec2.LaunchTemplate("my-template", {
blockDeviceMappings: [{
ebs: {
encrypted: "true",
kmsKeyId: customerManagedKey.id, // Specify customer-managed KMS key
volumeSize: 20,
},
}],
});
ec2-launch-template-disallow-public-ip
Severity: high · Enforcement: advisory
Checks that EC2 Launch Templates do not have public IP addresses.
- 09.m Network Controls — Networks shall be managed and controlled in order to protect the organization from threats and to maintain security for the systems and applications using the network, including information in transit.
Remediation
Fix: Disable Public IP Assignment in Launch Template
Set associatePublicIpAddress to false (or omit it) in the network interface configuration to prevent instances from receiving public IP addresses:
const launchTemplate = new aws.ec2.LaunchTemplate("my-template", {
imageId: "ami-12345678",
instanceType: "t3.micro",
networkInterfaces: [{
associatePublicIpAddress: "false", // Disable public IP assignment
securityGroups: [securityGroup.id],
subnetId: privateSubnet.id,
}],
});
ec2-launch-template-disallow-unencrypted-block-device
Severity: high · Enforcement: advisory
Checks that EC2 Launch Templates do not have unencrypted block device.
- 06.d Data Protection and Privacy of Covered Information — Covered information shall be protected against unauthorized disclosure, modification and destruction. For the purpose of this control, covered information includes protected health information, cardholder data, and other sensitive information.
Remediation
Fix: Enable EBS Volume Encryption in Launch Template
Set the encrypted property to “true” for all block device mappings in the Launch Template:
const launchTemplate = new aws.ec2.LaunchTemplate("my-template", {
imageId: "ami-12345678",
instanceType: "t3.micro",
blockDeviceMappings: [{
deviceName: "/dev/sda1",
ebs: {
encrypted: "true", // Enable encryption for the EBS volume
volumeSize: 20,
volumeType: "gp3",
},
}],
});
ec2-security-group-disallow-inbound-http-traffic
Severity: critical · Enforcement: advisory
Check that EC2 Security Groups do not allow inbound HTTP traffic.
- 09.m Network Controls — Networks shall be managed and controlled in order to protect the organization from threats and to maintain security for the systems and applications using the network, including information in transit.
Remediation
Fix: Remove HTTP Inbound Traffic Rules
Remove any ingress rules that allow HTTP traffic on port 80, or use HTTPS (port 443) instead:
const securityGroup = new ec2.SecurityGroup("my-sg", {
vpcId: vpc.id,
ingress: [
{
protocol: "tcp",
fromPort: 443, // Use HTTPS instead of HTTP (port 80)
toPort: 443,
cidrBlocks: ["0.0.0.0/0"],
},
// Remove any rules with fromPort: 80 or toPort: 80
],
});
ecr-image-scanning
Severity: medium · Enforcement: advisory
Ensures ECR repositories have image scanning enabled for vulnerability management
- 10.m Control of Technical Vulnerabilities — Information about technical vulnerabilities of information systems being used shall be obtained in a timely fashion, the organization
Remediation
Fix: Enable Image Scanning for ECR Repository
Set the imageScanningConfiguration with scanOnPush: true to automatically scan container images for vulnerabilities when they are pushed:
const repository = new aws.ecr.Repository("my-repo", {
name: "my-application",
imageScanningConfiguration: {
scanOnPush: true, // Enable automatic vulnerability scanning
},
});
ecr-repository-configure-customer-managed-key
Severity: low · Enforcement: advisory
Checks that ECR repositories use a customer-managed KMS key.
- 10.f Policy on the Use of Cryptographic Controls — Cryptographic controls shall be used in compliance with all relevant agreements, legislation and regulations, and risk assessments shall consider the organization
Remediation
Fix: Configure Customer-Managed KMS Key for ECR Repository
Set the encryptionConfiguration with encryptionType to “KMS” and provide a kmsKey ARN to use customer-managed encryption:
const kmsKey = new aws.kms.Key("ecr-key", {
description: "KMS key for ECR repository encryption",
});
const repo = new ecr.Repository("my-repo", {
encryptionConfigurations: [{
encryptionType: "KMS", // Use KMS encryption instead of AES256
kmsKey: kmsKey.arn, // Specify customer-managed KMS key
}],
});
ecr-repository-configure-image-scan
Severity: high · Enforcement: advisory
Checks that ECR repositories have ‘scan-on-push’ configured.
- 10.m Control of Technical Vulnerabilities — Information about technical vulnerabilities of information systems being used shall be obtained in a timely fashion, the organization
Remediation
Fix: Enable Image Scanning for ECR Repository
Set the imageScanningConfiguration with scanOnPush enabled to automatically scan container images for vulnerabilities when pushed:
const repository = new aws.ecr.Repository("my-repo", {
imageScanningConfiguration: {
scanOnPush: true, // Enable automatic vulnerability scanning on image push
},
});
ecr-repository-disallow-mutable-image
Severity: high · Enforcement: advisory
Checks that ECR Repositories have immutable images enabled.
- 10.h Control of Operational Software — The installation of software on operational systems shall be controlled.
Remediation
Fix: Enable Immutable Image Tags
Set the imageTagMutability property to “IMMUTABLE” to prevent image tags from being overwritten:
const repository = new ecr.Repository("my-repository", {
imageTagMutability: "IMMUTABLE", // Prevent image tags from being overwritten
});
ecr-repository-disallow-unencrypted-repository
Severity: high · Enforcement: advisory
Checks that ECR Repositories are encrypted.
- 06.d Data Protection and Privacy of Covered Information — Covered information shall be protected against unauthorized disclosure, modification and destruction. For the purpose of this control, covered information includes protected health information, cardholder data, and other sensitive information.
Remediation
Fix: Enable Encryption for ECR Repository
Configure the encryptionConfigurations property to enable encryption at rest for your ECR repository:
const repo = new ecr.Repository("my-repo", {
name: "my-application-repo",
encryptionConfigurations: [{ // Enable encryption
encryptionType: "AES256", // Use AWS managed encryption (or "KMS" for customer-managed keys)
}],
});
ecr-repository-enable-image-scan
Severity: high · Enforcement: advisory
Checks that ECR repositories have ‘scan-on-push’ enabled.
- 10.m Control of Technical Vulnerabilities — Information about technical vulnerabilities of information systems being used shall be obtained in a timely fashion, the organization
Remediation
Fix: Enable Scan-on-Push for ECR Repository
Set scanOnPush to true in the imageScanningConfiguration to automatically scan container images for vulnerabilities when pushed:
const repository = new aws.ecr.Repository("my-repository", {
imageScanningConfiguration: {
scanOnPush: true, // Enable automatic vulnerability scanning
},
});
ecs-task-definition-image-scanning
Severity: medium · Enforcement: advisory
Ensures ECS task definitions use images from repositories with vulnerability scanning
- 10.m Control of Technical Vulnerabilities — Information about technical vulnerabilities of information systems being used shall be obtained in a timely fashion, the organization
Remediation
Fix: Use ECR Images with Scanning Enabled
Update your ECS task definition to use container images from ECR repositories that have vulnerability scanning enabled:
const taskDefinition = new aws.ecs.TaskDefinition("my-task", {
family: "my-app",
containerDefinitions: JSON.stringify([{
name: "app",
image: "123456789012.dkr.ecr.us-east-1.amazonaws.com/my-repo:latest", // Use ECR image with scanning
memory: 512,
cpu: 256,
}]),
requiresCompatibilities: ["FARGATE"],
networkMode: "awsvpc",
cpu: "256",
memory: "512",
});
efs-file-system-configure-customer-managed-key
Severity: low · Enforcement: advisory
Check that encrypted EFS File system uses a customer-managed KMS key.
- 10.f Policy on the Use of Cryptographic Controls — Cryptographic controls shall be used in compliance with all relevant agreements, legislation and regulations, and risk assessments shall consider the organization
Remediation
Fix: Configure Customer-Managed KMS Key for EFS Encryption
Set the kmsKeyId property to specify a customer-managed KMS key for EFS file system encryption:
const fileSystem = new aws.efs.FileSystem("my-efs", {
encrypted: true,
kmsKeyId: kmsKey.arn, // Use customer-managed KMS key instead of AWS-managed key
lifecyclePolicy: {
transitionToIa: "AFTER_30_DAYS",
},
});
efs-file-system-disallow-unencrypted-file-system
Severity: high · Enforcement: advisory
Checks that EFS File Systems do not have an unencrypted file system.
- 06.d Data Protection and Privacy of Covered Information — Covered information shall be protected against unauthorized disclosure, modification and destruction. For the purpose of this control, covered information includes protected health information, cardholder data, and other sensitive information.
Remediation
Fix: Enable Encryption for EFS File System
Set the encrypted property to true when creating an EFS file system:
const fileSystem = new aws.efs.FileSystem("my-efs", {
encrypted: true, // Enable encryption at rest
kmsKeyId: kmsKey.arn, // Optional: specify a custom KMS key
});
eks-cluster-disallow-api-endpoint-public-access
Severity: critical · Enforcement: advisory
Check that EKS Clusters API Endpoint are not publicly accessible.
- 09.m Network Controls — Networks shall be managed and controlled in order to protect the organization from threats and to maintain security for the systems and applications using the network, including information in transit.
Remediation
Fix: Disable Public Access to EKS Cluster API Endpoint
Set endpointPublicAccess to false and endpointPrivateAccess to true in the VPC configuration:
const cluster = new eks.Cluster("my-cluster", {
vpcConfig: {
subnetIds: privateSubnetIds,
endpointPublicAccess: false, // Disable public access to API endpoint
endpointPrivateAccess: true, // Enable private access for internal communication
},
// ... other configuration
});
eks-cluster-enable-cluster-encryption-config
Severity: high · Enforcement: advisory
Check that EKS Cluster Encryption Config is enabled.
- 06.d Data Protection and Privacy of Covered Information — Covered information shall be protected against unauthorized disclosure, modification and destruction. For the purpose of this control, covered information includes protected health information, cardholder data, and other sensitive information.
Remediation
Fix: Enable EKS Cluster Encryption Configuration
Configure the encryptionConfig property to encrypt Kubernetes secrets using AWS KMS:
const cluster = new aws.eks.Cluster("my-cluster", {
roleArn: clusterRole.arn,
vpcConfig: {
subnetIds: subnetIds,
},
encryptionConfig: { // Enable encryption for Kubernetes secrets
provider: {
keyArn: kmsKey.arn, // KMS key for encrypting secrets
},
resources: ["secrets"], // Encrypt Kubernetes secrets at rest
},
});
elb-load-balancer-configure-access-logging
Severity: medium · Enforcement: advisory
Check that ELB Load Balancers uses access logging.
- 09.z Publicly Available Information — Publicly available information shall be protected against unauthorized modification or deletion.
Remediation
Fix: Enable Access Logging for ELB Load Balancer
Configure the accessLogs property with enabled: true and specify an S3 bucket for storing access logs:
const lb = new aws.elb.LoadBalancer("my-lb", {
availabilityZones: ["us-west-2a", "us-west-2b"],
listeners: [{
instancePort: 80,
instanceProtocol: "http",
lbPort: 80,
lbProtocol: "http",
}],
accessLogs: {
enabled: true, // Enable access logging
bucket: "my-logs-bucket", // S3 bucket for logs
},
});
elb-load-balancer-configure-multi-availability-zone
Severity: high · Enforcement: advisory
Check that ELB Load Balancers uses more than one availability zone.
- 12.a Including Information Security in the Business Continuity Management — Information security shall be a central part of the organization
Remediation
Fix: Configure Multiple Availability Zones for Load Balancer
Specify at least two availability zones in the availabilityZones property to ensure high availability:
const lb = new aws.elb.LoadBalancer("my-lb", {
availabilityZones: ["us-east-1a", "us-east-1b"], // Configure multiple AZs for resilience
listeners: [{
instancePort: 8000,
instanceProtocol: "http",
lbPort: 80,
lbProtocol: "http",
}],
});
elb-load-balancer-disallow-unencrypted-traffic
Severity: critical · Enforcement: advisory
Check that ELB Load Balancers do not allow unencrypted (HTTP) traffic.
- 10.f Policy on the Use of Cryptographic Controls — Cryptographic controls shall be used in compliance with all relevant agreements, legislation and regulations, and risk assessments shall consider the organization
Remediation
Fix: Use HTTPS Instead of HTTP for Load Balancer Listeners
Configure all listeners to use HTTPS (port 443) instead of HTTP (port 80) to ensure encrypted traffic:
const lb = new aws.elb.LoadBalancer("my-lb", {
availabilityZones: ["us-west-2a", "us-west-2b"],
listeners: [{
instancePort: 443,
instanceProtocol: "https",
lbPort: 443,
lbProtocol: "https", // Use HTTPS instead of HTTP
sslCertificateId: "arn:aws:iam::123456789012:server-certificate/my-cert",
}],
});
elb-load-balancer-enable-health-check
Severity: high · Enforcement: advisory
Check that ELB Load Balancers have a health check enabled.
- 12.a Including Information Security in the Business Continuity Management — Information security shall be a central part of the organization
Remediation
Fix: Configure Health Check for Classic Load Balancer
Add a healthCheck configuration block to your ELB Load Balancer to enable health monitoring:
const lb = new aws.elb.LoadBalancer("my-load-balancer", {
availabilityZones: ["us-west-2a", "us-west-2b"],
listeners: [{
instancePort: 80,
instanceProtocol: "HTTP",
lbPort: 80,
lbProtocol: "HTTP",
}],
healthCheck: { // Enable health check configuration
target: "HTTP:80/",
interval: 30,
timeout: 5,
healthyThreshold: 2,
unhealthyThreshold: 2,
},
});
environment-separation-tagging
Severity: low · Enforcement: advisory
Ensures that resources are tagged to distinguish between production and non-production environments
- 09.d Separation of Development, Test, and Operational Environments — Development, testing, and operational environments shall be separated to reduce the risks of unauthorized access or changes to the operational environment.
Remediation
Fix: Add Environment Tag to Resource
Add an “Environment” tag to the resource with a valid environment value (e.g., production, development, staging, testing):
const instance = new aws.ec2.Instance("web-server", {
instanceType: "t3.micro",
ami: "ami-12345678",
tags: {
"Environment": "production", // Add environment tag for proper separation
"Name": "web-server",
},
});
iam-group-policy-least-privilege
Severity: high · Enforcement: advisory
Ensures IAM group policies follow least privilege principles
- 01.c Privilege Management — The allocation and use of privileges shall be restricted and controlled. The use of privileged utility programs shall be restricted and tightly controlled.
Remediation
Fix: Replace Wildcard Permissions with Specific Actions and Resources
Replace wildcard actions and resources with explicit, scoped permissions:
const groupPolicy = new aws.iam.GroupPolicy("my-group-policy", {
group: myGroup.name,
policy: JSON.stringify({
Version: "2012-10-17",
Statement: [{
Effect: "Allow",
Action: [
"cloudwatch:PutMetricData", // Specify exact actions needed
],
Resource: "*", // Some AWS services require "*" for resource
Condition: {
StringEquals: {
"cloudwatch:namespace": "MyApp", // Use conditions to scope access
},
},
}],
}),
});
iam-password-policy-minimum-password-length
Severity: high · Enforcement: advisory
Ensure IAM password policy requires minimum length of 14 or greater.
- 01.c Privilege Management — The allocation and use of privileges shall be restricted and controlled. The use of privileged utility programs shall be restricted and tightly controlled.
Remediation
Fix: Set Minimum Password Length to 14 Characters
Set the minimumPasswordLength to 14 or greater for the IAM Account Password Policy:
const passwordPolicy = new aws.iam.AccountPasswordPolicy("account-password-policy", {
minimumPasswordLength: 14, // Set minimum length to at least 14 characters
});
iam-password-policy-prevent-reuse
Severity: high · Enforcement: advisory
Ensure IAM password policy prevents password reuse.
- 01.c Privilege Management — The allocation and use of privileges shall be restricted and controlled. The use of privileged utility programs shall be restricted and tightly controlled.
Remediation
Fix: Configure Password Reuse Prevention
Set the passwordReusePrevention property to 24 to prevent users from reusing their previous 24 passwords:
const accountPasswordPolicy = new aws.iam.AccountPasswordPolicy("password-policy", {
minimumPasswordLength: 14,
requireNumbers: true,
requireSymbols: true,
requireUppercaseCharacters: true,
requireLowercaseCharacters: true,
passwordReusePrevention: 24, // Prevent reuse of previous 24 passwords
});
iam-policy-least-privilege
Severity: high · Enforcement: advisory
Ensures IAM policies follow least privilege principles
- 01.c Privilege Management — The allocation and use of privileges shall be restricted and controlled. The use of privileged utility programs shall be restricted and tightly controlled.
Remediation
Fix: Replace Wildcard Permissions with Specific Actions and Resources
Replace wildcard actions and resources with explicit, scoped permissions that grant only the minimum required access:
const policy = new aws.iam.Policy("my-policy", {
policy: JSON.stringify({
Version: "2012-10-17",
Statement: [{
Effect: "Allow",
Action: [
"s3:GetObject", // Specify exact actions needed
"s3:PutObject",
],
Resource: [
"arn:aws:s3:::my-bucket/*", // Scope to specific resources
],
}],
}),
});
iam-role-assume-role-mfa-enforcement
Severity: high · Enforcement: advisory
Ensures IAM roles require MFA when assumed by human users (not AWS services)
- 01.p Secure Log-on Procedures — Log-on procedures shall be designed to minimize the opportunity for unauthorized access. Log-on procedures shall reveal the minimum of information necessary to allow authorized users to recognize that they have accessed the appropriate system.
Remediation
Fix: Add MFA Condition to Role Trust Policy
Add the aws:MultiFactorAuthPresent condition to any assume role statement that allows human principals to assume the role:
const adminRole = new aws.iam.Role("admin-role", {
assumeRolePolicy: JSON.stringify({
Version: "2012-10-17",
Statement: [{
Effect: "Allow",
Principal: {
AWS: "arn:aws:iam::123456789012:root" // Root account (human)
},
Action: "sts:AssumeRole",
Condition: {
Bool: {
"aws:MultiFactorAuthPresent": "true" // Require MFA
}
}
}],
}),
});
const userAssumeRole = new aws.iam.Role("user-role", {
assumeRolePolicy: JSON.stringify({
Version: "2012-10-17",
Statement: [{
Effect: "Allow",
Principal: {
AWS: "arn:aws:iam::123456789012:user/john.doe" // IAM user (human)
},
Action: "sts:AssumeRole",
Condition: {
Bool: {
"aws:MultiFactorAuthPresent": "true" // Require MFA
}
}
}],
}),
});
// Service roles are automatically exempt (no MFA condition needed)
const ecsTaskRole = new aws.iam.Role("ecs-task-role", {
assumeRolePolicy: JSON.stringify({
Version: "2012-10-17",
Statement: [{
Effect: "Allow",
Principal: {
Service: "ecs-tasks.amazonaws.com" // Service principal - no MFA needed
},
Action: "sts:AssumeRole"
}],
}),
});
// Role principals are never flagged (could be cross-account service roles)
const crossAccountRole = new aws.iam.Role("cross-account-role", {
assumeRolePolicy: JSON.stringify({
Version: "2012-10-17",
Statement: [{
Effect: "Allow",
Principal: {
AWS: "arn:aws:iam::111111111111:role/service-role" // Role principal - not checked
},
Action: "sts:AssumeRole"
}],
}),
});
iam-role-least-privilege
Severity: high · Enforcement: advisory
Ensures IAM roles follow least privilege principles
- 01.c Privilege Management — The allocation and use of privileges shall be restricted and controlled. The use of privileged utility programs shall be restricted and tightly controlled.
Remediation
Fix: Replace Wildcard Permissions with Specific Actions and Resources
Replace wildcard actions and resources in inline policies with explicit, scoped permissions:
const role = new aws.iam.Role("my-role", {
assumeRolePolicy: assumePolicyDoc,
inlinePolicies: [{
name: "my-inline-policy",
policy: JSON.stringify({
Version: "2012-10-17",
Statement: [{
Effect: "Allow",
Action: [
"dynamodb:GetItem", // Specify exact actions needed
"dynamodb:PutItem",
],
Resource: [
"arn:aws:dynamodb:us-east-1:123456789012:table/MyTable", // Scope to specific resources
],
}],
}),
}],
});
iam-role-policy-least-privilege
Severity: high · Enforcement: advisory
Ensures IAM role policies follow least privilege principles
- 01.c Privilege Management — The allocation and use of privileges shall be restricted and controlled. The use of privileged utility programs shall be restricted and tightly controlled.
Remediation
Fix: Replace Wildcard Permissions with Specific Actions and Resources
Replace wildcard actions and resources with explicit, scoped permissions:
const rolePolicy = new aws.iam.RolePolicy("my-role-policy", {
role: myRole.id,
policy: JSON.stringify({
Version: "2012-10-17",
Statement: [{
Effect: "Allow",
Action: [
"ec2:DescribeInstances", // Specify exact actions needed
"ec2:StartInstances",
"ec2:StopInstances",
],
Resource: [
"arn:aws:ec2:us-east-1:123456789012:instance/*", // Scope to specific resources
],
}],
}),
});
iam-role-session-duration
Severity: medium · Enforcement: advisory
Enforces maximum session duration for IAM roles
- 01.a Access Control Policy — All users shall have a unique identifier for their personal and sole use so that users can be linked to and made responsible for their actions.
Remediation
Fix: Set Appropriate Maximum Session Duration for IAM Role
Configure the maxSessionDuration property based on the role type to limit credential exposure window:
const appRole = new aws.iam.Role("app-role", {
assumeRolePolicy: JSON.stringify({
Version: "2012-10-17",
Statement: [{
Effect: "Allow",
Principal: { Service: "ec2.amazonaws.com" },
Action: "sts:AssumeRole",
}],
}),
maxSessionDuration: 3600, // 1 hour for general roles (default)
});
const adminRole = new aws.iam.Role("admin-role", {
name: "AdminRole",
assumeRolePolicy: JSON.stringify({
Version: "2012-10-17",
Statement: [{
Effect: "Allow",
Principal: { AWS: "arn:aws:iam::123456789012:root" },
Action: "sts:AssumeRole",
}],
}),
maxSessionDuration: 7200, // 2 hours for administrative roles
});
iam-user-mfa-console-access
Severity: high · Enforcement: advisory
Ensures IAM users with console access have MFA devices
- 01.p Secure Log-on Procedures — Log-on procedures shall be designed to minimize the opportunity for unauthorized access. Log-on procedures shall reveal the minimum of information necessary to allow authorized users to recognize that they have accessed the appropriate system.
Remediation
Fix: Enable MFA for IAM User Console Access
Create a Virtual MFA Device for each IAM user with console access:
const user = new aws.iam.User("example-user", {
name: "example-user",
});
const loginProfile = new aws.iam.UserLoginProfile("example-login", {
user: user.name,
});
// Create Virtual MFA Device for the user
const mfaDevice = new aws.iam.VirtualMfaDevice("example-user-mfa", {
virtualMfaDeviceName: "example-user-mfa", // Name must match pattern: <username>-mfa or <username>-mfa-device
userName: user.name, // Associate MFA device with the user
});
iam-user-policy-least-privilege
Severity: high · Enforcement: advisory
Ensures IAM user policies follow least privilege principles
- 01.c Privilege Management — The allocation and use of privileges shall be restricted and controlled. The use of privileged utility programs shall be restricted and tightly controlled.
Remediation
Fix: Replace Wildcard Permissions with Specific Actions and Resources
Replace wildcard actions and resources with explicit, scoped permissions:
const userPolicy = new aws.iam.UserPolicy("my-user-policy", {
user: myUser.name,
policy: JSON.stringify({
Version: "2012-10-17",
Statement: [{
Effect: "Allow",
Action: [
"s3:ListBucket", // Specify exact actions needed
],
Resource: [
"arn:aws:s3:::my-bucket", // Scope to specific resources
],
}],
}),
});
kinesis-event-source-mapping-dlq
Severity: medium · Enforcement: advisory
Ensures Kinesis Lambda event source mappings have DLQ configuration
- 12.a Including Information Security in the Business Continuity Management — Information security shall be a central part of the organization
Remediation
Fix: Configure Dead Letter Queue for Kinesis Event Source Mapping
Add the destinationConfig property with an onFailure destination to capture failed records:
const eventSourceMapping = new aws.lambda.EventSourceMapping("kinesis-mapping", {
eventSourceArn: kinesisStream.arn,
functionName: lambdaFunction.arn,
startingPosition: "LATEST",
destinationConfig: { // Add destination configuration for error handling
onFailure: {
destination: dlqArn, // ARN of SQS queue or SNS topic for failed records
},
},
});
kinesis-stream-retention
Severity: medium · Enforcement: advisory
Ensures Kinesis streams have retention periods configured
- 06.d Data Protection and Privacy of Covered Information — Covered information shall be protected against unauthorized disclosure, modification and destruction. For the purpose of this control, covered information includes protected health information, cardholder data, and other sensitive information.
Remediation
Fix: Configure Kinesis Stream Retention Period
Set the retentionPeriod property to define how long data records remain accessible in the stream (minimum 24 hours, maximum 8760 hours):
const stream = new aws.kinesis.Stream("my-stream", {
shardCount: 1,
retentionPeriod: 24, // Set retention period in hours (24 hours minimum)
encryptionType: "KMS",
kmsKeyId: kmsKey.id,
});
kms-grant-access-control
Severity: high · Enforcement: advisory
Validates KMS grants for least privilege access control
- 01.a Access Control Policy — All users shall have a unique identifier for their personal and sole use so that users can be linked to and made responsible for their actions.
Remediation
Fix: Configure KMS Grant with Least Privilege Access Control
Specify explicit operations for the grant, add constraints for sensitive operations, and define a specific grantee principal:
const grant = new aws.kms.Grant("my-kms-grant", {
keyId: kmsKey.id,
granteePrincipal: roleArn, // Specify a specific grantee principal
operations: ["Encrypt", "Decrypt"], // Define specific operations
constraints: {
encryptionContextSubset: {
"Department": "Finance", // Add constraints for sensitive operations
},
},
});
kms-key-creation
Severity: medium · Enforcement: advisory
Validates KMS key creation with appropriate specifications and origins
- 10.f Policy on the Use of Cryptographic Controls — Cryptographic controls shall be used in compliance with all relevant agreements, legislation and regulations, and risk assessments shall consider the organization
Remediation
Fix: Configure KMS Key with Proper Specifications
Add a description, configure an appropriate deletion window (7-30 days), and ensure key specifications match your security requirements:
const key = new aws.kms.Key("my-key", {
description: "Key for encrypting application data", // Add clear description
customerMasterKeySpec: "SYMMETRIC_DEFAULT", // Use approved key spec
keyUsage: "ENCRYPT_DECRYPT", // Specify key usage
deletionWindowInDays: 30, // Set deletion window between 7-30 days
enableKeyRotation: true,
});
kms-key-deletion-lifecycle
Severity: medium · Enforcement: advisory
Validates KMS key deletion windows and lifecycle management
- 10.f Policy on the Use of Cryptographic Controls — Cryptographic controls shall be used in compliance with all relevant agreements, legislation and regulations, and risk assessments shall consider the organization
Remediation
Fix: Configure KMS Key Deletion Window and Lifecycle Management
Set a deletionWindowInDays between 7 and 30 days, add descriptive tags, and provide a clear description for proper lifecycle management:
const kmsKey = new aws.kms.Key("my-key", {
description: "Encryption key for application data",
deletionWindowInDays: 30, // Set deletion window between 7-30 days
tags: {
Environment: "production",
Owner: "security-team",
Purpose: "data-encryption",
},
});
kms-key-enable-key-rotation
Severity: medium · Enforcement: advisory
Checks that KMS Keys have key rotation enabled.
- 10.f Policy on the Use of Cryptographic Controls — Cryptographic controls shall be used in compliance with all relevant agreements, legislation and regulations, and risk assessments shall consider the organization
Remediation
Fix: Enable Automatic Key Rotation for KMS Keys
Set the enableKeyRotation property to true for all KMS keys to ensure cryptographic keys are automatically rotated annually:
const key = new kms.Key("my-key", {
description: "KMS key with automatic rotation",
enableKeyRotation: true, // Enable automatic annual key rotation
});
kms-key-policy-access-control
Severity: high · Enforcement: advisory
Validates KMS key policies for least privilege and separation of duties
- 01.a Access Control Policy — All users shall have a unique identifier for their personal and sole use so that users can be linked to and made responsible for their actions.
Remediation
Fix: Configure KMS Key Policy with Least Privilege Access Control
Define an explicit key policy with specific principals and actions, avoiding wildcards:
const keyPolicy = {
Version: "2012-10-17",
Statement: [
{
Sid: "Enable IAM User Permissions",
Effect: "Allow",
Principal: {
AWS: `arn:aws:iam::${accountId}:root`, // Specific account root
},
Action: "kms:*",
Resource: "*",
},
{
Sid: "Allow Key Administrators",
Effect: "Allow",
Principal: {
AWS: `arn:aws:iam::${accountId}:role/KeyAdminRole`, // Specific role ARN
},
Action: [
"kms:Create*",
"kms:Describe*",
"kms:Enable*",
"kms:List*",
"kms:Put*",
"kms:Update*",
"kms:Revoke*",
"kms:Disable*",
"kms:Get*",
"kms:Delete*",
"kms:ScheduleKeyDeletion",
"kms:CancelKeyDeletion", // Specific administrative actions only
],
Resource: "*",
},
{
Sid: "Allow Key Usage",
Effect: "Allow",
Principal: {
AWS: `arn:aws:iam::${accountId}:role/KeyUserRole`, // Specific user role ARN
},
Action: [
"kms:Decrypt",
"kms:EncryptionContext*",
"kms:GenerateDataKey", // Specific usage actions only
],
Resource: "*",
},
],
};
const key = new aws.kms.Key("my-key", {
description: "My KMS key with least privilege policy",
policy: JSON.stringify(keyPolicy), // Apply the policy with specific principals and actions
});
lambda-environment-variables-encryption
Severity: high · Enforcement: advisory
Ensures that all Lambda functions have their environment variables encrypted using AWS KMS
- 10.d Message Integrity — Integrity shall be applied to messages using cryptography or digital signatures, where deemed appropriate.
Remediation
Fix: Encrypt Lambda Environment Variables with KMS
Configure a KMS key for Lambda function environment variable encryption by setting the kmsKeyArn property:
const kmsKey = new aws.kms.Key("lambda-env-key", {
description: "KMS key for Lambda environment variable encryption",
});
const lambdaFunction = new aws.lambda.Function("my-function", {
runtime: "nodejs18.x",
handler: "index.handler",
role: role.arn,
code: new pulumi.asset.AssetArchive({
".": new pulumi.asset.FileArchive("./function"),
}),
environment: {
variables: {
DATABASE_URL: "postgres://example.com/db",
},
},
kmsKeyArn: kmsKey.arn, // Encrypt environment variables with KMS
});
lambda-function-documentation
Severity: low · Enforcement: advisory
Ensures all AWS Lambda functions have a documented description attribute
- 09.b Change Management — Changes to systems, applications and supporting infrastructure shall be controlled.
Remediation
Fix: Add Description to Lambda Function
Add a meaningful description attribute to your Lambda function that is at least 10 characters long:
const myFunction = new aws.lambda.Function("my-function", {
code: new pulumi.asset.FileArchive("./function"),
role: lambdaRole.arn,
handler: "index.handler",
runtime: "nodejs20.x",
description: "Processes user authentication requests and validates credentials", // Add descriptive documentation
});
lambda-function-logging
Severity: medium · Enforcement: advisory
Ensures that all AWS Lambda functions have logging enabled to track output data processing
- 10.e Output Data Validation — Output data from applications shall be validated to ensure that the processing of stored information is correct and appropriate to the circumstances.
Remediation
Fix: Enable Lambda Function Logging Configuration
Add the loggingConfig property to your Lambda function with an appropriate applicationLogLevel (DEBUG, INFO, or WARN):
const myFunction = new aws.lambda.Function("my-function", {
runtime: "nodejs18.x",
handler: "index.handler",
role: lambdaRole.arn,
code: new pulumi.asset.AssetArchive({
".": new pulumi.asset.FileArchive("./app"),
}),
loggingConfig: {
logFormat: "JSON",
applicationLogLevel: "INFO", // Set log level to INFO or DEBUG for adequate logging
},
});
lambda-permission-configure-source-arn
Severity: critical · Enforcement: advisory
Checks that lambda function permissions have a source arn specified.
- 01.c Privilege Management — The allocation and use of privileges shall be restricted and controlled. The use of privileged utility programs shall be restricted and tightly controlled.
Remediation
Fix: Configure Source ARN for Lambda Permission
Add the sourceArn property to restrict which AWS service or resource can invoke the Lambda function:
const lambdaPermission = new aws.lambda.Permission("my-permission", {
action: "lambda:InvokeFunction",
function: myFunction.name,
principal: "apigateway.amazonaws.com",
sourceArn: apiGateway.executionArn, // Specify the source ARN to restrict invocation
});
lambda-runtime-restrictions
Severity: low · Enforcement: advisory
Ensures that AWS Lambda functions are created only with approved runtime versions
- 10.h Control of Operational Software — The installation of software on operational systems shall be controlled.
Remediation
Fix: Use Approved Lambda Runtime
Set the runtime property to an approved runtime version from the organization’s approved list:
const myFunction = new aws.lambda.Function("my-function", {
runtime: "nodejs20.x", // Use an approved runtime version
handler: "index.handler",
role: role.arn,
code: new pulumi.asset.AssetArchive({
".": new pulumi.asset.FileArchive("./function"),
}),
});
limit-lambda-execution-time
Severity: low · Enforcement: advisory
Ensures that AWS Lambda functions are configured to time out after a specified duration to prevent extended access
- 01.u Limitation of Connection Time — Inactive sessions shall shut down after a defined period of inactivity.
Remediation
Fix: Configure Lambda Function Timeout
Set the timeout property to limit function execution time (default maximum: 300 seconds):
const myFunction = new aws.lambda.Function("my-function", {
runtime: "nodejs20.x",
handler: "index.handler",
role: lambdaRole.arn,
code: new pulumi.asset.AssetArchive({
".": new pulumi.asset.FileArchive("./app"),
}),
timeout: 300, // Set timeout to prevent extended access (max 300 seconds by default)
});
load-balancer-waf-association
Severity: critical · Enforcement: advisory
Ensures public-facing Load Balancers have WAF associations
- 09.m Network Controls — Networks shall be managed and controlled in order to protect the organization from threats and to maintain security for the systems and applications using the network, including information in transit.
Remediation
Fix: Associate WAF Web ACL with Load Balancer
Create a WAF Web ACL association to protect your public-facing Load Balancer:
// Create a WAF Web ACL association for the Load Balancer
const wafAssociation = new aws.wafv2.WebAclAssociation("lb-waf-association", {
resourceArn: loadBalancer.arn, // Reference the Load Balancer ARN
webAclArn: webAcl.arn, // Reference the WAF Web ACL ARN
});
neptune-clusterinstance-managed-service-patching
Severity: medium · Enforcement: advisory
Ensures Neptune cluster instances have automated minor version upgrades enabled
- 10.k Change Control Procedures — Changes to systems within the development lifecycle shall be controlled by the use of formal change control procedures.
Remediation
Fix: Enable Automatic Minor Version Upgrades for Neptune Cluster Instance
Set the autoMinorVersionUpgrade property to true to enable automated patching for managed service security updates:
const neptuneInstance = new aws.neptune.ClusterInstance("my-neptune-instance", {
clusterIdentifier: neptuneCluster.id,
instanceClass: "db.r5.large",
engine: "neptune",
autoMinorVersionUpgrade: true, // Enable automatic minor version upgrades
});
neptune-clusterinstance-no-public-access
Severity: critical · Enforcement: advisory
Checks that Neptune Cluster Instances public access is not enabled.
- 09.m Network Controls — Networks shall be managed and controlled in order to protect the organization from threats and to maintain security for the systems and applications using the network, including information in transit.
Remediation
Fix: Disable Public Access for Neptune Cluster Instance
Set the publiclyAccessible property to false:
const neptuneInstance = new aws.neptune.ClusterInstance("neptune-instance", {
clusterIdentifier: neptuneCluster.id,
instanceClass: "db.r5.large",
engine: "neptune",
publiclyAccessible: false, // Disable public access
});
no-direct-user-access-keys
Severity: high · Enforcement: advisory
Prevents creation of direct IAM user access keys for human users
- 01.p Secure Log-on Procedures — Log-on procedures shall be designed to minimize the opportunity for unauthorized access. Log-on procedures shall reveal the minimum of information necessary to allow authorized users to recognize that they have accessed the appropriate system.
Remediation
Fix: Use IAM Roles Instead of Access Keys
Remove the IAM access key resource and use IAM roles with temporary credentials instead:
// Remove this - do not create IAM access keys
// const accessKey = new aws.iam.AccessKey("user-key", {
// user: user.name,
// });
// Instead, use IAM roles for workloads
const role = new aws.iam.Role("app-role", {
assumeRolePolicy: JSON.stringify({
Version: "2012-10-17",
Statement: [{
Effect: "Allow",
Principal: { Service: "ec2.amazonaws.com" }, // Use appropriate service
Action: "sts:AssumeRole",
}],
}),
});
// Attach necessary policies to the role
new aws.iam.RolePolicyAttachment("app-policy", {
role: role.name,
policyArn: "arn:aws:iam::aws:policy/ReadOnlyAccess", // Use least-privilege policy
});
// For human users, use AWS SSO or federated identity instead of access keys
no-hardcoded-secrets
Severity: critical · Enforcement: advisory
Ensures EC2 instance userData does not contain hardcoded secrets
- 01.d User Password Management — The allocation and management of passwords shall be controlled through a formal process, including requirements for password encryption, storage separate from application system data, and prevention of hardcoded credentials in scripts and configuration.
Remediation
Fix: Remove Hardcoded Secrets
Remove hardcoded secrets from userData scripts.
Example Violation
const instance = new aws.ec2.Instance("web-server", {
instanceType: "t3.micro",
ami: "ami-12345678",
userData: `#!/bin/bash
export DATABASE_PASSWORD="mySecretPassword123"
export API_KEY="sk_live_abc123def456789"
mysql -u admin -p"hardcodedPassword" -h db.example.com
`,
});
pubsub-least-privilege-iam
Severity: medium · Enforcement: advisory
Ensures IAM policies follow least privilege principles for Pub/Sub services (SNS, SQS, Kinesis)
- 01.c Privilege Management — The allocation and use of privileges shall be restricted and controlled. The use of privileged utility programs shall be restricted and tightly controlled.
Remediation
Fix: Use Specific Pub/Sub IAM Actions and Resource ARNs
Replace wildcard permissions with specific actions and resource ARNs for Pub/Sub services:
const queuePolicy = new aws.iam.Policy("queue-policy", {
policy: JSON.stringify({
Version: "2012-10-17",
Statement: [{
Effect: "Allow",
Action: [
"sqs:SendMessage", // Use specific actions instead of sqs:*
"sqs:ReceiveMessage",
"sqs:DeleteMessage",
],
Resource: "arn:aws:sqs:us-east-1:123456789012:my-queue", // Use specific ARN instead of *
}],
}),
});
rds-audit-logging
Severity: medium · Enforcement: advisory
Ensures RDS instances have audit logging enabled
- 09.z Publicly Available Information — Publicly available information shall be protected against unauthorized modification or deletion.
Remediation
Fix: Enable RDS Audit Logging to CloudWatch
Configure enabledCloudwatchLogsExports with appropriate audit log types for your database engine:
// For MySQL/MariaDB
const db = new aws.rds.Instance("my-db", {
engine: "mysql",
instanceClass: "db.t3.micro",
allocatedStorage: 20,
enabledCloudwatchLogsExports: ["audit", "error", "general", "slowquery"], // Enable audit logs
// ... other configuration
});
// For PostgreSQL
const pgDb = new aws.rds.Instance("my-pg-db", {
engine: "postgres",
instanceClass: "db.t3.micro",
allocatedStorage: 20,
enabledCloudwatchLogsExports: ["postgresql"], // Enable PostgreSQL logs
// ... other configuration
});
// For Aurora clusters
const cluster = new aws.rds.Cluster("my-cluster", {
engine: "aurora-mysql",
enabledCloudwatchLogsExports: ["audit", "error", "general", "slowquery"], // Enable audit logs
// ... other configuration
});
rds-cluster-configure-customer-managed-key
Severity: low · Enforcement: advisory
Checks that RDS Clusters storage uses a customer-managed KMS key.
- 06.d Data Protection and Privacy of Covered Information — Covered information shall be protected against unauthorized disclosure, modification and destruction. For the purpose of this control, covered information includes protected health information, cardholder data, and other sensitive information.
Remediation
Fix: Configure Customer-Managed KMS Key for RDS Cluster
Specify a customer-managed KMS key for RDS Cluster storage encryption using the kmsKeyId property:
const cluster = new rds.Cluster("my-cluster", {
engine: "aurora-postgresql",
storageEncrypted: true,
kmsKeyId: kmsKey.arn, // Use customer-managed KMS key
masterUsername: "admin",
masterPassword: dbPassword,
});
rds-cluster-disallow-single-availability-zone
Severity: high · Enforcement: advisory
Check that RDS Cluster doesn’t use single availability zone.
- 12.a Including Information Security in the Business Continuity Management — Information security shall be a central part of the organization
Remediation
Fix: Configure Multiple Availability Zones for RDS Cluster
Specify at least two availability zones in the availabilityZones property to ensure high availability and resilience:
const cluster = new rds.Cluster("my-cluster", {
engine: "aurora-mysql",
engineVersion: "8.0.mysql_aurora.3.04.0",
availabilityZones: ["us-east-1a", "us-east-1b"], // Configure at least two AZs
databaseName: "mydb",
masterUsername: "admin",
masterPassword: dbPassword,
skipFinalSnapshot: true,
});
rds-cluster-disallow-unencrypted-storage
Severity: high · Enforcement: advisory
Checks that RDS Clusters storage is encrypted.
- 06.d Data Protection and Privacy of Covered Information — Covered information shall be protected against unauthorized disclosure, modification and destruction. For the purpose of this control, covered information includes protected health information, cardholder data, and other sensitive information.
Remediation
Fix: Enable RDS Cluster Storage Encryption
Set the storageEncrypted property to true to enable encryption at rest for the RDS cluster:
const cluster = new aws.rds.Cluster("my-cluster", {
engine: "aurora-mysql",
engineVersion: "8.0.mysql_aurora.3.02.0",
masterUsername: "admin",
masterPassword: dbPassword,
storageEncrypted: true, // Enable storage encryption
databaseName: "mydb",
skipFinalSnapshot: true,
});
rds-cluster-enable-backup-retention
Severity: medium · Enforcement: advisory
Checks that RDS Clusters backup retention policy is enabled.
- 12.a Including Information Security in the Business Continuity Management — Information security shall be a central part of the organization
Remediation
Fix: Enable RDS Cluster Backup Retention
Set the backupRetentionPeriod to a value between 1 and 35 days to enable automated backups:
const cluster = new rds.Cluster("my-cluster", {
engine: "aurora-mysql",
masterUsername: "admin",
masterPassword: dbPassword,
backupRetentionPeriod: 7, // Enable backup retention (1-35 days)
preferredBackupWindow: "03:00-04:00",
});
rds-cluster-instance-disallow-public-access
Severity: critical · Enforcement: advisory
Checks that RDS Cluster Instances public access is not enabled.
- 09.m Network Controls — Networks shall be managed and controlled in order to protect the organization from threats and to maintain security for the systems and applications using the network, including information in transit.
Remediation
Fix: Disable Public Access for RDS Cluster Instance
Set the publiclyAccessible property to false to ensure the RDS Cluster Instance is not accessible from the public internet:
const clusterInstance = new aws.rds.ClusterInstance("my-cluster-instance", {
clusterIdentifier: cluster.id,
instanceClass: "db.r5.large",
engine: "aurora-postgresql",
publiclyAccessible: false, // Disable public access
});
rds-cluster-secure-master-credentials
Severity: high · Enforcement: advisory
Ensures RDS clusters use secure credential management instead of hardcoded passwords
- 06.d Data Protection and Privacy of Covered Information — Covered information shall be protected against unauthorized disclosure, modification and destruction. For the purpose of this control, covered information includes protected health information, cardholder data, and other sensitive information.
Remediation
Fix: Use AWS Secrets Manager for RDS Cluster Master Credentials
Enable AWS-managed master password using Secrets Manager instead of hardcoded credentials:
const dbCluster = new aws.rds.Cluster("my-cluster", {
engine: "aurora-mysql",
engineVersion: "8.0.mysql_aurora.3.02.0",
manageMasterUserPassword: true, // Enable AWS Secrets Manager for master password
masterUsername: "admin",
// Do NOT set the masterPassword property - AWS Secrets Manager handles it
vpcSecurityGroupIds: [securityGroup.id],
dbSubnetGroupName: subnetGroup.name,
});
rds-clusterinstance-managed-service-patching
Severity: medium · Enforcement: advisory
Ensures RDS cluster instances have automated minor version upgrades enabled
- 10.k Change Control Procedures — Changes to systems within the development lifecycle shall be controlled by the use of formal change control procedures.
Remediation
Fix: Enable Automatic Minor Version Upgrades for Aurora Cluster Instance
Set the autoMinorVersionUpgrade property to true to enable automated patching for managed service security updates:
const clusterInstance = new aws.rds.ClusterInstance("my-cluster-instance", {
clusterIdentifier: cluster.id,
instanceClass: "db.r5.large",
engine: cluster.engine,
autoMinorVersionUpgrade: true, // Enable automatic minor version upgrades
});
rds-clusterinstance-ssl-encryption
Severity: high · Enforcement: advisory
Ensures RDS cluster instances have SSL/TLS encryption enabled through parameter group configuration
- 10.f Policy on the Use of Cryptographic Controls — Cryptographic controls shall be used in compliance with all relevant agreements, legislation and regulations, and risk assessments shall consider the organization
Remediation
Fix: Configure SSL/TLS Encryption for Aurora Cluster Instance
Configure a parameter group to enforce SSL/TLS connections for your Aurora cluster instance:
const clusterParamGroup = new aws.rds.ParameterGroup("cluster-params", {
family: "aurora-postgresql14",
parameters: [
{
name: "rds.force_ssl",
value: "1", // Enforce SSL/TLS for all connections
},
],
});
const clusterInstance = new aws.rds.ClusterInstance("my-cluster-instance", {
clusterIdentifier: cluster.id,
instanceClass: "db.r5.large",
engine: cluster.engine,
dbParameterGroupName: clusterParamGroup.name, // Attach parameter group with SSL enforcement
});
rds-iam-authentication
Severity: medium · Enforcement: advisory
Ensures RDS instances have IAM database authentication enabled
- 01.a Access Control Policy — All users shall have a unique identifier for their personal and sole use so that users can be linked to and made responsible for their actions.
Remediation
Fix: Enable IAM Database Authentication for RDS Instance
Set the iamDatabaseAuthenticationEnabled property to true to enable IAM-based authentication for your RDS instance:
const rdsInstance = new aws.rds.Instance("my-database", {
engine: "mysql",
instanceClass: "db.t3.micro",
allocatedStorage: 20,
username: "admin",
iamDatabaseAuthenticationEnabled: true, // Enable IAM database authentication
skipFinalSnapshot: true,
});
rds-instance-configure-customer-managed-key
Severity: low · Enforcement: advisory
Checks that RDS Instance storage uses a customer-managed KMS key.
- 06.d Data Protection and Privacy of Covered Information — Covered information shall be protected against unauthorized disclosure, modification and destruction. For the purpose of this control, covered information includes protected health information, cardholder data, and other sensitive information.
Remediation
Fix: Configure Customer-Managed KMS Key for RDS Instance
Specify a customer-managed KMS key when enabling storage encryption on your RDS instance:
const rdsInstance = new aws.rds.Instance("my-db", {
allocatedStorage: 20,
engine: "postgres",
instanceClass: "db.t3.micro",
storageEncrypted: true,
kmsKeyId: kmsKey.arn, // Specify customer-managed KMS key ARN
// ... other configuration
});
rds-instance-disallow-public-access
Severity: critical · Enforcement: advisory
Checks that RDS Instance public access is not enabled.
- 09.m Network Controls — Networks shall be managed and controlled in order to protect the organization from threats and to maintain security for the systems and applications using the network, including information in transit.
Remediation
Fix: Disable Public Access for RDS Instance
Set publiclyAccessible to false to prevent the RDS instance from being accessible from the internet:
const dbInstance = new aws.rds.Instance("my-database", {
allocatedStorage: 20,
engine: "mysql",
engineVersion: "8.0",
instanceClass: "db.t3.micro",
dbSubnetGroupName: privateSubnetGroup.name,
vpcSecurityGroupIds: [dbSecurityGroup.id],
publiclyAccessible: false, // Disable public access
username: dbUsername,
password: dbPassword,
});
rds-instance-disallow-unencrypted-storage
Severity: high · Enforcement: advisory
Checks that RDS instance storage is encrypted.
- 06.d Data Protection and Privacy of Covered Information — Covered information shall be protected against unauthorized disclosure, modification and destruction. For the purpose of this control, covered information includes protected health information, cardholder data, and other sensitive information.
Remediation
Fix: Enable RDS Storage Encryption
Set the storageEncrypted property to true to encrypt the RDS instance storage:
const dbInstance = new aws.rds.Instance("my-db", {
engine: "postgres",
instanceClass: "db.t3.micro",
allocatedStorage: 20,
storageEncrypted: true, // Enable storage encryption
username: "admin",
password: adminPassword,
});
rds-instance-enable-backup-retention
Severity: medium · Enforcement: advisory
Checks that RDS Instances backup retention policy is enabled.
- 12.a Including Information Security in the Business Continuity Management — Information security shall be a central part of the organization
Remediation
Fix: Enable Backup Retention for RDS Instance
Set the backupRetentionPeriod to a value between 1 and 35 days to enable automated backups:
const dbInstance = new aws.rds.Instance("my-db", {
engine: "mysql",
instanceClass: "db.t3.micro",
allocatedStorage: 20,
backupRetentionPeriod: 7, // Enable backup retention (1-35 days)
username: "admin",
password: dbPassword,
});
rds-instance-high-availability
Severity: medium · Enforcement: advisory
Ensures RDS instances have Multi-AZ deployment enabled for high availability
- 12.a Including Information Security in the Business Continuity Management — Information security shall be a central part of the organization
Remediation
Fix: Enable Multi-AZ Deployment for RDS Instance
Set the multiAz property to true to enable automatic failover to a standby replica in a different Availability Zone:
const dbInstance = new aws.rds.Instance("my-database", {
allocatedStorage: 20,
engine: "mysql",
engineVersion: "8.0",
instanceClass: "db.t3.micro",
username: "admin",
password: dbPassword,
multiAz: true, // Enable Multi-AZ deployment for high availability
skipFinalSnapshot: true,
});
rds-instance-managed-service-patching
Severity: medium · Enforcement: advisory
Ensures RDS instances have automated minor version upgrades enabled
- 10.k Change Control Procedures — Changes to systems within the development lifecycle shall be controlled by the use of formal change control procedures.
Remediation
Fix: Enable Automatic Minor Version Upgrades for RDS
Set the autoMinorVersionUpgrade property to true to enable automated patching for managed service security updates:
const db = new aws.rds.Instance("my-database", {
engine: "postgres",
instanceClass: "db.t3.micro",
allocatedStorage: 20,
dbName: "mydb",
username: "admin",
password: dbPassword,
autoMinorVersionUpgrade: true, // Enable automatic minor version upgrades
skipFinalSnapshot: true,
});
rds-instance-ssl-encryption
Severity: high · Enforcement: advisory
Ensures RDS instances have SSL/TLS encryption enabled through parameter group configuration
- 10.f Policy on the Use of Cryptographic Controls — Cryptographic controls shall be used in compliance with all relevant agreements, legislation and regulations, and risk assessments shall consider the organization
Remediation
Fix: Configure SSL/TLS Encryption for RDS Instance
Configure a parameter group to enforce SSL/TLS connections for your RDS instance:
const dbParamGroup = new aws.rds.ParameterGroup("db-params", {
family: "mysql8.0",
parameters: [
{
name: "require_secure_transport",
value: "1", // Enforce SSL/TLS for all connections
},
],
});
const db = new aws.rds.Instance("my-database", {
engine: "mysql",
instanceClass: "db.t3.micro",
allocatedStorage: 20,
parameterGroupName: dbParamGroup.name, // Attach parameter group with SSL enforcement
username: "admin",
password: dbPassword,
});
rds-private-subnet-validation
Severity: critical · Enforcement: advisory
Validates that RDS DB subnet groups contain only private subnets
- 09.m Network Controls — Networks shall be managed and controlled in order to protect the organization from threats and to maintain security for the systems and applications using the network, including information in transit.
Remediation
Fix: Deploy RDS DB Subnet Group in Private Subnets
Ensure the DB subnet group only contains subnets that do not have routes to an Internet Gateway. Private subnets should route internet-bound traffic through a NAT Gateway instead:
const privateSubnetGroup = new aws.rds.SubnetGroup("db-subnet-group", {
subnetIds: [
privateSubnet1.id, // Private subnet without Internet Gateway route
privateSubnet2.id, // Private subnet without Internet Gateway route
],
tags: {
Name: "Private DB Subnet Group",
},
});
const db = new aws.rds.Instance("database", {
dbSubnetGroupName: privateSubnetGroup.name,
publiclyAccessible: false,
// ... other configuration
});
rds-secure-master-credentials
Severity: high · Enforcement: advisory
Ensures RDS instances use secure credential management instead of hardcoded passwords
- 06.d Data Protection and Privacy of Covered Information — Covered information shall be protected against unauthorized disclosure, modification and destruction. For the purpose of this control, covered information includes protected health information, cardholder data, and other sensitive information.
Remediation
Fix: Use AWS Secrets Manager for RDS Master Credentials
Enable AWS-managed master password using Secrets Manager instead of hardcoded credentials:
const dbInstance = new aws.rds.Instance("my-db", {
allocatedStorage: 20,
engine: "mysql",
instanceClass: "db.t3.micro",
manageMasterUserPassword: true, // Enable AWS Secrets Manager for master password
username: "admin",
// Do NOT set the password property - AWS Secrets Manager handles it
vpcSecurityGroupIds: [securityGroup.id],
dbSubnetGroupName: subnetGroup.name,
});
resource-tagging
Severity: low · Enforcement: advisory
Ensures all AWS resources must include tags for proper change tracking
- 09.b Change Management — Changes to systems, applications and supporting infrastructure shall be controlled.
Remediation
Fix: Add Required Tags to AWS Resources
Add a tags property with meaningful values to enable proper change tracking and documentation:
const instance = new aws.ec2.Instance("my-instance", {
ami: "ami-0c55b159cbfafe1f0",
instanceType: "t3.micro",
tags: {
Environment: "production", // Add meaningful tags for change tracking
Owner: "team-name",
Application: "web-app",
},
});
restrict-default-iam-user-creation
Severity: medium · Enforcement: advisory
Ensures that default IAM user accounts are not allowed to be created
- 01.b User Registration — User registration shall be used for authorizing and enabling access to information systems and services and for revoking access rights.
Remediation
Fix: Use Descriptive User Names
Use specific, descriptive user names that follow your organization’s naming conventions instead of generic default names:
const iamUser = new aws.iam.User("my-iam-user", {
name: "john.doe", // Use descriptive, organization-specific user names
// Avoid generic names like: root, admin, administrator, default, user, guest, test, demo
});
s3-bucket-access-logging
Severity: medium · Enforcement: advisory
Ensures each S3 bucket has access logging enabled
- 09.e Service Delivery — Policy ensures compliance with HITRUST security requirements.
Remediation
Fix: Enable S3 Bucket Access Logging
Create a BucketLogging resource with a target bucket and prefix to enable access logging:
const myBucket = new aws.s3.Bucket("my-bucket", {
// Bucket configuration
});
const logBucket = new aws.s3.Bucket("log-bucket", {
// Configure log bucket settings
});
const bucketLogging = new aws.s3.BucketLogging("my-bucket-logging", {
bucket: myBucket.id,
targetBucket: logBucket.id, // Specify target bucket for logs
targetPrefix: "logs/my-bucket/", // Specify prefix for organization
});
s3-bucket-disallow-public-read
Severity: critical · Enforcement: advisory
Checks that S3 Bucket ACLs don’t allow ‘public-read’ or ‘public-read-write’ or ‘authenticated-read’.
- 09.m Network Controls — Networks shall be managed and controlled in order to protect the organization from threats and to maintain security for the systems and applications using the network, including information in transit.
Remediation
Fix: Use Private ACL for S3 Bucket
Set the acl to “private” or omit it entirely (defaults to private) to prevent public read access:
const bucket = new aws.s3.Bucket("my-bucket", {
acl: "private", // Use private ACL instead of public-read/public-read-write/authenticated-read
// Or omit the acl property to use the default private setting
});
s3-bucket-encryption
Severity: high · Enforcement: advisory
S3 buckets must have server-side encryption configured using BucketServerSideEncryptionConfiguration resource
- 06.d Data Protection and Privacy of Covered Information — Covered information shall be protected against unauthorized disclosure, modification and destruction. For the purpose of this control, covered information includes protected health information, cardholder data, and other sensitive information.
Remediation
Fix: Configure S3 Bucket Server-Side Encryption
Create a separate BucketServerSideEncryptionConfigurationV2 resource for your S3 bucket with encryption rules. Use AES256 or KMS encryption:
const bucket = new aws.s3.BucketV2("my-bucket", {
bucket: "my-secure-bucket",
});
// Add encryption configuration resource
const bucketEncryption = new aws.s3.BucketServerSideEncryptionConfiguration("my-bucket-encryption", {
bucket: bucket.id,
rules: [{
applyServerSideEncryptionByDefault: {
sseAlgorithm: "aws:kms", // Enable KMS encryption
kmsMasterKeyId: kmsKey.arn, // Specify customer-managed key
},
bucketKeyEnabled: true, // Enable bucket key for cost optimization
}],
});
s3-bucket-least-privilege
Severity: critical · Enforcement: advisory
Prevents overly permissive S3 bucket policies
- 01.v Information Access Restriction — Access to systems and applications shall be restricted in accordance with the access control policy.
Remediation
Fix: Use Specific Actions, Resources, and Principals
Replace wildcard (*) values in S3 bucket policy statements with specific, scoped permissions:
const bucketPolicy = new aws.s3.BucketPolicy("policy", {
bucket: bucket.id,
policy: bucket.arn.apply(arn => JSON.stringify({
Version: "2012-10-17",
Statement: [{
Effect: "Allow",
Principal: {
AWS: "arn:aws:iam::123456789012:role/specific-role" // Specify exact principal ARN
},
Action: ["s3:GetObject", "s3:PutObject"], // Use specific S3 actions
Resource: `${arn}/*` // Scope to specific bucket
}]
}))
});
s3-bucket-lifecycle
Severity: medium · Enforcement: advisory
Ensures each S3 bucket has lifecycle rules configured for retention/disposal
- 06.d Data Protection and Privacy of Covered Information — Covered information shall be protected against unauthorized disclosure, modification and destruction. For the purpose of this control, covered information includes protected health information, cardholder data, and other sensitive information.
Remediation
Fix: Configure Lifecycle Rules for S3 Bucket
Create a BucketLifecycleConfiguration resource with at least one enabled rule:
const myBucket = new aws.s3.Bucket("my-bucket", {
// Bucket configuration
});
const lifecycleConfig = new aws.s3.BucketLifecycleConfiguration("my-bucket-lifecycle", {
bucket: myBucket.id,
rules: [
{
id: "delete-old-objects",
status: "Enabled", // Rule must be enabled
expiration: {
days: 90, // Define retention period (e.g., expire after 90 days)
},
},
],
});
s3-bucket-macie-access
Severity: low · Enforcement: advisory
Ensures S3 buckets allow AWS Macie access for data classification and discovery
- 06.d Data Protection and Privacy of Covered Information — Covered information shall be protected against unauthorized disclosure, modification and destruction. For the purpose of this control, covered information includes protected health information, cardholder data, and other sensitive information.
Remediation
Fix: Allow AWS Macie Service Access in S3 Bucket Policy
Add an Allow statement for the AWS Macie service principal in your S3 bucket policy, or ensure Deny statements exclude the Macie service-linked role:
const bucketPolicy = new aws.s3.BucketPolicy("my-bucket-policy", {
bucket: bucket.id,
policy: bucket.arn.apply(arn => JSON.stringify({
Version: "2012-10-17",
Statement: [
{
Effect: "Allow",
Principal: {
Service: "macie.amazonaws.com" // Allow Macie service access
},
Action: [
"s3:GetObject",
"s3:GetBucketLocation",
"s3:ListBucket"
],
Resource: [
arn,
`${arn}/*`
]
}
]
}))
});
s3-bucket-public-access-block
Severity: critical · Enforcement: advisory
Ensures each S3 bucket has a public access block with all settings enabled
- 09.m Network Controls — Networks shall be managed and controlled in order to protect the organization from threats and to maintain security for the systems and applications using the network, including information in transit.
Remediation
Fix: Enable All Public Access Block Settings
Create a BucketPublicAccessBlock resource with all four settings set to true:
const myBucket = new aws.s3.Bucket("my-bucket", {
// Bucket configuration
});
const publicAccessBlock = new aws.s3.BucketPublicAccessBlock("my-bucket-public-access-block", {
bucket: myBucket.id,
blockPublicAcls: true, // Blocks new public ACLs
blockPublicPolicy: true, // Blocks new public bucket policies
ignorePublicAcls: true, // Ignores existing public ACLs
restrictPublicBuckets: true, // Restricts public access to buckets with public policies
});
s3-bucket-replication
Severity: medium · Enforcement: advisory
Ensures S3 buckets have replication configured for enhanced availability
- 12.a Including Information Security in the Business Continuity Management — Information security shall be a central part of the organization
Remediation
Fix: Configure Replication for S3 Bucket
Create a BucketReplicationConfig resource with an IAM role and replication rules:
// Create destination bucket
const destBucket = new aws.s3.Bucket("dest-bucket", {
bucket: "my-dest-bucket",
});
// Create replication IAM role
const replicationRole = new aws.iam.Role("replication-role", {
assumeRolePolicy: JSON.stringify({
Version: "2012-10-17",
Statement: [{
Effect: "Allow",
Principal: { Service: "s3.amazonaws.com" },
Action: "sts:AssumeRole",
}],
}),
});
// Enable versioning on source bucket (required for replication)
const sourceBucketVersioning = new aws.s3.BucketVersioning("source-versioning", {
bucket: sourceBucket.id,
versioningConfiguration: { status: "Enabled" },
});
// Configure replication using BucketReplicationConfig
const replication = new aws.s3.BucketReplicationConfig("replication", {
bucket: sourceBucket.id,
role: replicationRole.arn,
rules: [{
id: "replicate-all",
status: "Enabled",
destination: {
bucket: destBucket.arn,
},
filter: {},
}],
}, { dependsOn: [sourceBucketVersioning] });
s3-bucket-versioning
Severity: medium · Enforcement: advisory
S3 buckets must have versioning enabled using BucketVersioning resource
- 06.d Data Protection and Privacy of Covered Information — Covered information shall be protected against unauthorized disclosure, modification and destruction. For the purpose of this control, covered information includes protected health information, cardholder data, and other sensitive information.
Remediation
Fix: Enable S3 Bucket Versioning
Create a separate BucketVersioning resource with status set to “Enabled” for each S3 bucket:
const bucket = new aws.s3.BucketV2("my-bucket", {
bucket: "my-data-bucket",
});
const versioning = new aws.s3.BucketVersioning("my-bucket-versioning", {
bucket: bucket.id,
versioningConfiguration: {
status: "Enabled", // Enable versioning for data integrity and recovery
},
});
secrets-manager-secret-configure-customer-managed-key
Severity: low · Enforcement: advisory
Check that Secrets Manager Secrets use a customer-manager KMS key.
- 10.f Policy on the Use of Cryptographic Controls — Cryptographic controls shall be used in compliance with all relevant agreements, legislation and regulations, and risk assessments shall consider the organization
Remediation
Fix: Configure Customer-Managed KMS Key for Secrets Manager Secret
Set the kmsKeyId property to reference a customer-managed KMS key for encrypting the secret:
const secret = new aws.secretsmanager.Secret("my-secret", {
name: "my-application-secret",
kmsKeyId: kmsKey.arn, // Use customer-managed KMS key
description: "Sensitive application credentials",
});
security-group-default-deny
Severity: high · Enforcement: advisory
Ensures Security Groups follow default deny with explicit allow principle
- 09.m Network Controls — Networks shall be managed and controlled in order to protect the organization from threats and to maintain security for the systems and applications using the network, including information in transit.
Remediation
Fix: Replace Unrestricted CIDR Blocks with Specific IP Ranges
Replace 0.0.0.0/0 in ingress and egress rules with specific CIDR blocks or security group references to follow the default deny with explicit allow principle:
const webSecurityGroup = new aws.ec2.SecurityGroup("web-sg", {
vpcId: vpc.id,
ingress: [{
protocol: "tcp",
fromPort: 443,
toPort: 443,
cidrBlocks: ["10.0.0.0/16"], // Use specific CIDR block instead of 0.0.0.0/0
}],
egress: [{
protocol: "tcp",
fromPort: 443,
toPort: 443,
cidrBlocks: ["10.0.0.0/16"], // Use specific CIDR block instead of 0.0.0.0/0
}],
});
security-group-ssh-rdp
Severity: critical · Enforcement: advisory
Ensures security groups do not allow SSH/RDP from the internet
- 10.f Policy on the Use of Cryptographic Controls — Cryptographic controls shall be used in compliance with all relevant agreements, legislation and regulations, and risk assessments shall consider the organization
Remediation
Fix: Remove Public SSH and RDP Access
Remove or restrict ingress rules that allow SSH (port 22) or RDP (port 3389) from 0.0.0.0/0. Use specific CIDR blocks for trusted networks or implement alternative secure access methods:
const securityGroup = new aws.ec2.SecurityGroup("my-sg", {
vpcId: vpc.id,
ingress: [
{
fromPort: 22,
toPort: 22,
protocol: "tcp",
cidrBlocks: ["10.0.0.0/16"], // Restrict to specific network, not 0.0.0.0/0
},
{
fromPort: 3389,
toPort: 3389,
protocol: "tcp",
cidrBlocks: ["10.0.0.0/16"], // Restrict to specific network, not 0.0.0.0/0
},
],
});
security-group-strict
Severity: high · Enforcement: advisory
Ensures security groups follow strict firewall rules with default deny
- 09.m Network Controls — Networks shall be managed and controlled in order to protect the organization from threats and to maintain security for the systems and applications using the network, including information in transit.
Remediation
Fix: Configure Strict Security Group Rules
Restrict ingress rules to specific CIDR blocks instead of allowing access from the entire internet (0.0.0.0/0). Use specific protocols and narrow port ranges:
const securityGroup = new aws.ec2.SecurityGroup("my-sg", {
vpcId: vpc.id,
ingress: [
{
protocol: "tcp", // Use specific protocol, not "-1" (all)
fromPort: 443,
toPort: 443,
cidrBlocks: ["10.0.0.0/8"], // Restrict to internal network, not "0.0.0.0/0"
},
],
egress: [
{
protocol: "-1",
fromPort: 0,
toPort: 0,
cidrBlocks: ["0.0.0.0/0"],
},
],
});
sns-subscription-dead-letter-queue
Severity: medium · Enforcement: advisory
Ensures SNS subscriptions have dead letter queue configuration
- 12.a Including Information Security in the Business Continuity Management — Information security shall be a central part of the organization
Remediation
Fix: Configure Dead Letter Queue for SNS Subscription
Set the redrivePolicy with a deadLetterTargetArn pointing to an SQS queue to capture failed message deliveries:
const dlq = new aws.sqs.Queue("my-dlq", {
messageRetentionSeconds: 1209600, // 14 days
});
const subscription = new aws.sns.TopicSubscription("my-subscription", {
topic: topic.arn,
protocol: "sqs",
endpoint: targetQueue.arn,
redrivePolicy: JSON.stringify({ // Configure dead letter queue
deadLetterTargetArn: dlq.arn,
}),
});
sqs-dead-letter-queue
Severity: medium · Enforcement: advisory
Ensures SQS queues have dead letter queue configuration
- 12.a Including Information Security in the Business Continuity Management — Information security shall be a central part of the organization
Remediation
Fix: Configure Dead Letter Queue for SQS Queue
Set the redrivePolicy with a deadLetterTargetArn pointing to a DLQ and specify maxReceiveCount to capture failed messages:
// Create a dead letter queue first
const dlq = new aws.sqs.Queue("my-dlq", {
messageRetentionSeconds: 1209600, // 14 days
});
// Configure the main queue with redrive policy
const queue = new aws.sqs.Queue("my-queue", {
redrivePolicy: pulumi.interpolate`{
"deadLetterTargetArn": "${dlq.arn}",
"maxReceiveCount": 3
}`, // Configure DLQ to capture messages that fail processing
messageRetentionSeconds: 345600,
});
sqs-encryption
Severity: high · Enforcement: advisory
Ensures SQS queues have server-side encryption enabled
- 06.d Data Protection and Privacy of Covered Information — Covered information shall be protected against unauthorized disclosure, modification and destruction. For the purpose of this control, covered information includes protected health information, cardholder data, and other sensitive information.
Remediation
Fix: Enable Server-Side Encryption for SQS Queue
Set the kmsMasterKeyId property to enable server-side encryption with AWS KMS:
const queue = new aws.sqs.Queue("my-queue", {
name: "my-secure-queue",
kmsMasterKeyId: "alias/aws/sqs", // Enable encryption with AWS-managed KMS key
// Or use a customer-managed key:
// kmsMasterKeyId: customerKey.arn,
});
sqs-message-retention
Severity: medium · Enforcement: advisory
Ensures SQS queues have message retention periods configured
- 06.d Data Protection and Privacy of Covered Information — Covered information shall be protected against unauthorized disclosure, modification and destruction. For the purpose of this control, covered information includes protected health information, cardholder data, and other sensitive information.
Remediation
Fix: Configure SQS Message Retention Period
Set the messageRetentionSeconds property to define how long messages are retained in the queue (60 seconds to 1,209,600 seconds/14 days):
const queue = new aws.sqs.Queue("my-queue", {
messageRetentionSeconds: 345600, // Set retention period (e.g., 4 days)
});
subnet-multi-az
Severity: medium · Enforcement: advisory
Ensures subnets are distributed across multiple availability zones
- 09.m Network Controls — Networks shall be managed and controlled in order to protect the organization from threats and to maintain security for the systems and applications using the network, including information in transit.
Remediation
Fix: Distribute Subnets Across Multiple Availability Zones
Create subnets in at least 2 different availability zones to ensure high availability and fault tolerance:
const subnet1 = new aws.ec2.Subnet("subnet-az1", {
vpcId: vpc.id,
cidrBlock: "10.0.1.0/24",
availabilityZone: "us-east-1a", // Specify explicit AZ
});
const subnet2 = new aws.ec2.Subnet("subnet-az2", {
vpcId: vpc.id,
cidrBlock: "10.0.2.0/24",
availabilityZone: "us-east-1b", // Use different AZ for redundancy
});
vpc-endpoint-security-policy
Severity: medium · Enforcement: advisory
Ensures that VPC endpoints are associated with security policies that limit access to specified resources
- 01.v Information Access Restriction — Access to systems and applications shall be restricted in accordance with the access control policy.
Remediation
Fix: Configure Restrictive VPC Endpoint Policy
Add a policy to your VPC endpoint that specifies explicit principals and resources instead of wildcards:
const vpcEndpoint = new aws.ec2.VpcEndpoint("my-endpoint", {
vpcId: vpc.id,
serviceName: "com.amazonaws.us-west-2.s3",
policy: JSON.stringify({
Version: "2012-10-17",
Statement: [{
Effect: "Allow",
Principal: {
AWS: "arn:aws:iam::123456789012:role/MyRole" // Specify explicit principal ARN
},
Action: "s3:GetObject",
Resource: "arn:aws:s3:::my-bucket/*" // Specify explicit resource ARN
}]
}),
});
vpc-flow-logs
Severity: medium · Enforcement: advisory
Ensures VPC flow logs use approved destinations for centralized monitoring
- 09.aa Audit Logging — The organization shall ensure that audit logs are enabled and monitored for sensitive systems.
Remediation
Fix: Configure VPC Flow Logs with Approved Destination
Configure VPC Flow Logs to use one of the approved log destinations specified in the policy configuration:
const flowLog = new aws.ec2.FlowLog("vpc-flow-log", {
vpcId: vpc.id,
trafficType: "ALL",
logDestination: "arn:aws:s3:::approved-logging-bucket", // Use approved destination
logDestinationType: "s3",
});
vpc-subnet-flow-logs
Severity: medium · Enforcement: advisory
Ensures all VPCs and subnets have flow logs enabled
- 09.z Publicly Available Information — Publicly available information shall be protected against unauthorized modification or deletion.
Remediation
Fix: Enable VPC Flow Logs for Network Monitoring
Create a VPC Flow Log resource and associate it with your VPC or subnet to capture network traffic information:
const vpc = new aws.ec2.Vpc("my-vpc", {
cidrBlock: "10.0.0.0/16",
});
// Enable flow logs for the VPC
const flowLog = new aws.ec2.FlowLog("vpc-flow-log", {
vpcId: vpc.id, // Associate flow log with VPC
trafficType: "ALL", // Capture all traffic (ACCEPT, REJECT, ALL)
logDestinationType: "cloud-watch-logs",
logDestination: logGroup.arn,
iamRoleArn: flowLogRole.arn,
});
waf-association-validation
Severity: critical · Enforcement: advisory
Validates WAF Web ACL associations are properly configured
- 09.m Network Controls — Networks shall be managed and controlled in order to protect the organization from threats and to maintain security for the systems and applications using the network, including information in transit.
Remediation
Fix: Configure WAF Web ACL Association Properties
Ensure both resourceArn and webAclArn are specified in the WAF association:
const wafAssociation = new aws.wafv2.WebAclAssociation("my-waf-association", {
resourceArn: resource.arn, // Specify the resource ARN to protect
webAclArn: webAcl.arn, // Specify the WAF Web ACL ARN
});