---
title: AWS
url: /docs/reference/pre-built-policy-packs/cis/aws/
---
> This [Pulumi Cloud](/docs/iac/concepts/pulumi-cloud/) feature is available in the [Enterprise edition](/pricing/).


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.

- [ec2-stopped-instance-30-days](#ec2-stopped-instance-30-days)
- [ssm-managed-instance-compliance-association-compliant](#ssm-managed-instance-compliance-association-compliant)
- [vpc-eip-associated](#vpc-eip-associated)

**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.

- [guardduty-enabled](#guardduty-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.

- [elasticbeanstalk-managed-updates-enabled](#elasticbeanstalk-managed-updates-enabled)

**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.

- [elb-disallow-unencrypted-traffic](#elb-disallow-unencrypted-traffic)
- [elbv2-acm-certificate-required](#elbv2-acm-certificate-required)
- [s3-bucket-ssl-enforcement-required](#s3-bucket-ssl-enforcement-required)

**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](#autoscaling-launch-config-public-ip-disabled)
- [dms-replication-instance-not-publicly-accessible](#dms-replication-instance-not-publicly-accessible)
- [ec2-imdsv2-required](#ec2-imdsv2-required)
- [ec2-instance-iam-profile-attached](#ec2-instance-iam-profile-attached)
- [ec2-instance-in-vpc](#ec2-instance-in-vpc)
- [ec2-instance-not-publicly-accessible](#ec2-instance-not-publicly-accessible)
- [ecs-task-definition-user-for-host-mode-check](#ecs-task-definition-user-for-host-mode-check)
- [eks-cluster-endpoint-restrict-public-access](#eks-cluster-endpoint-restrict-public-access)
- [elasticsearch-in-vpc-only](#elasticsearch-in-vpc-only)
- [emr-cluster-master-nodes-no-public-ip](#emr-cluster-master-nodes-no-public-ip)
- [iam-no-inline-policy-check](#iam-no-inline-policy-check)
- [iam-policy-no-statements-with-full-access](#iam-policy-no-statements-with-full-access)
- [lambda-function-public-access-prohibited](#lambda-function-public-access-prohibited)
- [lambda-inside-vpc](#lambda-inside-vpc)
- [neptune-clusterinstance-no-public-access](#neptune-clusterinstance-no-public-access)
- [rds-cluster-instance-disallow-public-access](#rds-cluster-instance-disallow-public-access)
- [rds-instance-disallow-public-access](#rds-instance-disallow-public-access)
- [redshift-cluster-public-access-check](#redshift-cluster-public-access-check)
- [s3-bucket-level-public-access-prohibited](#s3-bucket-level-public-access-prohibited)
- [s3-bucket-public-write-prohibited](#s3-bucket-public-write-prohibited)
- [s3-bucket-restrict-public-read-access](#s3-bucket-restrict-public-read-access)
- [sagemaker-notebook-no-direct-internet-access](#sagemaker-notebook-no-direct-internet-access)
- [subnet-auto-assign-public-ip-disabled](#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.

- [cloudwatch-log-group-retention-period-365](#cloudwatch-log-group-retention-period-365)

**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](#cloud-trail-cloud-watch-logs-enabled)
- [cloudtrail-s3-dataevents-enabled](#cloudtrail-s3-dataevents-enabled)
- [ec2-instance-detailed-monitoring-enabled](#ec2-instance-detailed-monitoring-enabled)
- [elasticsearch-logs-to-cloudwatch](#elasticsearch-logs-to-cloudwatch)
- [elb-logging-enabled](#elb-logging-enabled)
- [lambda-concurrency-check](#lambda-concurrency-check)
- [no-unrestricted-route-to-igw](#no-unrestricted-route-to-igw)
- [rds-cluster-logging-enabled](#rds-cluster-logging-enabled)
- [rds-instance-logging-enabled](#rds-instance-logging-enabled)
- [rds-logging-enabled](#rds-logging-enabled)
- [redshift-cluster-configuration-check](#redshift-cluster-configuration-check)
- [restricted-ssh](#restricted-ssh)
- [s3-bucket-logging-enabled](#s3-bucket-logging-enabled)
- [wafv2-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-gateway-cache-encryption-enabled)
- [api-gw-stage-cache-enabled](#api-gw-stage-cache-enabled)
- [cloud-trail-encryption-enabled](#cloud-trail-encryption-enabled)
- [cloudwatch-log-group-kms-encryption-enabled](#cloudwatch-log-group-kms-encryption-enabled)
- [dynamodb-kms-encryption-enabled](#dynamodb-kms-encryption-enabled)
- [ebs-volume-encryption-required](#ebs-volume-encryption-required)
- [efs-encryption-required](#efs-encryption-required)
- [elasticsearch-encryption-enabled](#elasticsearch-encryption-enabled)
- [kms-cmk-not-scheduled-for-deletion](#kms-cmk-not-scheduled-for-deletion)
- [rds-cluster-disallow-unencrypted-storage](#rds-cluster-disallow-unencrypted-storage)
- [rds-encryption-enabled](#rds-encryption-enabled)
- [s3-bucket-encryption](#s3-bucket-encryption)
- [sagemaker-endpoint-kms-encryption-enabled](#sagemaker-endpoint-kms-encryption-enabled)
- [sagemaker-notebook-kms-encryption-enabled](#sagemaker-notebook-kms-encryption-enabled)
- [secrets-manager-kms-encryption-enabled](#secrets-manager-kms-encryption-enabled)
- [sns-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.

- [ebs-volume-unused](#ebs-volume-unused)
- [redshift-maintenance-required](#redshift-maintenance-required)

**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](#autoscaling-health-checks-enabled)
- [cloud-trail-log-file-validation-enabled](#cloud-trail-log-file-validation-enabled)
- [cloudtrail-security-trail-enabled](#cloudtrail-security-trail-enabled)
- [ebs-attached-volume-encryption-enabled](#ebs-attached-volume-encryption-enabled)
- [iam-policy-no-statements-with-admin-access](#iam-policy-no-statements-with-admin-access)
- [kms-key-rotation-enabled](#kms-key-rotation-enabled)
- [s3-bucket-public-read-prohibited](#s3-bucket-public-read-prohibited)
- [vpc-security-group-restrict-ingress-ssh-all](#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.

- [iam-root-user-no-access-keys](#iam-root-user-no-access-keys)

**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-account-password-policy-strong-min-reuse-24)
- [iam-root-user-mfa-enabled](#iam-root-user-mfa-enabled)
- [iam-user-console-access-mfa-enabled](#iam-user-console-access-mfa-enabled)
- [iam-user-mfa-enabled](#iam-user-mfa-enabled)

**5.3** — Delete or disable any dormant accounts after a period of 45 days of inactivity, where supported.

- [iam-user-unused-credentials-90](#iam-user-unused-credentials-90)

**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.

- [iam-policy-no-star-star](#iam-policy-no-star-star)

**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.

- [securityhub-enabled](#securityhub-enabled)
- [ssm-managed-instance-compliance-patch-compliant](#ssm-managed-instance-compliance-patch-compliant)

**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.

- [ssm-managed-instance-compliance-patch-compliant](#ssm-managed-instance-compliance-patch-compliant)

**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](#apigateway-stage-logging-enabled)
- [cloudfront-distribution-logging-enabled](#cloudfront-distribution-logging-enabled)
- [cloudtrail-trail-enabled](#cloudtrail-trail-enabled)
- [cloudtrail-trail-integrated-with-logs](#cloudtrail-trail-integrated-with-logs)
- [vpc-flow-logs-enabled](#vpc-flow-logs-enabled)
- [waf-web-acl-logging-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-pitr-enabled)
- [dynamodb-table-in-backup-plan](#dynamodb-table-in-backup-plan)
- [ebs-optimized-instance](#ebs-optimized-instance)
- [rds-db-instance-backup-enabled](#rds-db-instance-backup-enabled)
- [redshift-backup-enabled](#redshift-backup-enabled)
- [s3-bucket-replication](#s3-bucket-replication)
- [s3-bucket-versioning-enabled](#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.

- [dynamodb-table-in-backup-plan](#dynamodb-table-in-backup-plan)

**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.

- [ec2-instance-ssm-managed](#ec2-instance-ssm-managed)

**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](#acm-certificate-expiration-check)
- [ec2-instance-no-public-ip](#ec2-instance-no-public-ip)
- [elb-deletion-protection-enabled](#elb-deletion-protection-enabled)
- [rds-instance-deletion-protection-enabled](#rds-instance-deletion-protection-enabled)
- [rds-multi-az-support](#rds-multi-az-support)
- [redshift-enhanced-vpc-routing-enabled](#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.

- [alb-waf-enabled](#alb-waf-enabled)

**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.

- [codebuild-project-source-repo-url-check](#codebuild-project-source-repo-url-check)

## 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:
```typescript
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

```typescript
// 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.

```typescript
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:
```typescript
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:

```typescript
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:

```typescript
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

```typescript
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:

```typescript
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:

```typescript
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:

```typescript
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

```typescript
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:

```typescript
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:

```typescript
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

```typescript
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:

```typescript
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: true` to capture events across all AWS regions
- Enable `includeGlobalServiceEvents` to capture IAM and STS events
- Use `enableLogFileValidation` to 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

```typescript
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:

```typescript
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.

```typescript
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

```typescript
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

```typescript
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:

```typescript
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`.

```typescript
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

```typescript
// 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

```typescript
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:

```typescript
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.

```typescript
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:

```typescript
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"`:

```typescript
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:

```typescript
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

```typescript
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.

```typescript
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

```typescript
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

```typescript
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

```typescript
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

```typescript
// 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

```typescript
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:

```typescript
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

```typescript
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:

```typescript
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:

```typescript
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.

```typescript
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

```typescript
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:

```typescript
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:

```typescript
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:

```typescript
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

```typescript
// 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

```typescript
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:

```typescript
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.

```typescript
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

```typescript
// 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

```typescript
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:*"

```typescript
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:*"

```typescript
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"

```typescript
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:

```typescript
// ❌ 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):

```typescript
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

```typescript
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

```typescript
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

```typescript
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.

```typescript
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.

```typescript
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

```typescript
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:

```typescript
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`:

```typescript
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.

```typescript
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:

```typescript
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:

```typescript
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):

```typescript
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):

```typescript
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:

```typescript
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:

```typescript
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:

```typescript
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:

```typescript
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

```typescript
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.

```typescript
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:

```typescript
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

```typescript
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

```typescript
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.

```typescript
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.

```typescript
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

```typescript
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.

```typescript
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

```typescript
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

```typescript
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

```typescript
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

```typescript
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

```typescript
// 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

```typescript
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:

```typescript
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:

```typescript
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:

```typescript
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:

```typescript
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

```typescript
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:

```typescript
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:

```typescript
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.

```typescript
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

```typescript
// 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

```typescript
// 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

```typescript
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

```typescript
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.

```typescript
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

```typescript
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

```typescript
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

```typescript
// 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

```typescript
// 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

```typescript
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:

```typescript
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

```typescript
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

```typescript
// 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

```typescript
// 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.

```typescript
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

```typescript
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

```typescript
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

```typescript
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

```typescript
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

```typescript
const instance = new aws.ec2.Instance("instance", {
    vpcSecurityGroupIds: [securityGroup.id],  // This fixes the violation
    // ... other required config
});
```


