CIS 8.1 - AWS
This page lists all 115 policies in the CIS 8.1 pack for AWS, as published in cis-aws version 1.0.2.
Policies by control
1.1 — Establish and maintain an accurate, detailed, and up-to-date inventory of all enterprise assets with the potential to store or process data, to include: end-user devices (including portable and mobile), network devices, non-computing/IoT devices, and servers. Ensure the inventory records the network address (if static), hardware address, machine name, enterprise asset owner, department for each asset, and whether the asset has been approved to connect to the network. For mobile end-user devices, MDM type tools can support this process, where appropriate. This inventory includes assets connected to the infrastructure physically, virtually, remotely, and those within cloud environments. Additionally, it includes assets that are regularly connected to the enterprise’s network infrastructure, even if they are not under control of the enterprise. Review and update the inventory of all enterprise assets bi-annually, or more frequently.
1.2 — Ensure that a process exists to address unauthorized assets on a weekly basis. The enterprise may choose to remove the asset from the network, deny the asset from connecting remotely to the network, or quarantine the asset.
2.2 — Ensure that only currently supported software is designated as authorized in the software inventory for enterprise assets. If software is unsupported, yet necessary for the fulfillment of the enterprise’s mission, document an exception detailing mitigating controls and residual risk acceptance. For any unsupported software without an exception documentation, designate as unauthorized. Review the software list to verify software support at least monthly, or more frequently.
3.1 — Establish and maintain a documented data management process. In the process, address data sensitivity, data owner, handling of data, data retention limits, and disposal requirements, based on sensitivity and retention standards for the enterprise. Review and update documentation annually, or when significant enterprise changes occur that could impact this Safeguard.
3.3 — Configure data access control lists based on a user’s need to know. Apply data access control lists, also known as access permissions, to local and remote file systems, databases, and applications.
- autoscaling-launch-config-public-ip-disabled
- dms-replication-instance-not-publicly-accessible
- ec2-imdsv2-required
- ec2-instance-iam-profile-attached
- ec2-instance-in-vpc
- ec2-instance-not-publicly-accessible
- ecs-task-definition-user-for-host-mode-check
- eks-cluster-endpoint-restrict-public-access
- elasticsearch-in-vpc-only
- emr-cluster-master-nodes-no-public-ip
- iam-no-inline-policy-check
- iam-policy-no-statements-with-full-access
- lambda-function-public-access-prohibited
- lambda-inside-vpc
- neptune-clusterinstance-no-public-access
- rds-cluster-instance-disallow-public-access
- rds-instance-disallow-public-access
- redshift-cluster-public-access-check
- s3-bucket-level-public-access-prohibited
- s3-bucket-public-write-prohibited
- s3-bucket-restrict-public-read-access
- sagemaker-notebook-no-direct-internet-access
- subnet-auto-assign-public-ip-disabled
3.4 — Retain data according to the enterprise’s documented data management process. Data retention must include both minimum and maximum timelines.
3.8 — Document data flows. Data flow documentation includes service provider data flows and should be based on the enterprise’s data management process. Review and update documentation annually, or when significant enterprise changes occur that could impact this Safeguard.
- cloud-trail-cloud-watch-logs-enabled
- cloudtrail-s3-dataevents-enabled
- ec2-instance-detailed-monitoring-enabled
- elasticsearch-logs-to-cloudwatch
- elb-logging-enabled
- lambda-concurrency-check
- no-unrestricted-route-to-igw
- rds-cluster-logging-enabled
- rds-instance-logging-enabled
- rds-logging-enabled
- redshift-cluster-configuration-check
- restricted-ssh
- s3-bucket-logging-enabled
- wafv2-logging-enabled
3.11 — Encrypt sensitive data at rest on servers, applications, and databases. Storage-layer encryption, also known as server-side encryption, meets the minimum requirement of this Safeguard. Additional encryption methods may include application-layer encryption, also known as client-side encryption, where access to the data storage device(s) does not permit access to the plain-text data.
- api-gateway-cache-encryption-enabled
- api-gw-stage-cache-enabled
- cloud-trail-encryption-enabled
- cloudwatch-log-group-kms-encryption-enabled
- dynamodb-kms-encryption-enabled
- ebs-volume-encryption-required
- efs-encryption-required
- elasticsearch-encryption-enabled
- kms-cmk-not-scheduled-for-deletion
- rds-cluster-disallow-unencrypted-storage
- rds-encryption-enabled
- s3-bucket-encryption
- sagemaker-endpoint-kms-encryption-enabled
- sagemaker-notebook-kms-encryption-enabled
- secrets-manager-kms-encryption-enabled
- sns-kms-encryption-enabled
4.1 — Establish and maintain a documented secure configuration process for enterprise assets (end-user devices, including portable and mobile, non-computing/IoT devices, and servers) and software (operating systems and applications). Review and update documentation annually, or when significant enterprise changes occur that could impact this Safeguard.
4.6 — Securely manage enterprise assets and software. Example implementations include managing configuration through version-controlled Infrastructure-as-Code (IaC) and accessing administrative interfaces over secure network protocols, such as Secure Shell (SSH) and Hypertext Transfer Protocol Secure (HTTPS). Do not use insecure management protocols, such as Telnet (Teletype Network) and HTTP, unless operationally essential.
- autoscaling-health-checks-enabled
- cloud-trail-log-file-validation-enabled
- cloudtrail-security-trail-enabled
- ebs-attached-volume-encryption-enabled
- iam-policy-no-statements-with-admin-access
- kms-key-rotation-enabled
- s3-bucket-public-read-prohibited
- vpc-security-group-restrict-ingress-ssh-all
4.7 — Manage default accounts on enterprise assets and software, such as root, administrator, and other pre-configured vendor accounts. Example implementations can include: disabling default accounts or making them unusable.
5.2 — Use unique passwords for all enterprise assets. Best practice implementation includes, at a minimum, an 8-character password for accounts using Multi-Factor Authentication (MFA) and a 14-character password for accounts not using MFA.
- iam-account-password-policy-strong-min-reuse-24
- iam-root-user-mfa-enabled
- iam-user-console-access-mfa-enabled
- iam-user-mfa-enabled
5.3 — Delete or disable any dormant accounts after a period of 45 days of inactivity, where supported.
5.4 — Restrict administrator privileges to dedicated administrator accounts on enterprise assets. Conduct general computing activities, such as internet browsing, email, and productivity suite use, from the user’s primary, non-privileged account.
7.1 — Establish and maintain a documented vulnerability management process for enterprise assets. Review and update documentation annually, or when significant enterprise changes occur that could impact this Safeguard.
7.3 — 7.3 - Vulnerability Management: Establish and maintain a documented vulnerability management process for enterprise assets, and perform automated operating system patch management on a monthly or more frequent basis.
8.2 — Collect audit logs. Ensure that logging, per the enterprise’s audit log management process, has been enabled across enterprise assets.
- apigateway-stage-logging-enabled
- cloudfront-distribution-logging-enabled
- cloudtrail-trail-enabled
- cloudtrail-trail-integrated-with-logs
- vpc-flow-logs-enabled
- waf-web-acl-logging-enabled
11.2 — Perform automated backups of in-scope enterprise assets. Run backups weekly, or more frequently, based on the sensitivity of the data.
- dynamodb-pitr-enabled
- dynamodb-table-in-backup-plan
- ebs-optimized-instance
- rds-db-instance-backup-enabled
- redshift-backup-enabled
- s3-bucket-replication
- s3-bucket-versioning-enabled
11.4 — 11.4 - Data Recovery: Perform automated backups of in-scope enterprise assets weekly or more frequently, and maintain isolated recovery data through version controlling backup destinations via offline, cloud, or off-site systems.
12.1 — Ensure network infrastructure is kept up-to-date. Example implementations include running the latest stable release of software and/or using currently supported network as a service (NaaS) offerings. Review software versions monthly, or more frequently, to verify software support.
12.2 — Design and maintain a secure network architecture. A secure network architecture must address segmentation, least privilege, and availability, at a minimum. Example implementations may include documentation, policy, and design components.
- acm-certificate-expiration-check
- ec2-instance-no-public-ip
- elb-deletion-protection-enabled
- rds-instance-deletion-protection-enabled
- rds-multi-az-support
- redshift-enhanced-vpc-routing-enabled
13.1 — Centralize security event alerting across enterprise assets for log correlation and analysis. Best practice implementation requires the use of a SIEM, which includes vendor-defined event correlation alerts. A log analytics platform configured with security-relevant correlation alerts also satisfies this Safeguard.
16.1 — Establish and maintain a secure application development process. In the process, address such items as: secure application design standards, secure coding practices, developer training, vulnerability management, security of third-party code, and application security testing procedures. Review and update documentation annually, or when significant enterprise changes occur that could impact this Safeguard.
Policy details
acm-certificate-expiration-check
Severity: medium · Enforcement: advisory
Ensure ACM certificates are configured to prevent expiration-related service disruptions through automatic renewal.
- 12.2 — Design and maintain a secure network architecture. A secure network architecture must address segmentation, least privilege, and availability, at a minimum. Example implementations may include documentation, policy, and design components.
Remediation
Fix: Configure ACM Certificate for Automatic Renewal
Use DNS validation to enable automatic renewal:
const certificate = new aws.acm.Certificate("cert", {
domainName: "example.com",
validationMethod: "DNS", // Enables fully automatic renewal ~60 days before expiration (EMAIL also allows renewal but requires manual approval)
options: {
certificateTransparencyLoggingPreference: "ENABLED",
},
});
DNS-validated ACM certificates automatically renew without manual intervention.
Note: Imported certificates cannot auto-renew and must be manually replaced before expiration.
alb-waf-enabled
Severity: high · Enforcement: advisory
Ensure Application Load Balancers have WAF protection enabled for application layer defense.
- 13.1 — Centralize security event alerting across enterprise assets for log correlation and analysis. Best practice implementation requires the use of a SIEM, which includes vendor-defined event correlation alerts. A log analytics platform configured with security-relevant correlation alerts also satisfies this Safeguard.
Remediation
Fix: Associate WAF Web ACL with ALB
// Associate WAF with ALB
const wafAssociation = new aws.wafv2.WebAclAssociation("wafAssociation", {
resourceArn: alb.arn, // This fixes the issue
webAclArn: webAcl.arn,
});
api-gateway-cache-encryption-enabled
Severity: high · Enforcement: advisory
Ensures API Gateway method settings have cache data encryption enabled when caching is configured.
- 3.11 — Encrypt sensitive data at rest on servers, applications, and databases. Storage-layer encryption, also known as server-side encryption, meets the minimum requirement of this Safeguard. Additional encryption methods may include application-layer encryption, also known as client-side encryption, where access to the data storage device(s) does not permit access to the plain-text data.
Remediation
Fix: Enable cache data encryption for API Gateway method settings
When enabling caching for API Gateway methods, ensure cache data encryption is also enabled to protect sensitive data at rest.
import * as aws from "@pulumi/aws";
const methodSettings = new aws.apigateway.MethodSettings("example-method-settings", {
restApi: restApi.id,
stageName: stage.stageName,
methodPath: "*/*",
settings: {
cachingEnabled: true,
cacheDataEncrypted: true, // Enable cache encryption at rest
cacheTtlInSeconds: 300,
},
});
api-gw-stage-cache-enabled
Severity: medium · Enforcement: advisory
Ensure API Gateway stages have caching enabled for performance.
- 3.11 — Enable caching on API Gateway stages to improve API performance and reduce backend load. This policy validates the Stage resource configuration. Cache encryption is validated separately via the api-gw-cache-encrypted policy.
Remediation
Fix: Enable API Gateway Stage Cache
Enable cache cluster on API Gateway stage:
const stage = new aws.apigateway.Stage("api-stage", {
restApi: restApi.id,
deploymentId: deployment.id,
stageName: "prod",
cacheClusterEnabled: true, // Enable cache cluster
cacheClusterSize: "1.6", // Valid sizes: 0.5, 1.6, 6.1, 13.5, 28.4, 58.2, 118, 237
});
Note:
- This policy validates that the cache cluster is enabled at the Stage level
- Cache encryption is enforced by the companion policy ‘api-gw-cache-encrypted’ which validates MethodSettings resources
- Both policies work together to ensure caching is enabled AND encrypted
apigateway-stage-logging-enabled
Severity: medium · Enforcement: advisory
Ensures API Gateway stages have access logging enabled
- 8.2 — Collect audit logs. Ensure that logging, per the enterprise’s audit log management process, has been enabled across enterprise assets.
Remediation
Fix: Configure Access Logging for API Gateway Stage
Add the accessLogSettings property to your API Gateway Stage resource with a valid CloudWatch log group destination:
const logGroup = new aws.cloudwatch.LogGroup("api-gateway-logs", {
retentionInDays: 30,
});
const stage = new aws.apigateway.Stage("api-stage", {
restApi: restApi.id,
deployment: deployment.id,
stageName: "prod",
accessLogSettings: {
// Configure the CloudWatch log group ARN for audit logs
destinationArn: logGroup.arn,
format: "$context.requestId",
},
});
autoscaling-health-checks-enabled
Severity: high · Enforcement: advisory
Ensures Auto Scaling groups with load balancers have ELB health checks configured for proper monitoring.
- 4.6 — Securely manage enterprise assets and software. Example implementations include managing configuration through version-controlled Infrastructure-as-Code (IaC) and accessing administrative interfaces over secure network protocols, such as Secure Shell (SSH) and Hypertext Transfer Protocol Secure (HTTPS). Do not use insecure management protocols, such as Telnet (Teletype Network) and HTTP, unless operationally essential.
Remediation
Fix: Configure ELB Health Checks for Auto Scaling Group
Set the healthCheckType to “ELB” and configure an appropriate healthCheckGracePeriod (minimum 300 seconds) for Auto Scaling groups that use load balancers:
const asg = new aws.autoscaling.Group("my-asg", {
minSize: 1,
maxSize: 3,
targetGroupArns: [targetGroup.arn],
healthCheckType: "ELB", // Enable ELB health checks
healthCheckGracePeriod: 300, // Set grace period to at least 300 seconds
vpcZoneIdentifiers: subnetIds,
launchTemplate: {
id: launchTemplate.id,
version: "$Latest",
},
});
autoscaling-launch-config-public-ip-disabled
Severity: high · Enforcement: advisory
Ensure Auto Scaling launch configurations have public IP address assignment disabled to prevent direct internet access and maintain proper data access control.
- 3.3 — Configure data access control lists based on a user’s need to know. Apply data access control lists, also known as access permissions, to local and remote file systems, databases, and applications.
Remediation
Fix: Disable Public IP Assignment
const launchConfig = new aws.ec2.LaunchConfiguration("my-launch-config", {
imageId: "ami-12345678",
instanceType: "t3.medium",
associatePublicIpAddress: false, // Disable public IP assignment
securityGroups: [securityGroup.id],
});
cloud-trail-cloud-watch-logs-enabled
Severity: high · Enforcement: advisory
Ensures CloudTrail trails have CloudWatch Logs integration enabled for real-time monitoring and analysis.
- 3.8 — Document data flows. Data flow documentation includes service provider data flows and should be based on the enterprise’s data management process. Review and update documentation annually, or when significant enterprise changes occur that could impact this Safeguard.
Remediation
Fix: Configure CloudWatch Logs Integration for CloudTrail
Add the CloudWatch Logs group ARN and IAM role ARN to your CloudTrail trail configuration:
const logGroup = new aws.cloudwatch.LogGroup("trail-log-group", {
retentionInDays: 90,
});
const trailRole = new aws.iam.Role("trail-cloudwatch-role", {
assumeRolePolicy: JSON.stringify({
Version: "2012-10-17",
Statement: [{
Effect: "Allow",
Principal: { Service: "cloudtrail.amazonaws.com" },
Action: "sts:AssumeRole",
}],
}),
});
const trail = new aws.cloudtrail.Trail("my-trail", {
s3BucketName: bucket.id,
cloudWatchLogsGroupArn: logGroup.arn, // Add this field
cloudWatchLogsRoleArn: trailRole.arn, // Add this field
});
cloud-trail-encryption-enabled
Severity: high · Enforcement: advisory
Ensures CloudTrail trails have encryption enabled using KMS keys.
- 3.11 — Encrypt sensitive data at rest on servers, applications, and databases. Storage-layer encryption, also known as server-side encryption, meets the minimum requirement of this Safeguard. Additional encryption methods may include application-layer encryption, also known as client-side encryption, where access to the data storage device(s) does not permit access to the plain-text data.
Remediation
Fix: Enable KMS Encryption for CloudTrail
Add a customer-managed KMS key to your CloudTrail trail configuration:
import * as aws from "@pulumi/aws";
// Create or reference a KMS key for CloudTrail encryption
const trailKey = new aws.kms.Key("trail-key", {
description: "KMS key for CloudTrail log encryption",
enableKeyRotation: true,
});
const trail = new aws.cloudtrail.Trail("my-trail", {
s3BucketName: bucket.id,
kmsKeyId: trailKey.arn, // Add the KMS key ARN to enable encryption
});
cloud-trail-log-file-validation-enabled
Severity: high · Enforcement: advisory
Ensures CloudTrail trails have log file validation enabled to protect audit log integrity.
- 4.6 — Securely manage enterprise assets and software. Example implementations include managing configuration through version-controlled Infrastructure-as-Code (IaC) and accessing administrative interfaces over secure network protocols, such as Secure Shell (SSH) and Hypertext Transfer Protocol Secure (HTTPS). Do not use insecure management protocols, such as Telnet (Teletype Network) and HTTP, unless operationally essential.
Remediation
Fix: Enable CloudTrail Log File Validation
Update your CloudTrail trail configuration to enable log file validation:
import * as aws from "@pulumi/aws";
const trail = new aws.cloudtrail.Trail("my-trail", {
s3BucketName: "my-cloudtrail-bucket",
enableLogFileValidation: true, // Enable log file validation to ensure audit log integrity
});
This ensures CloudTrail logs are cryptographically signed, allowing you to verify they haven’t been modified after delivery.
cloudfront-distribution-logging-enabled
Severity: medium · Enforcement: advisory
Ensure CloudFront distributions have access logging enabled to collect audit logs for compliance.
- 8.2 — Collect audit logs. Ensure that logging, per the enterprise’s audit log management process, has been enabled across enterprise assets.
Remediation
Fix: Enable Access Logging for CloudFront Distribution
const distribution = new aws.cloudfront.Distribution("cdn", {
loggingConfig: {
bucket: logBucket.bucketDomainName, // S3 bucket for logs
prefix: "cloudfront-logs/", // Optional log prefix
},
// ... other config
});
cloudtrail-s3-dataevents-enabled
Severity: high · Enforcement: advisory
Ensures CloudTrail trails have S3 data events enabled for comprehensive object-level logging.
- 3.8 — Document data flows. Data flow documentation includes service provider data flows and should be based on the enterprise’s data management process. Review and update documentation annually, or when significant enterprise changes occur that could impact this Safeguard.
Remediation
Fix: Enable S3 Data Events in CloudTrail
Configure your CloudTrail trail to log S3 object-level operations by adding event selectors:
import * as aws from "@pulumi/aws";
const trail = new aws.cloudtrail.Trail("my-trail", {
s3BucketName: trailBucket.bucket,
// Enable S3 data events for all buckets
eventSelectors: [{
readWriteType: "All", // Log both read and write operations
includeManagementEvents: true,
dataResources: [{
type: "AWS::S3::Object",
values: ["arn:aws:s3:::*/*"], // Monitor all S3 objects
}],
}],
});
Alternatively, use advanced event selectors for more granular control:
const trail = new aws.cloudtrail.Trail("my-trail", {
s3BucketName: trailBucket.bucket,
advancedEventSelectors: [{
name: "Log S3 data events",
fieldSelectors: [
{
field: "eventCategory",
equals: ["Data"], // Data events category
},
{
field: "resources.type",
equals: ["AWS::S3::Object"], // S3 object operations
},
],
}],
});
cloudtrail-security-trail-enabled
Severity: medium · Enforcement: advisory
Ensure CloudTrail security trail is enabled for comprehensive audit logging and monitoring.
- 4.6 — Securely manage enterprise assets and software. Example implementations include managing configuration through version-controlled Infrastructure-as-Code (IaC) and accessing administrative interfaces over secure network protocols, such as Secure Shell (SSH) and Hypertext Transfer Protocol Secure (HTTPS). Do not use insecure management protocols, such as Telnet (Teletype Network) and HTTP, unless operationally essential.
Remediation
Fix: Create CloudTrail with all event selectors
const trail = new aws.cloudtrail.Trail("trail", {
enableLogging: true, // This fixes the violation
eventSelectors: [{
includeManagementEvents: true,
dataResources: [{
type: "AWS::S3::Object",
values: ["arn:aws:s3:::*/*"],
}],
}],
// ... other required config
});
cloudtrail-trail-enabled
Severity: critical · Enforcement: advisory
Ensures CloudTrail is enabled with at least one active trail for audit logging.
- 8.2 — Collect audit logs. Ensure that logging, per the enterprise’s audit log management process, has been enabled across enterprise assets.
Remediation
Fix: Enable CloudTrail for audit logging
Create a CloudTrail trail to capture API activity and management events:
import * as aws from "@pulumi/aws";
// Create an S3 bucket for CloudTrail logs
const trailBucket = new aws.s3.Bucket("cloudtrail-logs", {
forceDestroy: true, // Only for demo - remove in production
});
// Create CloudTrail trail
const trail = new aws.cloudtrail.Trail("main-trail", {
s3BucketName: trailBucket.bucket,
isMultiRegionTrail: true, // Enable for all regions
includeGlobalServiceEvents: true,
enableLogFileValidation: true, // Ensure log integrity
});
Key configuration:
- Set
isMultiRegionTrail: trueto capture events across all AWS regions - Enable
includeGlobalServiceEventsto capture IAM and STS events - Use
enableLogFileValidationto ensure log integrity
cloudtrail-trail-integrated-with-logs
Severity: medium · Enforcement: advisory
Ensure CloudTrail trails integrate with CloudWatch Logs to collect audit logs for compliance.
- 8.2 — Collect audit logs. Ensure that logging, per the enterprise’s audit log management process, has been enabled across enterprise assets.
Remediation
Fix: Set CloudWatch Logs group ARN
const trail = new aws.cloudtrail.Trail("trail", {
cloudWatchLogsGroupArn: logGroup.arn, // This fixes the violation
// ... other required config
});
cloudwatch-log-group-kms-encryption-enabled
Severity: high · Enforcement: advisory
Ensures CloudWatch log groups have encryption enabled using KMS keys.
- 3.11 — Encrypt sensitive data at rest on servers, applications, and databases. Storage-layer encryption, also known as server-side encryption, meets the minimum requirement of this Safeguard. Additional encryption methods may include application-layer encryption, also known as client-side encryption, where access to the data storage device(s) does not permit access to the plain-text data.
Remediation
Fix: Enable KMS Encryption for CloudWatch Log Group
Add a KMS key to your CloudWatch log group resource to enable encryption at rest:
import * as aws from "@pulumi/aws";
const logGroup = new aws.cloudwatch.LogGroup("my-log-group", {
name: "/aws/my-application",
kmsKeyId: kmsKey.arn, // Add KMS key ARN to enable encryption
retentionInDays: 30,
});
cloudwatch-log-group-retention-period-365
Severity: medium · Enforcement: advisory
Ensures CloudWatch log groups have appropriate retention periods for compliance.
- 3.4 — Retain data according to the enterprise’s documented data management process. Data retention must include both minimum and maximum timelines.
Remediation
Fix: Configure CloudWatch Log Group Retention Period
Set the retentionInDays property to at least 365 days to meet audit record retention requirements.
import * as aws from "@pulumi/aws";
const logGroup = new aws.cloudwatch.LogGroup("my-log-group", {
name: "/aws/lambda/my-function",
retentionInDays: 365, // Set retention to at least 365 days for compliance
});
codebuild-project-source-repo-url-check
Severity: medium · Enforcement: advisory
Ensure CodeBuild project source repository URLs use secure and trusted sources.
- 16.1 — Establish and maintain a secure application development process. In the process, address such items as: secure application design standards, secure coding practices, developer training, vulnerability management, security of third-party code, and application security testing procedures. Review and update documentation annually, or when significant enterprise changes occur that could impact this Safeguard.
Remediation
Fix: Use HTTPS URL for CodeBuild Source Repository
const project = new aws.codebuild.Project("build", {
source: {
type: "GITHUB",
location: "https://github.com/myorg/myrepo.git", // Use HTTPS URL
},
// ... other config
});
dms-replication-instance-not-publicly-accessible
Severity: high · Enforcement: advisory
Ensures DMS replication instances are not publicly accessible to maintain security.
- 3.3 — Configure data access control lists based on a user’s need to know. Apply data access control lists, also known as access permissions, to local and remote file systems, databases, and applications.
Remediation
Fix: Disable Public Accessibility
const replicationInstance = new aws.dms.ReplicationInstance("my-replication-instance", {
replicationInstanceClass: "dms.t3.micro",
publiclyAccessible: false, // Set to false to prevent public access
// ... other config
});
dynamodb-kms-encryption-enabled
Severity: high · Enforcement: advisory
Ensures DynamoDB tables have encryption enabled using KMS keys.
- 3.11 — Encrypt sensitive data at rest on servers, applications, and databases. Storage-layer encryption, also known as server-side encryption, meets the minimum requirement of this Safeguard. Additional encryption methods may include application-layer encryption, also known as client-side encryption, where access to the data storage device(s) does not permit access to the plain-text data.
Remediation
Fix: Enable Customer-Managed KMS Encryption for DynamoDB Table
Configure the DynamoDB table with a customer-managed KMS key for encryption at rest:
import * as aws from "@pulumi/aws";
// Create or reference a customer-managed KMS key
const kmsKey = new aws.kms.Key("table-encryption-key", {
description: "KMS key for DynamoDB table encryption",
deletionWindowInDays: 10,
});
const table = new aws.dynamodb.Table("my-table", {
// ... other configuration ...
serverSideEncryption: {
enabled: true, // Enable encryption
kmsKeyArn: kmsKey.arn, // Use customer-managed KMS key (not AWS-managed)
},
});
dynamodb-pitr-enabled
Severity: medium · Enforcement: advisory
DynamoDB tables must have point-in-time recovery enabled
- 11.2 — Perform automated backups of in-scope enterprise assets. Run backups weekly, or more frequently, based on the sensitivity of the data.
Remediation
Fix: Enable Point-in-Time Recovery on DynamoDB Table
Add the pointInTimeRecovery property to your DynamoDB table configuration and set enabled to true.
const table = new aws.dynamodb.Table("my-table", {
name: "my-table",
attributes: [
{ name: "id", type: "S" },
],
hashKey: "id",
billingMode: "PAY_PER_REQUEST",
// Enable point-in-time recovery for backup and recovery capabilities
pointInTimeRecovery: {
enabled: true, // Set to true to enable PITR
},
});
dynamodb-table-in-backup-plan
Severity: medium · Enforcement: advisory
Ensure DynamoDB tables are included in AWS Backup plans for centralized backup management.
- 11.2 — CIS Controls v8 IG1 11.2
- 11.4 — 11.4 - Data Recovery: Perform automated backups of in-scope enterprise assets weekly or more frequently, and maintain isolated recovery data through version controlling backup destinations via offline, cloud, or off-site systems.
Remediation
Fix: Add DynamoDB table to AWS Backup plan
// Create backup vault
const vault = new aws.backup.Vault("dynamodb-vault", {
name: "dynamodb-backup-vault",
});
// Create IAM role for AWS Backup
const backupRole = new aws.iam.Role("backup-role", {
assumeRolePolicy: JSON.stringify({
Version: "2012-10-17",
Statement: [{
Effect: "Allow",
Principal: { Service: "backup.amazonaws.com" },
Action: "sts:AssumeRole",
}],
}),
managedPolicyArns: [
"arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForBackup",
"arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForRestores",
],
});
// Create backup plan
const backupPlan = new aws.backup.Plan("dynamodb-backup-plan", {
name: "daily-dynamodb-backups",
rules: [{
ruleName: "daily-backup",
targetVaultName: vault.name,
schedule: "cron(0 3 * * ? *)",
lifecycle: {
deleteAfter: 35,
},
}],
});
// Add DynamoDB tables to backup selection
const backupSelection = new aws.backup.Selection("dynamodb-tables", {
name: "dynamodb-backup-selection",
planId: backupPlan.id,
iamRoleArn: backupRole.arn,
resources: ["arn:aws:dynamodb:*:*:table/*"],
});
ebs-attached-volume-encryption-enabled
Severity: high · Enforcement: advisory
Ensure EBS volumes attached to EC2 instances are encrypted to protect data at rest.
- 4.6 — Securely manage enterprise assets and software. Example implementations include managing configuration through version-controlled Infrastructure as Code, and accessing administrative interfaces over secure network protocols, such as Secure Shell (SSH) and Hypertext Transfer Protocol Secure (HTTPS). Do not use insecure management protocols, such as Telnet (Teletype Network) and HTTP, unless operationally essential.
Remediation
Fix: Enable EBS Volume Encryption
const volume = new aws.ebs.Volume("data-volume", {
availabilityZone: "us-west-2a",
size: 100,
type: "gp3",
encrypted: true, // Enable encryption at rest
tags: {
Name: "encrypted-volume",
},
});
ebs-optimized-instance
Severity: medium · Enforcement: advisory
EC2 instances must be EBS optimized
- 11.2 — Perform automated backups of in-scope enterprise assets. Run backups weekly, or more frequently, based on the sensitivity of the data.
Remediation
Fix: Enable EBS optimization for EC2 instances
Set the ebsOptimized property to true on your EC2 instance resource:
const instance = new aws.ec2.Instance("my-instance", {
instanceType: "t3.medium",
ami: "ami-0c55b159cbfafe1f0",
ebsOptimized: true, // Enable EBS optimization
});
Note: Ensure your instance type supports EBS optimization. Most modern instance types (t3, m5, c5, etc.) support it by default.
ebs-volume-encryption-required
Severity: high · Enforcement: advisory
Checks that EBS volumes are encrypted.
- 3.11 — Encrypt sensitive data at rest on servers, applications, and databases. Storage-layer encryption, also known as server-side encryption, meets the minimum requirement of this Safeguard. Additional encryption methods may include application-layer encryption, also known as client-side encryption, where access to the data storage device(s) does not permit access to the plain-text data.
Remediation
Fix: Enable EBS Volume Encryption
Set the encrypted property to true on your EBS volume resource.
import * as aws from "@pulumi/aws";
const volume = new aws.ebs.Volume("my-volume", {
availabilityZone: "us-west-2a",
size: 100,
encrypted: true, // Enable encryption
});
ebs-volume-unused
Severity: low · Enforcement: advisory
EBS volumes must be removed when unused
- 4.1 — Establish and maintain a documented secure configuration process for enterprise assets (end-user devices, including portable and mobile, non-computing/IoT devices, and servers) and software (operating systems and applications). Review and update documentation annually, or when significant enterprise changes occur that could impact this Safeguard.
Remediation
Fix: Attach EBS volume to an EC2 instance or delete if unused
Either attach the unattached EBS volume to an EC2 instance, or delete it if no longer needed:
import * as aws from "@pulumi/aws";
// Option 1: Attach the volume to an EC2 instance
const volumeAttachment = new aws.ec2.VolumeAttachment("my-volume-attachment", {
instanceId: instance.id,
volumeId: volume.id, // Attach the previously unattached volume
deviceName: "/dev/sdh",
});
// Option 2: Delete the unused volume resource from your Pulumi program
// Simply remove the aws.ebs.Volume resource definition if no longer needed
ec2-imdsv2-required
Severity: high · Enforcement: advisory
EC2 instances must use IMDSv2
- 3.3 — Configure data access control lists based on a user’s need to know. Apply data access control lists, also known as access permissions, to local and remote file systems, databases, and applications.
Remediation
Fix: Enable IMDSv2 for EC2 Instance
Configure the EC2 instance to require IMDSv2 by setting metadataOptions.httpTokens to "required":
new aws.ec2.Instance("my-instance", {
instanceType: "t3.micro",
ami: "ami-12345678",
metadataOptions: {
httpTokens: "required", // Enforce IMDSv2
},
});
ec2-instance-detailed-monitoring-enabled
Severity: low · Enforcement: advisory
EC2 instances must have detailed monitoring enabled
- 3.8 — Document data flows. Data flow documentation includes service provider data flows and should be based on the enterprise’s data management process. Review and update documentation annually, or when significant enterprise changes occur that could impact this Safeguard.
Remediation
Fix: Enable Detailed Monitoring on EC2 Instance
Set the monitoring property to true on your EC2 instance resource:
const instance = new aws.ec2.Instance("my-instance", {
ami: "ami-12345678",
instanceType: "t3.micro",
monitoring: true, // Enable detailed (1-minute interval) monitoring
});
ec2-instance-iam-profile-attached
Severity: high · Enforcement: advisory
Ensure EC2 instances have IAM instance profiles attached for proper access control and security.
- 3.3 — Configure data access control lists based on a user’s need to know. Apply data access control lists, also known as access permissions, to local and remote file systems, databases, and applications.
Remediation
Fix: Attach IAM Instance Profile
const instanceRole = new aws.iam.Role("instance-role", {
assumeRolePolicy: JSON.stringify({
Version: "2012-10-17",
Statement: [{
Action: "sts:AssumeRole",
Effect: "Allow",
Principal: {
Service: "ec2.amazonaws.com",
},
}],
}),
});
const instanceProfile = new aws.iam.InstanceProfile("instance-profile", {
role: instanceRole.name,
});
const instance = new aws.ec2.Instance("app-server", {
ami: "ami-12345678",
instanceType: "t3.medium",
iamInstanceProfile: instanceProfile.name, // Attach instance profile
subnetId: subnet.id,
});
ec2-instance-in-vpc
Severity: high · Enforcement: advisory
EC2 instances must be placed in VPC for network isolation
- 3.3 — Configure data access control lists based on a user’s need to know. Apply data access control lists, also known as access permissions, to local and remote file systems, databases, and applications.
Remediation
Fix: Place EC2 Instance in a VPC Subnet
Add the subnetId property to your EC2 instance resource to ensure it’s deployed within a VPC for proper network isolation.
new aws.ec2.Instance("my-instance", {
ami: "ami-12345678",
instanceType: "t3.micro",
subnetId: mySubnet.id, // Specify a subnet to place instance in VPC
// ... other configuration
});
ec2-instance-no-public-ip
Severity: high · Enforcement: advisory
Checks that EC2 instances do not have a public IP address.
- 12.2 — Design and maintain a secure network architecture. A secure network architecture must address segmentation, least privilege, and availability, at a minimum. Example implementations may include documentation, policy, and design components.
Remediation
Fix: Disable Public IP Assignment
const instance = new aws.ec2.Instance("app-server", {
ami: "ami-12345678",
instanceType: "t3.medium",
associatePublicIpAddress: false, // Disable public IP to prevent direct internet access
subnetId: privateSubnet.id,
});
ec2-instance-not-publicly-accessible
Severity: critical · Enforcement: advisory
Ensure EC2 instances do not have public IP addresses for enhanced security.
- 3.3 — Configure data access control lists based on a user’s need to know. Apply data access control lists, also known as access permissions, to local and remote file systems, databases, and applications.
Remediation
Fix: Disable Public IP Address Assignment
const instance = new aws.ec2.Instance("app-server", {
ami: "ami-12345678",
instanceType: "t3.medium",
subnetId: subnet.id,
associatePublicIpAddress: false, // Prevent public IP assignment
});
ec2-instance-ssm-managed
Severity: medium · Enforcement: advisory
Ensure EC2 instances are managed by AWS Systems Manager for network infrastructure management.
- 12.1 — Ensure network infrastructure is kept up-to-date. Example implementations include running the latest stable release of software and/or using currently supported network as a service (NaaS) offerings. Review software versions monthly, or more frequently, to verify software support.
Remediation
Fix: Attach SSM Managed Policy to Instance Role
const instanceRole = new aws.iam.Role("instance-role", {
assumeRolePolicy: JSON.stringify({
Version: "2012-10-17",
Statement: [{
Action: "sts:AssumeRole",
Effect: "Allow",
Principal: { Service: "ec2.amazonaws.com" },
}],
}),
});
const ssmPolicy = new aws.iam.RolePolicyAttachment("ssm-policy", {
role: instanceRole.name,
policyArn: "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore", // SSM managed policy
});
const instanceProfile = new aws.iam.InstanceProfile("instance-profile", {
role: instanceRole.name,
});
const instance = new aws.ec2.Instance("my-instance", {
ami: "ami-12345678",
instanceType: "t3.medium",
iamInstanceProfile: instanceProfile.name,
subnetId: subnet.id,
});
ec2-stopped-instance-30-days
Severity: low · Enforcement: advisory
Ensure EC2 instances are stopped after 30 days to maintain asset inventory hygiene.
- 1.1 — Establish and maintain an accurate, detailed, and up-to-date inventory of all enterprise assets with the potential to store or process data, to include: end-user devices (including portable and mobile), network devices, non-computing/IoT devices, and servers. Ensure the inventory records the network address (if static), hardware address, machine name, enterprise asset owner, department for each asset, and whether the asset has been approved to connect to the network. For mobile end-user devices, MDM type tools can support this process, where appropriate. This inventory includes assets connected to the infrastructure physically, virtually, remotely, and those within cloud environments. Additionally, it includes assets that are regularly connected to the enterprise’s network infrastructure, even if they are not under control of the enterprise. Review and update the inventory of all enterprise assets bi-annually, or more frequently.
Remediation
Fix: Terminate or Start the Instance
// Option 1: Terminate the instance if no longer needed
// Remove from Pulumi program or use AWS CLI:
// aws ec2 terminate-instances --instance-ids i-1234567890abcdef0
// Option 2: Start the instance if still needed
// aws ec2 start-instances --instance-ids i-1234567890abcdef0
// For new instances, add lifecycle tags to track usage
const instance = new aws.ec2.Instance("my-instance", {
ami: "ami-12345678",
instanceType: "t3.medium",
subnetId: subnet.id,
tags: {
CreationDate: new Date().toISOString(),
Purpose: "active-workload",
},
});
ecs-task-definition-user-for-host-mode-check
Severity: high · Enforcement: advisory
ECS task definitions must use non-privileged user for host mode
- 3.3 — Configure data access control lists based on a user’s need to know. Apply data access control lists, also known as access permissions, to local and remote file systems, databases, and applications.
Remediation
Fix: Remove Privileged Container Settings
const taskDefinition = new aws.ecs.TaskDefinition("app-task", {
family: "app-task",
containerDefinitions: JSON.stringify([{
name: "app-container",
image: "nginx:latest",
privileged: false, // Set to false to disable privileged mode
user: "1000:1000", // For host network mode: specify non-root user (UID:GID)
linuxParameters: {
capabilities: {
add: ["NET_BIND_SERVICE"], // Avoid SYS_ADMIN, NET_ADMIN, or ALL
},
},
}]),
});
efs-encryption-required
Severity: high · Enforcement: advisory
Checks that EFS File Systems do not have an unencrypted file system.
- 3.11 — Encrypt sensitive data at rest on servers, applications, and databases. Storage-layer encryption, also known as server-side encryption, meets the minimum requirement of this Safeguard. Additional encryption methods may include application-layer encryption, also known as client-side encryption, where access to the data storage device(s) does not permit access to the plain-text data.
Remediation
Fix: Enable EFS File System Encryption
Set the encrypted property to true on your EFS file system resource:
import * as aws from "@pulumi/aws";
const fileSystem = new aws.efs.FileSystem("my-efs", {
encrypted: true, // Enable encryption at rest
kmsKeyId: myKmsKey.id, // Optional: specify a custom KMS key
});
Note: Encryption must be enabled at file system creation time and cannot be changed later.
eks-cluster-endpoint-restrict-public-access
Severity: high · Enforcement: advisory
Ensure EKS cluster endpoints are not publicly accessible for enhanced security.
- 3.3 — Configure data access control lists based on a user’s need to know. Apply data access control lists, also known as access permissions, to local and remote file systems, databases, and applications.
Remediation
Fix: Restrict Public Access to EKS Cluster Endpoint
const cluster = new aws.eks.Cluster("cluster", {
vpcConfig: {
endpointPublicAccess: false, // Disable public access
endpointPrivateAccess: true, // Enable private access
// ... other config
},
});
elasticbeanstalk-managed-updates-enabled
Severity: high · Enforcement: advisory
Elastic Beanstalk environments must have managed platform updates enabled
- 2.2 — Ensure that only currently supported software is designated as authorized in the software inventory for enterprise assets. If software is unsupported, yet necessary for the fulfillment of the enterprise’s mission, document an exception detailing mitigating controls and residual risk acceptance. For any unsupported software without an exception documentation, designate as unauthorized. Review the software list to verify software support at least monthly, or more frequently.
Remediation
Fix: Enable Managed Platform Updates
Configure managed platform updates for your Elastic Beanstalk environment by adding the required settings:
import * as aws from "@pulumi/aws";
const environment = new aws.elasticbeanstalk.Environment("my-environment", {
application: "my-app",
solutionStackName: "64bit Amazon Linux 2023 v6.0.0 running Node.js 18",
settings: [
// Enable managed platform updates
{
namespace: "aws:elasticbeanstalk:managedactions",
name: "ManagedActionsEnabled",
value: "true", // Required: Enable automated updates
},
{
namespace: "aws:elasticbeanstalk:managedactions",
name: "PreferredStartTime",
value: "sun:02:00", // Required: Set maintenance window
},
// Configure update level
{
namespace: "aws:elasticbeanstalk:managedactions:platformupdate",
name: "UpdateLevel",
value: "minor", // Required: Set to "patch", "minor", or "all"
},
{
namespace: "aws:elasticbeanstalk:managedactions:platformupdate",
name: "InstanceRefreshEnabled",
value: "true", // Recommended: Enable for zero-downtime updates
},
],
});
elasticsearch-encryption-enabled
Severity: high · Enforcement: advisory
Elasticsearch domains must have encryption at rest enabled
- 3.11 — Encrypt sensitive data at rest on servers, applications, and databases. Storage-layer encryption, also known as server-side encryption, meets the minimum requirement of this Safeguard. Additional encryption methods may include application-layer encryption, also known as client-side encryption, where access to the data storage device(s) does not permit access to the plain-text data.
Remediation
Fix: Enable Encryption at Rest for Elasticsearch Domain
Enable the encryptAtRest configuration on your Elasticsearch domain to encrypt data stored on disk:
const domain = new aws.elasticsearch.Domain("my-domain", {
domainName: "my-elasticsearch-domain",
encryptAtRest: {
enabled: true, // Enable encryption at rest
},
// ... other configuration
});
elasticsearch-in-vpc-only
Severity: high · Enforcement: advisory
Elasticsearch domains must be deployed in VPC for network isolation
- 3.3 — Configure data access control lists based on a user’s need to know. Apply data access control lists, also known as access permissions, to local and remote file systems, databases, and applications.
Remediation
Fix: Deploy Elasticsearch Domain in VPC
Add VPC configuration to your Elasticsearch domain to enable network isolation and boundary protection.
import * as aws from "@pulumi/aws";
const myElasticsearchDomain = new aws.elasticsearch.Domain("my-domain", {
domainName: "my-domain",
elasticsearchVersion: "7.10",
clusterConfig: {
instanceType: "r5.large.elasticsearch",
instanceCount: 2,
},
// Add VPC configuration for network isolation
vpcOptions: {
subnetIds: [subnet1.id, subnet2.id], // Specify subnet IDs from your VPC
securityGroupIds: [securityGroup.id], // Optional: specify security groups
},
ebsOptions: {
ebsEnabled: true,
volumeSize: 10,
},
});
elasticsearch-logs-to-cloudwatch
Severity: medium · Enforcement: advisory
Ensure Elasticsearch domains send logs to CloudWatch for monitoring and analysis.
- 3.8 — Document data flows. Data flow documentation includes service provider data flows and should be based on the enterprise’s data management process. Review and update documentation annually, or when significant enterprise changes occur that could impact this Safeguard.
Remediation
Fix: Enable CloudWatch Logging for Elasticsearch Domain
const domain = new aws.elasticsearch.Domain("search", {
logPublishingOptions: [
{
logType: "INDEX_SLOW_LOGS",
enabled: true,
cloudwatchLogGroupArn: logGroup.arn,
},
{
logType: "SEARCH_SLOW_LOGS",
enabled: true,
cloudwatchLogGroupArn: logGroup.arn,
},
{
logType: "ES_APPLICATION_LOGS",
enabled: true,
cloudwatchLogGroupArn: logGroup.arn,
},
],
// ... other config
});
elb-deletion-protection-enabled
Severity: medium · Enforcement: advisory
Load balancers must have deletion protection enabled
- 12.2 — Design and maintain a secure network architecture. A secure network architecture must address segmentation, least privilege, and availability, at a minimum. Example implementations may include documentation, policy, and design components.
Remediation
Fix: Enable deletion protection on the load balancer
Set the enableDeletionProtection property to true on your load balancer resource:
const alb = new aws.lb.LoadBalancer("my-alb", {
loadBalancerType: "application",
enableDeletionProtection: true, // Enable deletion protection
subnets: subnetIds,
});
elb-disallow-unencrypted-traffic
Severity: critical · Enforcement: advisory
Check that ELB Load Balancers do not allow unencrypted (HTTP) traffic.
- 3.1 — Establish and maintain a documented data management process. In the process, address data sensitivity, data owner, handling of data, data retention limits, and disposal requirements, based on sensitivity and retention standards for the enterprise. Review and update documentation annually, or when significant enterprise changes occur that could impact this Safeguard.
Remediation
Fix: Configure HTTPS/SSL listeners instead of HTTP
Update your ELB Load Balancer to use HTTPS or SSL protocol instead of HTTP:
const loadBalancer = new aws.elb.LoadBalancer("my-lb", {
listeners: [
{
instancePort: 443,
instanceProtocol: "https",
lbPort: 443,
lbProtocol: "https", // Use "https" or "ssl" instead of "http"
sslCertificateId: "arn:aws:iam::123456789012:server-certificate/my-cert", // Required for HTTPS/SSL
},
],
});
elb-logging-enabled
Severity: medium · Enforcement: advisory
Check that ELB Load Balancers uses access logging.
- 3.8 — Document data flows. Data flow documentation includes service provider data flows and should be based on the enterprise’s data management process. Review and update documentation annually, or when significant enterprise changes occur that could impact this Safeguard.
Remediation
Fix: Enable Access Logging for ELB Load Balancer
Configure the accessLogs property with an S3 bucket to store access logs:
const loadBalancer = new aws.elb.LoadBalancer("my-lb", {
availabilityZones: ["us-west-2a", "us-west-2b"],
listeners: [{ /* ... */ }],
accessLogs: {
enabled: true, // Enable access logging
bucket: "my-elb-logs-bucket", // S3 bucket for logs
bucketPrefix: "my-app", // Optional prefix for log files
},
});
elbv2-acm-certificate-required
Severity: high · Enforcement: advisory
Ensure ELBv2 (ALB/NLB) HTTPS listeners use ACM certificates for automated certificate management.
- 3.1 — Establish and maintain a documented data management process. In the process, address data sensitivity, data owner, handling of data, data retention limits, and disposal requirements, based on sensitivity and retention standards for the enterprise. Review and update documentation annually, or when significant enterprise changes occur that could impact this Safeguard.
Remediation
Fix: Use ACM certificate for ELBv2 HTTPS listener
// Configure HTTPS listener with ACM certificate
const listener = new aws.lb.Listener("listener", {
protocol: "HTTPS",
certificateArn: certificate.arn, // This fixes the issue
});
emr-cluster-master-nodes-no-public-ip
Severity: high · Enforcement: advisory
EMR clusters must not be deployed in public subnets that auto-assign public IP addresses
- 3.3 — Configure data access control lists based on a user’s need to know. Apply data access control lists, also known as access permissions, to local and remote file systems, databases, and applications.
Remediation
Fix: Deploy EMR Cluster in Private Subnet
const privateSubnet = new aws.ec2.Subnet("private-subnet", {
vpcId: vpc.id,
cidrBlock: "10.0.1.0/24",
mapPublicIpOnLaunch: false, // Disable auto-assign public IP
availabilityZone: "us-east-1a",
});
const emrCluster = new aws.emr.Cluster("my-cluster", {
releaseLabel: "emr-6.10.0",
ec2Attributes: {
subnetId: privateSubnet.id, // Use private subnet without public IP auto-assignment
emrManagedMasterSecurityGroup: masterSecurityGroup.id,
emrManagedSlaveSecurityGroup: slaveSecurityGroup.id,
},
// ... other cluster configuration
});
guardduty-enabled
Severity: high · Enforcement: advisory
Ensures AWS GuardDuty is enabled with malware detection capabilities for threat protection.
- 1.2 — Ensure that a process exists to address unauthorized assets on a weekly basis. The enterprise may choose to remove the asset from the network, deny the asset from connecting remotely to the network, or quarantine the asset.
Remediation
Fix: Enable GuardDuty with Malware Detection
Create a GuardDuty Detector with EBS malware protection and S3 data events enabled:
import * as aws from "@pulumi/aws";
// Enable GuardDuty detector
const detector = new aws.guardduty.Detector("guardduty-detector", {
enable: true, // Ensure detector is enabled
});
// Enable EBS malware protection for EC2 instances
new aws.guardduty.DetectorFeature("ebs-malware-protection", {
detectorId: detector.id,
name: "EBS_MALWARE_PROTECTION",
status: "ENABLED", // Enable malware scanning for EBS volumes
});
// Enable S3 data events protection
new aws.guardduty.DetectorFeature("s3-protection", {
detectorId: detector.id,
name: "S3_DATA_EVENTS",
status: "ENABLED", // Enable S3 threat detection
});
iam-account-password-policy-strong-min-reuse-24
Severity: high · Enforcement: advisory
Ensure IAM password policy prevents password reuse.
- 5.2 — Use unique passwords for all enterprise assets. Best practice implementation includes, at a minimum, an 8-character password for accounts using Multi-Factor Authentication (MFA) and a 14-character password for accounts not using MFA.
Remediation
Fix: Set Password Reuse Prevention
Configure the IAM account password policy to prevent reuse of at least 24 previous passwords.
import * as aws from "@pulumi/aws";
const passwordPolicy = new aws.iam.AccountPasswordPolicy("account-password-policy", {
passwordReusePrevention: 24, // Prevent reuse of last 24 passwords
});
iam-no-inline-policy-check
Severity: high · Enforcement: advisory
Ensure IAM roles and users do not use inline policies for better security and manageability.
- 3.3 — Configure data access control lists based on a user’s need to know. Apply data access control lists, also known as access permissions, to local and remote file systems, databases, and applications.
Remediation
Fix: Use Managed Policies Instead of Inline
// Create a managed policy
const policy = new aws.iam.Policy("my-policy", {
policy: JSON.stringify({
Version: "2012-10-17",
Statement: [{
Effect: "Allow",
Action: ["s3:GetObject"],
Resource: "arn:aws:s3:::my-bucket/*",
}],
}),
});
// Attach to user instead of inline
const attachment = new aws.iam.UserPolicyAttachment("user-attachment", {
user: myUser.name,
policyArn: policy.arn, // Use managed policy, not inline
});
iam-policy-no-star-star
Severity: critical · Enforcement: advisory
Ensure IAM policies do not contain wildcard permissions (Action: *, Resource: *) for enhanced security and least privilege.
- 5.4 — Restrict administrator privileges to dedicated administrator accounts on enterprise assets. Conduct general computing activities, such as internet browsing, email, and productivity suite use, from the user’s primary, non-privileged account.
Remediation
Fix: Use Specific Actions and Resources
const policy = new aws.iam.Policy("limited-policy", {
policy: JSON.stringify({
Version: "2012-10-17",
Statement: [{
Effect: "Allow",
Action: [
"s3:GetObject",
"s3:ListBucket",
], // Specific actions instead of "*"
Resource: [
"arn:aws:s3:::my-bucket",
"arn:aws:s3:::my-bucket/*",
], // Specific resources instead of "*"
}],
}),
});
iam-policy-no-statements-with-admin-access
Severity: critical · Enforcement: advisory
Ensure IAM policies do not contain statements with administrative access permissions for enhanced security.
- 4.6 — Securely manage enterprise assets and software. Example implementations include managing configuration through version-controlled Infrastructure-as-Code (IaC) and accessing administrative interfaces over secure network protocols, such as Secure Shell (SSH) and Hypertext Transfer Protocol Secure (HTTPS). Do not use insecure management protocols, such as Telnet (Teletype Network) and HTTP, unless operationally essential.
Remediation
Fix: Avoid Administrative Actions Like “iam:*”
const policy = new aws.iam.Policy("limited-policy", {
policy: JSON.stringify({
Version: "2012-10-17",
Statement: [{
Effect: "Allow",
Action: [
"iam:GetUser",
"iam:ListAccessKeys",
], // Specific IAM actions, not "iam:*"
Resource: "arn:aws:iam::*:user/${aws:username}",
}],
}),
});
iam-policy-no-statements-with-full-access
Severity: critical · Enforcement: advisory
Ensure IAM policies do not contain statements with full access permissions for enhanced security.
- 3.3 — Configure data access control lists based on a user’s need to know. Apply data access control lists, also known as access permissions, to local and remote file systems, databases, and applications.
Remediation
Fix: Use Specific Actions Instead of “service:*”
const policy = new aws.iam.Policy("limited-policy", {
policy: JSON.stringify({
Version: "2012-10-17",
Statement: [{
Effect: "Allow",
Action: [
"s3:GetObject",
"s3:PutObject",
"s3:ListBucket",
], // Specific S3 actions instead of "s3:*"
Resource: [
"arn:aws:s3:::my-bucket",
"arn:aws:s3:::my-bucket/*",
],
}],
}),
});
iam-root-user-mfa-enabled
Severity: critical · Enforcement: advisory
Ensure AWS root user has Multi-Factor Authentication (MFA) device configured for enhanced security.
- 5.2 — Use unique passwords for all enterprise assets. Best practice implementation includes, at a minimum, an 8-character password for accounts using Multi-Factor Authentication (MFA) and a 14-character password for accounts not using MFA.
Remediation
Fix: Create VirtualMfaDevice with Name “root”
const rootMfa = new aws.iam.VirtualMfaDevice("root-mfa", {
virtualMfaDeviceName: "root", // Name for root user MFA
// ... other required config
});
iam-root-user-no-access-keys
Severity: high · Enforcement: advisory
Prevents creation of direct IAM user access keys for human users
- 4.7 — Manage default accounts on enterprise assets and software, such as root, administrator, and other pre-configured vendor accounts. Example implementations can include: disabling default accounts or making them unusable.
Remediation
Fix: Replace IAM User Access Keys with Temporary Credentials
Remove the IAM Access Key resource and use IAM roles with temporary credentials instead:
// ❌ Avoid: Creating long-lived IAM access keys
const userAccessKey = new aws.iam.AccessKey("userKey", {
user: iamUser.name,
});
// ✅ Correct: Use IAM roles for service authentication
const appRole = new aws.iam.Role("appRole", {
assumeRolePolicy: JSON.stringify({
Version: "2012-10-17",
Statement: [{
Effect: "Allow",
Principal: { Service: "ec2.amazonaws.com" }, // Or Lambda, ECS, etc.
Action: "sts:AssumeRole",
}],
}),
});
// Attach the role to your compute resource (EC2, Lambda, ECS)
const instanceProfile = new aws.iam.InstanceProfile("profile", {
role: appRole.name,
});
For human users, configure AWS SSO or use temporary credentials via aws sso login instead of access keys.
iam-user-console-access-mfa-enabled
Severity: high · Enforcement: advisory
IAM users must have MFA enabled for console access
- 5.2 — Use unique passwords for all enterprise assets. Best practice implementation includes, at a minimum, an 8-character password for accounts using Multi-Factor Authentication (MFA) and a 14-character password for accounts not using MFA.
Remediation
Fix: Enable MFA for IAM User Console Access
Create a Virtual MFA device for each IAM user that has console access (UserLoginProfile):
import * as aws from "@pulumi/aws";
const user = new aws.iam.User("myUser", {
name: "example-user",
});
const loginProfile = new aws.iam.UserLoginProfile("myUserLogin", {
user: user.name,
});
// Add Virtual MFA device for the user
const mfaDevice = new aws.iam.VirtualMfaDevice("myUserMfa", {
virtualMfaDeviceName: `${user.name}-mfa`, // Name must match pattern: {username}-mfa or {username}-mfa-device
});
Alternatively, consider using IAM roles with temporary credentials or AWS IAM Identity Center (SSO) instead of IAM users.
iam-user-mfa-enabled
Severity: high · Enforcement: advisory
Ensure all IAM users have Multi-Factor Authentication (MFA) devices configured for enhanced security.
- 5.2 — Use unique passwords for all enterprise assets. Best practice implementation includes, at a minimum, an 8-character password for accounts using Multi-Factor Authentication (MFA) and a 14-character password for accounts not using MFA.
Remediation
Fix: Create VirtualMfaDevice for IAM User
const user = new aws.iam.User("my-user", {
name: "john.doe",
// ... other required config
});
const userMfa = new aws.iam.VirtualMfaDevice("user-mfa", {
virtualMfaDeviceName: user.name, // Associate MFA with user
});
iam-user-unused-credentials-90
Severity: medium · Enforcement: advisory
Ensure IAM user credentials are rotated within 90 days to prevent dormant account usage and enhance security.
- 5.3 — Delete or disable any dormant accounts after a period of 45 days of inactivity, where supported.
Remediation
Fix: Rotate or Delete Old Access Keys
const user = new aws.iam.User("app-user", {
name: "application-user",
});
// Step 1: Create new access key
const newAccessKey = new aws.iam.AccessKey("new-key", {
user: user.name,
});
// Step 2: Update application to use new key (outputs for reference)
export const newKeyId = newAccessKey.id;
export const newSecret = newAccessKey.secret;
// Step 3: After verifying the new key works, delete old key:
// Run: aws iam delete-access-key --user-name application-user --access-key-id AKIAOLD...
// Or use aws.iam.AccessKey resource with the old key ID and delete it
// For automated rotation, consider AWS Secrets Manager with rotation Lambda
kms-cmk-not-scheduled-for-deletion
Severity: high · Enforcement: advisory
Ensure KMS customer-managed keys are not scheduled for deletion to prevent data access loss.
- 3.11 — Encrypt sensitive data at rest on servers, applications, and databases. Storage-layer encryption, also known as server-side encryption, meets the minimum requirement of this Safeguard. Additional encryption methods may include application-layer encryption, also known as client-side encryption, where access to the data storage device(s) does not permit access to the plain-text data.
Remediation
Fix: Don’t schedule KMS key for deletion
const key = new aws.kms.Key("myKey", {
description: "Customer-managed key for data encryption",
enableKeyRotation: true,
// Don't set deletionWindowInDays - this fixes the violation
});
kms-key-rotation-enabled
Severity: medium · Enforcement: advisory
Checks that KMS Keys have key rotation enabled.
- 4.6 — Securely manage enterprise assets and software. Example implementations include managing configuration through version-controlled Infrastructure-as-Code (IaC) and accessing administrative interfaces over secure network protocols, such as Secure Shell (SSH) and Hypertext Transfer Protocol Secure (HTTPS). Do not use insecure management protocols, such as Telnet (Teletype Network) and HTTP, unless operationally essential.
Remediation
Fix: Enable automatic key rotation for KMS keys
Set the enableKeyRotation property to true on your KMS key resource to enable automatic annual rotation of the key material.
const key = new aws.kms.Key("my-key", {
description: "My KMS key",
enableKeyRotation: true, // Enable automatic key rotation
});
lambda-concurrency-check
Severity: low · Enforcement: advisory
Lambda functions must have concurrent execution limits configured to protect resource availability
- 3.8 — Document data flows. Data flow documentation includes service provider data flows and should be based on the enterprise’s data management process. Review and update documentation annually, or when significant enterprise changes occur that could impact this Safeguard.
Remediation
Fix: Configure Reserved Concurrent Executions
Set the reservedConcurrentExecutions property on your Lambda function to limit concurrent executions and prevent resource exhaustion.
import * as aws from "@pulumi/aws";
const myFunction = new aws.lambda.Function("myFunction", {
runtime: "nodejs18.x",
handler: "index.handler",
role: lambdaRole.arn,
code: new pulumi.asset.AssetArchive({
".": new pulumi.asset.FileArchive("./function"),
}),
// Set reserved concurrent executions to limit resource consumption
reservedConcurrentExecutions: 10,
});
Choose a value based on your function’s expected load and account limits. Setting this prevents the function from consuming all available concurrency and impacting other functions in your account.
lambda-function-public-access-prohibited
Severity: high · Enforcement: advisory
Lambda functions must restrict public access through resource-based policies
- 3.3 — Configure data access control lists based on a user’s need to know. Apply data access control lists, also known as access permissions, to local and remote file systems, databases, and applications.
Remediation
Fix: Restrict Lambda Function Access to Specific Principals
const lambdaFunction = new aws.lambda.Function("myFunction", {
runtime: "nodejs18.x",
handler: "index.handler",
role: role.arn,
code: new pulumi.asset.AssetArchive({
".": new pulumi.asset.FileArchive("./lambda"),
}),
});
// Grant access to specific AWS service instead of wildcard
new aws.lambda.Permission("apiGatewayInvoke", {
action: "lambda:InvokeFunction",
function: lambdaFunction.name,
principal: "apigateway.amazonaws.com", // Specify AWS service instead of "*"
sourceArn: apiGateway.executionArn,
});
// Or grant access to specific AWS account
new aws.lambda.Permission("crossAccountInvoke", {
action: "lambda:InvokeFunction",
function: lambdaFunction.name,
principal: "123456789012", // Specify AWS account ID instead of "*"
});
lambda-inside-vpc
Severity: high · Enforcement: advisory
Lambda functions must be deployed in VPC for network isolation and security
- 3.3 — Configure data access control lists based on a user’s need to know. Apply data access control lists, also known as access permissions, to local and remote file systems, databases, and applications.
Remediation
Fix: Configure Lambda Function VPC Placement
Add a vpcConfig to your Lambda function with subnet and security group configurations:
import * as aws from "@pulumi/aws";
const myFunction = new aws.lambda.Function("myFunction", {
runtime: "nodejs18.x",
handler: "index.handler",
role: lambdaRole.arn,
code: new pulumi.asset.AssetArchive({
".": new pulumi.asset.FileArchive("./function"),
}),
// Add VPC configuration for network isolation
vpcConfig: {
subnetIds: [
privateSubnet1.id, // Use at least 2 subnets for high availability
privateSubnet2.id,
],
securityGroupIds: [lambdaSecurityGroup.id], // Specify security groups for access control
},
});
neptune-clusterinstance-no-public-access
Severity: critical · Enforcement: advisory
Checks that Neptune Cluster Instances public access is not enabled.
- 3.3 — Ensure that database instances are not publicly accessible.
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-unrestricted-route-to-igw
Severity: high · Enforcement: advisory
Ensures VPC route tables restrict public access to internet gateways appropriately.
- 3.8 — Document data flows. Data flow documentation includes service provider data flows and should be based on the enterprise’s data management process. Review and update documentation annually, or when significant enterprise changes occur that could impact this Safeguard.
Remediation
Fix: Restrict Route Table Internet Gateway Access
Remove or restrict overly broad routes to internet gateways in your VPC route table.
import * as aws from "@pulumi/aws";
// Create route table without unrestricted internet access
const routeTable = new aws.ec2.RouteTable("example", {
vpcId: vpc.id,
routes: [
// ❌ INCORRECT: Avoid routes with 0.0.0.0/0 to internet gateway
// {
// cidrBlock: "0.0.0.0/0",
// gatewayId: igw.id,
// },
// ✅ CORRECT: Use specific CIDR blocks or route through NAT gateway instead
{
cidrBlock: "10.0.0.0/8", // Private network range
gatewayId: igw.id,
},
// Or use NAT gateway for controlled outbound access
{
cidrBlock: "0.0.0.0/0",
natGatewayId: natGateway.id, // NAT gateway provides controlled egress
},
],
});
Alternatively, exempt specific route tables from this check by configuring the policy.
rds-cluster-disallow-unencrypted-storage
Severity: high · Enforcement: advisory
Checks that RDS Clusters storage is encrypted.
- 3.11 — Encrypt Sensitive Data at Rest
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-instance-disallow-public-access
Severity: critical · Enforcement: advisory
Checks that RDS Cluster Instances public access is not enabled.
- 3.3 — Ensure that database instances are not publicly accessible.
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-logging-enabled
Severity: medium · Enforcement: advisory
Ensure RDS clusters have logging enabled for monitoring and audit compliance.
- 3.8 — Document data flows. Data flow documentation includes service provider data flows and should be based on the enterprise’s data management process. Review and update documentation annually, or when significant enterprise changes occur that could impact this Safeguard.
Remediation
Fix: Enable CloudWatch logs exports
For Aurora clusters (logging is configured at the cluster level, applies to all cluster instances):
const cluster = new aws.rds.Cluster("myCluster", {
engine: "aurora-postgresql",
enabledCloudwatchLogsExports: ["postgresql"], // This fixes the violation
});
Note: For Aurora databases, configure logging on the rds.Cluster resource. All cluster instances inherit this configuration.
rds-db-instance-backup-enabled
Severity: medium · Enforcement: advisory
Checks that RDS Instances backup retention policy is enabled.
- 11.2 — Perform automated backups of in-scope enterprise assets. Run backups weekly, or more frequently, based on the sensitivity of the data.
Remediation
Fix: Enable automated backup retention for RDS instance
Set the backupRetentionPeriod property to specify the number of days to retain automated backups (1-35 days):
const db = new aws.rds.Instance("my-db", {
engine: "postgres",
instanceClass: "db.t3.micro",
allocatedStorage: 20,
backupRetentionPeriod: 7, // Enable automated backups with 7-day retention
});
rds-encryption-enabled
Severity: high · Enforcement: advisory
Checks that RDS instance storage is encrypted.
- 3.11 — Encrypt sensitive data at rest on servers, applications, and databases. Storage-layer encryption, also known as server-side encryption, meets the minimum requirement of this Safeguard. Additional encryption methods may include application-layer encryption, also known as client-side encryption, where access to the data storage device(s) does not permit access to the plain-text data.
Remediation
Fix: Enable RDS Storage Encryption
Enable the storageEncrypted property on your RDS instance:
const myRdsInstance = new aws.rds.Instance("my-db", {
engine: "postgres",
instanceClass: "db.t3.micro",
allocatedStorage: 20,
storageEncrypted: true, // Enable encryption at rest
});
rds-instance-deletion-protection-enabled
Severity: high · Enforcement: advisory
RDS database instances must have deletion protection enabled to prevent accidental deletion and ensure data availability
- 12.2 — Design and maintain a secure network architecture. A secure network architecture must address segmentation, least privilege, and availability, at a minimum. Example implementations may include documentation, policy, and design components.
Remediation
Fix: Enable RDS Deletion Protection
Set the deletionProtection property to true on your RDS instance:
import * as aws from "@pulumi/aws";
const db = new aws.rds.Instance("myDatabase", {
engine: "postgres",
instanceClass: "db.t3.micro",
allocatedStorage: 20,
deletionProtection: true, // Enable deletion protection
// ... other configuration
});
rds-instance-disallow-public-access
Severity: critical · Enforcement: advisory
Checks that RDS Instance public access is not enabled.
- 3.3 — Ensure that database instances are not publicly accessible.
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-logging-enabled
Severity: medium · Enforcement: advisory
Ensure RDS database instances have logging enabled for monitoring and audit compliance.
- 3.8 — Document data flows. Data flow documentation includes service provider data flows and should be based on the enterprise’s data management process. Review and update documentation annually, or when significant enterprise changes occur that could impact this Safeguard.
Remediation
Fix: Enable CloudWatch logs exports
For standalone RDS instances:
const dbInstance = new aws.rds.Instance("myDb", {
engine: "postgres",
instanceClass: "db.t3.micro",
allocatedStorage: 20,
enabledCloudwatchLogsExports: ["postgresql"], // This fixes the violation
});
rds-logging-enabled
Severity: medium · Enforcement: advisory
Ensure RDS database instances have logging enabled for monitoring and audit compliance.
- 3.8 — Document data flows. Data flow documentation includes service provider data flows and should be based on the enterprise’s data management process. Review and update documentation annually, or when significant enterprise changes occur that could impact this Safeguard.
Remediation
Fix: Enable CloudWatch logs exports
const dbInstance = new aws.rds.Instance("myDb", {
engine: "postgres",
instanceClass: "db.t3.micro",
allocatedStorage: 20,
enabledCloudwatchLogsExports: ["postgresql"], // This fixes the violation
});
rds-multi-az-support
Severity: medium · Enforcement: advisory
Ensures RDS instances have Multi-AZ deployment enabled for high availability
- 12.2 — Design and maintain a secure network architecture. A secure network architecture must address segmentation, least privilege, and availability, at a minimum. Example implementations may include documentation, policy, and design components.
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 db = new aws.rds.Instance("database", {
allocatedStorage: 20,
engine: "mysql",
instanceClass: "db.t3.micro",
multiAz: true, // Enable Multi-AZ deployment for high availability
});
redshift-backup-enabled
Severity: high · Enforcement: advisory
Ensures Redshift clusters have automatic snapshots enabled with minimum 7-day retention period.
- 11.2 — Perform automated backups of in-scope enterprise assets. Run backups weekly, or more frequently, based on the sensitivity of the data.
Remediation
Fix: Enable Automatic Snapshots with Minimum Retention Period
Set the automatedSnapshotRetentionPeriod property to at least 7 days on your Redshift cluster:
import * as aws from "@pulumi/aws";
const cluster = new aws.redshift.Cluster("myCluster", {
clusterIdentifier: "my-redshift-cluster",
nodeType: "dc2.large",
numberOfNodes: 2,
// Enable automatic snapshots with minimum 7-day retention
automatedSnapshotRetentionPeriod: 7,
});
redshift-cluster-configuration-check
Severity: high · Enforcement: advisory
Ensure each Redshift cluster has audit logging enabled for security monitoring and compliance.
- 3.8 — Document data flows. Data flow documentation includes service provider data flows and should be based on the enterprise’s data management process. Review and update documentation annually, or when significant enterprise changes occur that could impact this Safeguard.
Remediation
Fix: Enable Audit Logging for Redshift Cluster
const cluster = new aws.redshift.Cluster("data-warehouse", {
nodeType: "dc2.large",
// ... other config
});
const logging = new aws.redshift.Logging("cluster-logging", {
clusterIdentifier: cluster.id,
logDestinationType: "s3", // or "cloudwatch"
bucketName: logBucket.bucket, // For S3 destination
s3KeyPrefix: "redshift-logs/", // For S3 destination
});
redshift-cluster-public-access-check
Severity: high · Enforcement: advisory
Ensures Redshift clusters prohibit public access to prevent unauthorized connections.
- 3.3 — Configure data access control lists based on a user’s need to know. Apply data access control lists, also known as access permissions, to local and remote file systems, databases, and applications.
Remediation
Fix: Disable Public Access for Redshift Cluster
const cluster = new aws.redshift.Cluster("data-warehouse", {
clusterIdentifier: "my-cluster",
nodeType: "dc2.large",
masterUsername: "admin",
masterPassword: password.result,
publiclyAccessible: false, // Disable public access to prevent internet exposure
vpcSecurityGroupIds: [securityGroup.id],
clusterSubnetGroupName: subnetGroup.name,
});
redshift-enhanced-vpc-routing-enabled
Severity: medium · Enforcement: advisory
Ensures Redshift clusters have enhanced VPC routing enabled for network isolation.
- 12.2 — Design and maintain a secure network architecture. A secure network architecture must address segmentation, least privilege, and availability, at a minimum. Example implementations may include documentation, policy, and design components.
Remediation
Fix: Enable Enhanced VPC Routing
Set the enhancedVpcRouting property to true on your Redshift cluster to ensure all COPY and UNLOAD traffic flows through your VPC infrastructure.
const cluster = new aws.redshift.Cluster("my-cluster", {
clusterIdentifier: "my-cluster",
// ... other configuration ...
enhancedVpcRouting: true, // Enable enhanced VPC routing for network isolation
});
redshift-maintenance-required
Severity: medium · Enforcement: advisory
Ensures Redshift clusters have proper maintenance settings configured for automated updates.
- 4.1 — Establish and maintain a documented secure configuration process for enterprise assets (end-user devices, including portable and mobile, non-computing/IoT devices, and servers) and software (operating systems and applications). Review and update documentation annually, or when significant enterprise changes occur that could impact this Safeguard.
Remediation
Fix: Configure Redshift Maintenance Settings
Add a preferred maintenance window and enable automatic version upgrades to allow automated security updates and system baseline changes.
const cluster = new aws.redshift.Cluster("my-cluster", {
clusterIdentifier: "my-redshift-cluster",
// ... other configuration ...
// Configure maintenance window for automated updates
preferredMaintenanceWindow: "sun:05:00-sun:06:00", // Weekly maintenance window
// Enable automatic version upgrades for security patches
allowVersionUpgrade: true,
});
restricted-ssh
Severity: high · Enforcement: advisory
Ensure security groups restrict SSH access from 0.0.0.0/0 to prevent unauthorized remote access.
- 3.8 — Document data flows. Data flow documentation includes service provider data flows and should be based on the enterprise’s data management process. Review and update documentation annually, or when significant enterprise changes occur that could impact this Safeguard.
Remediation
Fix: Restrict SSH Access
const securityGroup = new aws.ec2.SecurityGroup("sg", {
ingress: [{
fromPort: 22,
toPort: 22,
protocol: "tcp",
cidrBlocks: ["10.0.0.0/8"], // Use specific CIDR, not 0.0.0.0/0
}],
});
s3-bucket-encryption
Severity: high · Enforcement: advisory
S3 buckets must have server-side encryption configured using BucketServerSideEncryptionConfiguration resource
- 3.11 — Encrypt sensitive data at rest on servers, applications, and databases. Storage-layer encryption, also known as server-side encryption, meets the minimum requirement of this Safeguard. Additional encryption methods may include application-layer encryption, also known as client-side encryption, where access to the data storage device(s) does not permit access to the plain-text data.
Remediation
Fix: Enable S3 Bucket Server-Side Encryption
Add a BucketServerSideEncryptionConfigurationV2 resource to enable server-side encryption for your S3 bucket.
import * as aws from "@pulumi/aws";
// Create the S3 bucket
const bucket = new aws.s3.BucketV2("my-bucket", {
bucket: "my-bucket-name",
});
// Add server-side encryption configuration
const encryptionConfig = new aws.s3.BucketServerSideEncryptionConfiguration("my-bucket-encryption", {
bucket: bucket.id,
rules: [{
applyServerSideEncryptionByDefault: {
// Use AES256 for AWS-managed keys or "aws:kms" for KMS
sseAlgorithm: "aws:kms",
// Specify a customer-managed KMS key (required for compliance)
kmsMasterKeyId: kmsKey.arn,
},
// Enable bucket key to reduce KMS API calls and costs
bucketKeyEnabled: true,
}],
});
s3-bucket-level-public-access-prohibited
Severity: high · Enforcement: advisory
Ensures each S3 bucket has a public access block with all settings enabled
- 3.3 — Configure data access control lists based on a user’s need to know. Apply data access control lists, also known as access permissions, to local and remote file systems, databases, and applications.
Remediation
Fix: Enable All S3 Bucket Public Access Block Settings
const bucket = new aws.s3.Bucket("my-bucket");
const publicAccessBlock = new aws.s3.BucketPublicAccessBlock("my-bucket-public-access-block", {
bucket: bucket.id,
blockPublicAcls: true, // Block public ACLs on this bucket
blockPublicPolicy: true, // Block public bucket policies
ignorePublicAcls: true, // Ignore all public ACLs on this bucket
restrictPublicBuckets: true, // Restrict public bucket access
});
s3-bucket-logging-enabled
Severity: medium · Enforcement: advisory
Ensure each S3 bucket has access logging enabled for monitoring and audit compliance.
- 3.8 — Document data flows. Data flow documentation includes service provider data flows and should be based on the enterprise’s data management process. Review and update documentation annually, or when significant enterprise changes occur that could impact this Safeguard.
Remediation
Fix: Enable S3 Bucket Logging
const logging = new aws.s3.BucketLogging("logging", {
bucket: bucket.id,
targetBucket: logBucket.id, // Bucket to store access logs
targetPrefix: "logs/",
});
s3-bucket-public-read-prohibited
Severity: critical · Enforcement: advisory
Ensure S3 buckets prohibit public read access through comprehensive access controls.
- 4.6 — Securely manage enterprise assets and software. Example implementations include managing configuration through version-controlled Infrastructure-as-Code (IaC) and accessing administrative interfaces over secure network protocols, such as Secure Shell (SSH) and Hypertext Transfer Protocol Secure (HTTPS). Do not use insecure management protocols, such as Telnet (Teletype Network) and HTTP, unless operationally essential.
Remediation
Fix: Set Private ACL
const bucket = new aws.s3.Bucket("bucket", {
acl: "private", // Use private, not public-read
});
s3-bucket-public-write-prohibited
Severity: critical · Enforcement: advisory
Ensure S3 buckets do not allow public write access through ACL settings for proper data access control.
- 3.3 — Configure data access control lists based on a user’s need to know. Apply data access control lists, also known as access permissions, to local and remote file systems, databases, and applications.
Remediation
Fix: Set Private ACL
const bucket = new aws.s3.Bucket("bucket", {
acl: "private", // Use private, not public-read-write
});
s3-bucket-replication
Severity: medium · Enforcement: advisory
Ensure S3 buckets have replication enabled for automated backup to different regions.
- 11.2 — Perform automated backups of in-scope enterprise assets. Run backups weekly, or more frequently, based on the sensitivity of the data.
Remediation
Fix: Enable Replication
// 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-restrict-public-read-access
Severity: critical · Enforcement: advisory
Ensure S3 buckets do not allow public read access through ACL settings for proper data access control.
- 3.3 — Configure data access control lists based on a user’s need to know. Apply data access control lists, also known as access permissions, to local and remote file systems, databases, and applications.
Remediation
Fix: Set Private ACL and Block Public Access
const bucket = new aws.s3.Bucket("bucket", {
acl: "private", // Use private, not public-read
});
const publicAccessBlock = new aws.s3.BucketPublicAccessBlock("block", {
bucket: bucket.id,
blockPublicAcls: true,
ignorePublicAcls: true,
restrictPublicBuckets: true,
});
s3-bucket-ssl-enforcement-required
Severity: high · Enforcement: advisory
S3 buckets must enforce SSL/TLS for all requests to ensure encryption in transit
- 3.1 — Establish and maintain a documented data management process. In the process, address data sensitivity, data owner, handling of data, data retention limits, and disposal requirements, based on sensitivity and retention standards for the enterprise. Review and update documentation annually, or when significant enterprise changes occur that could impact this Safeguard.
Remediation
Fix: Add Bucket Policy to Enforce SSL/TLS
Add a bucket policy that denies all requests made without SSL/TLS encryption:
import * as aws from "@pulumi/aws";
const bucket = new aws.s3.BucketV2("my-bucket", {
bucket: "my-secure-bucket",
});
// Add bucket policy to enforce SSL/TLS
const bucketPolicy = new aws.s3.BucketPolicy("my-bucket-policy", {
bucket: bucket.id,
policy: bucket.arn.apply(arn => JSON.stringify({
Version: "2012-10-17",
Statement: [{
Sid: "DenyInsecureTransport",
Effect: "Deny",
Principal: "*",
Action: "s3:*",
Resource: [
arn,
`${arn}/*`,
],
Condition: {
Bool: {
"aws:SecureTransport": "false" // Deny when SecureTransport is false
}
}
}]
}))
});
s3-bucket-versioning-enabled
Severity: medium · Enforcement: advisory
S3 buckets must have versioning enabled using BucketVersioning resource
- 11.2 — Perform automated backups of in-scope enterprise assets. Run backups weekly, or more frequently, based on the sensitivity of the data.
Remediation
Fix: Enable S3 Bucket Versioning
Add a BucketVersioning resource to enable versioning for your S3 bucket:
import * as aws from "@pulumi/aws";
const myBucket = new aws.s3.BucketV2("my-bucket", {
bucket: "my-bucket-name"
});
// Enable versioning for the bucket
const bucketVersioning = new aws.s3.BucketVersioning("my-bucket-versioning", {
bucket: myBucket.id,
versioningConfiguration: {
status: "Enabled", // Set status to "Enabled"
},
});
Note: Do not use the deprecated versioning field directly on the Bucket resource. Always use the separate BucketVersioning resource.
sagemaker-endpoint-kms-encryption-enabled
Severity: high · Enforcement: advisory
Ensures SageMaker endpoint configurations have encryption enabled using KMS keys.
- 3.11 — Encrypt sensitive data at rest on servers, applications, and databases. Storage-layer encryption, also known as server-side encryption, meets the minimum requirement of this Safeguard. Additional encryption methods may include application-layer encryption, also known as client-side encryption, where access to the data storage device(s) does not permit access to the plain-text data.
Remediation
Fix: Enable KMS encryption for SageMaker endpoint configuration
Add the kmsKeyArn property to your SageMaker endpoint configuration to enable encryption at rest:
const endpointConfig = new aws.sagemaker.EndpointConfiguration("example", {
productionVariants: [{
modelName: model.name,
initialInstanceCount: 1,
instanceType: "ml.t2.medium",
}],
kmsKeyArn: kmsKey.arn, // Add KMS key ARN to enable encryption at rest
});
sagemaker-notebook-kms-encryption-enabled
Severity: high · Enforcement: advisory
Ensures SageMaker notebook instances have encryption enabled using KMS keys.
- 3.11 — Encrypt sensitive data at rest on servers, applications, and databases. Storage-layer encryption, also known as server-side encryption, meets the minimum requirement of this Safeguard. Additional encryption methods may include application-layer encryption, also known as client-side encryption, where access to the data storage device(s) does not permit access to the plain-text data.
Remediation
Fix: Enable KMS encryption for SageMaker notebook instance
Add the kmsKeyId property to your SageMaker notebook instance configuration to enable encryption at rest:
import * as aws from "@pulumi/aws";
const notebookInstance = new aws.sagemaker.NotebookInstance("example", {
name: "my-notebook",
instanceType: "ml.t2.medium",
roleArn: role.arn,
kmsKeyId: kmsKey.id, // Add KMS key ID to enable encryption at rest
});
sagemaker-notebook-no-direct-internet-access
Severity: high · Enforcement: advisory
Ensures SageMaker notebook instances have direct internet access disabled.
- 3.3 — Configure data access control lists based on a user’s need to know. Apply data access control lists, also known as access permissions, to local and remote file systems, databases, and applications.
Remediation
Fix: Disable Direct Internet Access
const notebookInstance = new aws.sagemaker.NotebookInstance("ml-notebook", {
instanceType: "ml.t3.medium",
roleArn: role.arn,
directInternetAccess: "Disabled", // Disable direct internet access
subnetId: subnet.id, // Must specify subnet when internet access is disabled
securityGroups: [securityGroup.id], // Control network access via security groups
});
secrets-manager-kms-encryption-enabled
Severity: low · Enforcement: advisory
Ensures Secrets Manager secrets have encryption enabled using KMS keys.
- 3.11 — Encrypt sensitive data at rest on servers, applications, and databases. Storage-layer encryption, also known as server-side encryption, meets the minimum requirement of this Safeguard. Additional encryption methods may include application-layer encryption, also known as client-side encryption, where access to the data storage device(s) does not permit access to the plain-text data.
Remediation
Fix: Configure Customer-Managed KMS Key for Secrets Manager Secret
Add the kmsKeyId property to your Secrets Manager secret resource, specifying a customer-managed KMS key:
import * as aws from "@pulumi/aws";
const kmsKey = new aws.kms.Key("my-key", {
description: "KMS key for Secrets Manager encryption",
});
const secret = new aws.secretsmanager.Secret("my-secret", {
kmsKeyId: kmsKey.id, // Specify customer-managed KMS key
});
securityhub-enabled
Severity: high · Enforcement: advisory
Ensures AWS Security Hub is enabled for continuous monitoring and security assessment.
- 7.1 — Establish and maintain a documented vulnerability management process for enterprise assets. Review and update documentation annually, or when significant enterprise changes occur that could impact this Safeguard.
Remediation
Fix: Enable AWS Security Hub
Add an AWS Security Hub Account resource to your Pulumi program to enable continuous monitoring:
import * as aws from "@pulumi/aws";
// Enable Security Hub for continuous monitoring
const securityHub = new aws.securityhub.Account("security-hub", {
// Security Hub will be enabled in the current region
});
sns-kms-encryption-enabled
Severity: high · Enforcement: advisory
Ensures SNS topics have encryption enabled using KMS keys.
- 3.11 — Encrypt sensitive data at rest on servers, applications, and databases. Storage-layer encryption, also known as server-side encryption, meets the minimum requirement of this Safeguard. Additional encryption methods may include application-layer encryption, also known as client-side encryption, where access to the data storage device(s) does not permit access to the plain-text data.
Remediation
Fix: Enable KMS encryption for SNS topic
Add the kmsMasterKeyId property to your SNS topic to enable encryption at rest using a KMS key.
const myTopic = new aws.sns.Topic("myTopic", {
name: "my-topic",
kmsMasterKeyId: "alias/aws/sns", // Add KMS key ID or ARN for encryption
});
ssm-managed-instance-compliance-association-compliant
Severity: medium · Enforcement: advisory
Ensure SSM managed instances have compliance association to maintain proper asset management.
- 1.1 — Establish and maintain an accurate, detailed, and up-to-date inventory of all enterprise assets with the potential to store or process data, to include: end-user devices (including portable and mobile), network devices, non-computing/IoT devices, and servers. Ensure the inventory records the network address (if static), hardware address, machine name, enterprise asset owner, department for each asset, and whether the asset has been approved to connect to the network. For mobile end-user devices, MDM type tools can support this process, where appropriate. This inventory includes assets connected to the infrastructure physically, virtually, remotely, and those within cloud environments. Additionally, it includes assets that are regularly connected to the enterprise’s network infrastructure, even if they are not under control of the enterprise. Review and update the inventory of all enterprise assets bi-annually, or more frequently.
Remediation
Fix: Create SSM Association for Compliance
// Associate compliance document with instances
const association = new aws.ssm.Association("inventory", {
name: "AWS-GatherSoftwareInventory",
targets: [{
key: "tag:Environment",
values: ["production"],
}],
scheduleExpression: "rate(30 minutes)",
complianceSeverity: "MEDIUM",
parameters: {
applications: ["Enabled"],
awsComponents: ["Enabled"],
instanceDetailedInformation: ["Enabled"],
networkConfig: ["Enabled"],
},
});
ssm-managed-instance-compliance-patch-compliant
Severity: medium · Enforcement: advisory
Ensure SSM managed instances have patch compliance associations configured for vulnerability management.
- 7.1 — CIS Controls v8 IG1 7.1
- 7.3 — 7.3 - Vulnerability Management: Establish and maintain a documented vulnerability management process for enterprise assets, and perform automated operating system patch management on a monthly or more frequent basis.
Remediation
Fix: Create SSM Association for Patch Management
// Create patch baseline
const baseline = new aws.ssm.PatchBaseline("baseline", {
approvedPatchesComplianceLevel: "CRITICAL",
operatingSystem: "AMAZON_LINUX_2",
});
// Associate patch baseline with instances
const association = new aws.ssm.Association("patch-baseline", {
name: "AWS-RunPatchBaseline",
targets: [{
key: "tag:PatchGroup",
values: ["production"],
}],
scheduleExpression: "cron(0 2 ? * SUN *)",
complianceSeverity: "CRITICAL",
parameters: {
Operation: ["Install"],
RebootOption: ["RebootIfNeeded"],
},
});
subnet-auto-assign-public-ip-disabled
Severity: high · Enforcement: advisory
Ensures VPC subnets have auto-assign public IP disabled to prevent unintended internet exposure.
- 3.3 — Configure data access control lists based on a user’s need to know. Apply data access control lists, also known as access permissions, to local and remote file systems, databases, and applications.
Remediation
Fix: Disable Auto-Assign Public IP for VPC Subnets
const subnet = new aws.ec2.Subnet("private-subnet", {
vpcId: vpc.id,
cidrBlock: "10.0.1.0/24",
mapPublicIpOnLaunch: false, // Disable auto-assign public IP to prevent unintended internet exposure
});
vpc-eip-associated
Severity: low · Enforcement: advisory
Ensure VPC elastic IPs are associated with resources to maintain proper asset inventory.
- 1.1 — Establish and maintain an accurate, detailed, and up-to-date inventory of all enterprise assets with the potential to store or process data, to include: end-user devices (including portable and mobile), network devices, non-computing/IoT devices, and servers. Ensure the inventory records the network address (if static), hardware address, machine name, enterprise asset owner, department for each asset, and whether the asset has been approved to connect to the network. For mobile end-user devices, MDM type tools can support this process, where appropriate. This inventory includes assets connected to the infrastructure physically, virtually, remotely, and those within cloud environments. Additionally, it includes assets that are regularly connected to the enterprise’s network infrastructure, even if they are not under control of the enterprise. Review and update the inventory of all enterprise assets bi-annually, or more frequently.
Remediation
Fix: Associate EIP with instance or network interface
const eip = new aws.ec2.Eip("eip", {
instanceId: instance.id, // This fixes the violation
// OR networkInterfaceId: eni.id,
// ... other required config
});
vpc-flow-logs-enabled
Severity: medium · Enforcement: advisory
Ensures VPC flow logs use approved destinations for centralized monitoring
- 8.2 — Collect audit logs. Ensure that logging, per the enterprise’s audit log management process, has been enabled across enterprise assets.
Remediation
Fix: Use an approved log destination for VPC Flow Logs
Update the Flow Log to use one of the approved destinations specified in the policy configuration.
const flowLog = new aws.ec2.FlowLog("vpc-flow-log", {
vpcId: vpc.id,
trafficType: "ALL",
// Use an approved log destination (e.g., CloudWatch Logs or S3)
logDestination: "arn:aws:s3:::approved-flow-logs-bucket",
logDestinationType: "s3",
});
vpc-security-group-restrict-ingress-ssh-all
Severity: high · Enforcement: advisory
Ensure VPC security groups restrict SSH ingress access from all IPs (0.0.0.0/0) to prevent unauthorized access.
- 4.6 — Securely manage enterprise assets and software. Example implementations include managing configuration through version-controlled Infrastructure-as-Code (IaC) and accessing administrative interfaces over secure network protocols, such as Secure Shell (SSH) and Hypertext Transfer Protocol Secure (HTTPS). Do not use insecure management protocols, such as Telnet (Teletype Network) and HTTP, unless operationally essential.
Remediation
Fix: Use specific CIDR instead of 0.0.0.0/0 for SSH
const securityGroup = new aws.ec2.SecurityGroup("securityGroup", {
ingress: [{
protocol: "tcp",
fromPort: 22,
toPort: 22,
cidrBlocks: ["203.0.113.0/24"], // This fixes the violation - use specific CIDR
}],
// ... other required config
});
waf-web-acl-logging-enabled
Severity: medium · Enforcement: advisory
Ensure WAF web ACLs have logging enabled to collect security audit logs for compliance.
- 8.2 — Collect audit logs. Ensure that logging, per the enterprise’s audit log management process, has been enabled across enterprise assets.
Remediation
Fix: Enable WAF Logging
const webAcl = new aws.waf.WebAcl("web-acl", {
loggingConfiguration: {
logDestination: deliveryStream.arn, // Kinesis Firehose stream for logs
},
// ... other required config
});
wafv2-logging-enabled
Severity: medium · Enforcement: advisory
Ensure WAFv2 web ACLs have logging enabled for security monitoring and analysis.
- 3.8 — Document data flows. Data flow documentation includes service provider data flows and should be based on the enterprise’s data management process. Review and update documentation annually, or when significant enterprise changes occur that could impact this Safeguard.
Remediation
Fix: Enable WAFv2 Logging
// Create Kinesis Firehose delivery stream for logs
const deliveryStream = new aws.kinesis.FirehoseDeliveryStream("waf-logs", {
destination: "extended_s3",
extendedS3Configuration: {
bucketArn: s3Bucket.arn,
prefix: "waf-logs/",
},
});
// Configure WAFv2 logging
const loggingConfig = new aws.wafv2.WebAclLoggingConfiguration("logging", {
resourceArn: webAcl.arn,
logDestinationConfigs: [deliveryStream.arn],
});
Additional policies
These 12 policies are included in the pack but are not mapped to a specific CIS 8.1 control.
alb-http-to-https-redirection-check
Severity: high · Enforcement: advisory
Ensure ALB HTTP listeners redirect to HTTPS for secure data transmission.
Remediation
Fix: Configure HTTP to HTTPS redirection for ALB listener
// Add HTTP to HTTPS redirect action
const listener = new aws.lb.Listener("listener", {
protocol: "HTTP",
port: 80,
defaultActions: [{
type: "redirect",
redirect: {
protocol: "HTTPS", // This fixes the issue
port: "443",
statusCode: "HTTP_301",
},
}],
});
codebuild-project-envvar-awscred-check
Severity: high · Enforcement: advisory
Ensure CodeBuild project environment variables do not contain AWS credentials.
Remediation
Fix: Use Secure Storage for Credentials in CodeBuild
const project = new aws.codebuild.Project("build", {
environment: {
environmentVariables: [
{
name: "API_KEY",
value: "secret-arn",
type: "SECRETS_MANAGER", // Use Secrets Manager for credentials
},
// OR
{
name: "CONFIG_PARAM",
value: "param-name",
type: "PARAMETER_STORE", // Use Parameter Store for config
},
],
},
// ... other config
});
dynamodb-autoscaling-enabled
Severity: low · Enforcement: advisory
Ensures DynamoDB tables have auto-scaling or on-demand mode enabled for capacity management.
Remediation
Fix: Enable DynamoDB Auto-Scaling or On-Demand Mode
Configure auto-scaling targets and policies for your DynamoDB table’s read and write capacity, or switch to on-demand billing mode:
import * as aws from "@pulumi/aws";
const table = new aws.dynamodb.Table("myTable", {
name: "my-table",
billingMode: "PROVISIONED", // Use provisioned mode with auto-scaling
readCapacity: 5,
writeCapacity: 5,
attributes: [{ name: "id", type: "S" }],
hashKey: "id",
});
// Configure read capacity auto-scaling
const readTarget = new aws.appautoscaling.Target("readTarget", {
resourceId: pulumi.interpolate`table/${table.name}`,
scalableDimension: "dynamodb:table:ReadCapacityUnits",
serviceNamespace: "dynamodb",
minCapacity: 5,
maxCapacity: 100, // Set appropriate scaling limits
});
new aws.appautoscaling.Policy("readPolicy", {
resourceId: readTarget.resourceId,
scalableDimension: readTarget.scalableDimension,
serviceNamespace: readTarget.serviceNamespace,
policyType: "TargetTrackingScaling",
targetTrackingScalingPolicyConfiguration: {
targetValue: 70.0, // Target utilization percentage
predefinedMetricSpecification: {
predefinedMetricType: "DynamoDBReadCapacityUtilization",
},
},
});
// Configure write capacity auto-scaling
const writeTarget = new aws.appautoscaling.Target("writeTarget", {
resourceId: pulumi.interpolate`table/${table.name}`,
scalableDimension: "dynamodb:table:WriteCapacityUnits",
serviceNamespace: "dynamodb",
minCapacity: 5,
maxCapacity: 100,
});
new aws.appautoscaling.Policy("writePolicy", {
resourceId: writeTarget.resourceId,
scalableDimension: writeTarget.scalableDimension,
serviceNamespace: writeTarget.serviceNamespace,
policyType: "TargetTrackingScaling",
targetTrackingScalingPolicyConfiguration: {
targetValue: 70.0,
predefinedMetricSpecification: {
predefinedMetricType: "DynamoDBWriteCapacityUtilization",
},
},
});
// Alternative: Use on-demand billing mode (no auto-scaling needed)
// const table = new aws.dynamodb.Table("myTable", {
// billingMode: "PAY_PER_REQUEST", // On-demand mode handles scaling automatically
// attributes: [{ name: "id", type: "S" }],
// hashKey: "id",
// });
ebs-snapshot-not-publicly-restorable
Severity: high · Enforcement: advisory
Ensure EBS snapshots are not publicly restorable to prevent unauthorized data access.
Remediation
Fix: Keep Snapshots Private
const snapshot = new aws.ebs.Snapshot("backup-snapshot", {
volumeId: volume.id,
description: "Private backup snapshot",
tags: {
Name: "db-backup",
},
});
// Do NOT add aws.ec2.SnapshotCreateVolumePermission with accountId: "all"
// Snapshots are private by default
ebs-volume-in-backup-plan
Severity: medium · Enforcement: advisory
Ensure EBS volumes are included in AWS Backup plans for automated backup and recovery capabilities.
Remediation
Fix: Add EBS Volume to Backup Plan
// Create backup vault
const vault = new aws.backup.Vault("ebs-vault", {
name: "ebs-backup-vault",
});
// Create IAM role for AWS Backup
const backupRole = new aws.iam.Role("backup-role", {
assumeRolePolicy: JSON.stringify({
Version: "2012-10-17",
Statement: [{
Effect: "Allow",
Principal: { Service: "backup.amazonaws.com" },
Action: "sts:AssumeRole",
}],
}),
managedPolicyArns: ["arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForBackup"],
});
// Create backup plan
const backupPlan = new aws.backup.Plan("ebs-backup-plan", {
name: "daily-ebs-backups",
rules: [{
ruleName: "daily-backup",
targetVaultName: vault.name,
schedule: "cron(0 2 * * ? *)",
lifecycle: {
deleteAfter: 30,
},
}],
});
// Add EBS volumes to backup selection
const backupSelection = new aws.backup.Selection("ebs-volumes", {
name: "all-ebs-volumes",
planId: backupPlan.id,
iamRoleArn: backupRole.arn,
resources: ["arn:aws:ec2:*:*:volume/*"],
});
elb-acm-certificate-required
Severity: high · Enforcement: advisory
Ensure ELB Classic Load Balancers use ACM certificates for HTTPS/SSL listeners.
Remediation
Fix: Use ACM certificate for ELB HTTPS listener
// Configure HTTPS listener with ACM certificate
const elb = new aws.elb.LoadBalancer("elb", {
listeners: [{
lbProtocol: "HTTPS",
lbPort: 443,
sslCertificateId: certificate.arn, // This fixes the issue
}],
});
elb-cross-zone-load-balancing-enabled
Severity: low · Enforcement: advisory
Classic Load Balancers must have cross-zone load balancing enabled
Remediation
Fix: Enable cross-zone load balancing on Classic Load Balancer
Set the crossZoneLoadBalancing property to true to distribute traffic evenly across all availability zones.
const loadBalancer = new aws.elb.LoadBalancer("my-load-balancer", {
availabilityZones: ["us-west-2a", "us-west-2b"],
listeners: [{
instancePort: 80,
instanceProtocol: "http",
lbPort: 80,
lbProtocol: "http",
}],
crossZoneLoadBalancing: true, // Enable cross-zone load balancing
});
emr-kerberos-enabled
Severity: high · Enforcement: advisory
Ensure EMR clusters have Kerberos authentication enabled for enhanced security.
Remediation
Fix: Enable Kerberos Authentication for EMR Cluster
const cluster = new aws.emr.Cluster("cluster", {
kerberosAttributes: {
realm: "EC2.INTERNAL", // Kerberos realm
kdcAdminPassword: kdcPassword.result, // KDC admin password
},
// ... other config
});
iam-user-no-policies-check
Severity: high · Enforcement: advisory
Ensure IAM users follow best practices by using groups and roles instead of direct policy attachments.
Remediation
Fix: Use GroupMembership Instead of Direct Attachment
const group = new aws.iam.Group("developers-group", {
name: "Developers",
// ... other required config
});
const groupPolicyAttachment = new aws.iam.GroupPolicyAttachment("group-policy", {
group: group.name,
policyArn: "arn:aws:iam::aws:policy/ReadOnlyAccess",
});
const user = new aws.iam.User("my-user", {
name: "john.doe",
// ... other required config
});
const groupMembership = new aws.iam.GroupMembership("group-members", {
group: group.name,
users: [user.name], // Add users to group instead of direct policy attachment
});
s3-bucket-policy-grantee-check
Severity: high · Enforcement: advisory
Ensure S3 bucket policies do not grant access to inappropriate principals for proper access control.
Remediation
Fix: Use Specific Principals
const policy = new aws.s3.BucketPolicy("policy", {
bucket: bucket.id,
policy: JSON.stringify({
Statement: [{
Principal: { AWS: "arn:aws:iam::123456789012:root" }, // Specific account, not "*"
Action: "s3:GetObject",
Resource: pulumi.interpolate`${bucket.arn}/*`,
}],
}),
});
vpc-network-acl-unused
Severity: medium · Enforcement: advisory
Ensure VPC network ACLs are not unused to maintain proper network security asset management.
Remediation
Fix: Associate NetworkAcl with subnet
const nacl = new aws.ec2.NetworkAcl("nacl", {
subnetIds: [subnet.id], // This fixes the violation
// ... other required config
});
vpc-security-group-associated-to-eni
Severity: medium · Enforcement: advisory
Ensure VPC security groups are associated to ENI (network interfaces) to maintain proper network security asset management.
Remediation
Fix: Attach security group to instance or ENI
const instance = new aws.ec2.Instance("instance", {
vpcSecurityGroupIds: [securityGroup.id], // This fixes the violation
// ... other required config
});