Skip to main content
Pulumi logo Pulumi logo
  1. Docs
  2. Reference
  3. Pre-built Policy Packs
  4. ISO/IEC 27001
  5. AWS

ISO/IEC 27001 - AWS

    This page lists all 238 policies in the ISO/IEC 27001:2022 pack for AWS, as published in iso-27001-aws version 1.0.1.

    Policies by control

    A.5.9 Inventory of information and other associated assets — An inventory of information and other associated assets, including owners, shall be developed and maintained.

    A.5.14 Information transfer — Information transfer rules, procedures, or agreements shall be in place for all types of transfer facilities within the organization and between the organization and other parties.

    A.5.15 Access control — Rules to control physical and logical access to information and other associated assets shall be established and implemented based on business and information security requirements.

    A.5.16 Identity management — The full life cycle of identities shall be managed.

    A.5.17 Authentication information — Allocation and management of authentication information shall be controlled by a management process, including advising personnel on appropriate handling of authentication information.

    A.5.18 Access rights — Access rights to information and other associated assets shall be provisioned, reviewed, modified and removed in accordance with the organization’s topic-specific policy on and rules for access control.

    A.5.25 Assessment and decision on information security events — The organization shall assess information security events and decide if they are to be categorized as information security incidents.

    A.5.26 Response to information security incidents — Information security incidents shall be responded to in accordance with the documented procedures.

    A.5.28 Collection of evidence — The organization shall establish and implement procedures for the identification, collection, acquisition and preservation of evidence related to information security events.

    A.5.29 Information security during disruption — The organization shall plan how to maintain information security at an appropriate level during disruption.

    A.5.30 ICT readiness for business continuity — ICT readiness shall be planned, implemented, maintained and tested based on business continuity objectives and ICT continuity requirements.

    A.5.33 Protection of records — Records shall be protected from loss, destruction, falsification, unauthorized access and unauthorized release.

    A.5.36 Compliance with policies, rules and standards for information security — Compliance with the organization’s information security policy, topic-specific policies, rules and standards shall be regularly reviewed.

    A.6.7 Remote working — Security measures shall be implemented when personnel are working remotely to protect information accessed, processed or stored outside the organization’s premises.

    A.8.2 Privileged access rights — The allocation and use of privileged access rights shall be restricted and managed.

    A.8.3 Information access restriction — Access to information and other associated assets shall be restricted in accordance with the established topic-specific policy on access control.

    A.8.5 Secure authentication — Secure authentication technologies and procedures shall be implemented based on information access restrictions and the topic-specific policy on access control.

    A.8.6 Capacity management — The use of resources shall be monitored and adjusted in line with current and expected capacity requirements.

    A.8.7 Protection against malware — Protection against malware shall be implemented and supported by appropriate user awareness.

    A.8.8 Management of technical vulnerabilities — Information about technical vulnerabilities of information systems in use shall be obtained, the organization’s exposure to such vulnerabilities shall be evaluated and appropriate measures shall be taken.

    A.8.9 Configuration management — Configurations, including security configurations, of hardware, software, services and networks shall be established, documented, implemented, monitored and reviewed.

    A.8.10 Information deletion — Information stored in information systems, devices or in any other storage media shall be deleted when no longer required.

    A.8.12 Data leakage prevention — Data leakage prevention measures shall be applied to systems, networks and any other devices that process, store or transmit sensitive information.

    A.8.13 Information backup — Backup copies of information, software and systems shall be maintained and regularly tested in accordance with the agreed topic-specific policy on backup.

    A.8.14 Redundancy of information processing facilities — Information processing facilities shall be implemented with redundancy sufficient to meet availability requirements.

    A.8.15 Logging — Logs that record activities, exceptions, faults and other relevant events shall be produced, stored, protected and analysed.

    A.8.16 Monitoring activities — Networks, systems and applications shall be monitored for anomalous behaviour and appropriate actions taken to evaluate potential information security incidents.

    A.8.20 Networks security — Networks and network devices shall be secured, managed and controlled to protect information in systems and applications.

    A.8.21 Security of network services — Security mechanisms, service levels and service requirements of network services shall be identified, implemented and monitored.

    A.8.22 Segregation of networks — Groups of information services, users and information systems shall be segregated in the organization’s networks.

    A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.

    Policy details

    alb-http-to-https-redirection-check

    Severity: high · Enforcement: advisory

    Ensure ALB HTTP listeners redirect to HTTPS for secure data transmission.

    • A.5.14 Information transfer — Information transfer rules, procedures, or agreements shall be in place for all types of transfer facilities within the organization and between the organization and other parties.
    Remediation
    Fix: Configure HTTP to HTTPS redirection for ALB listener
    // Add HTTP to HTTPS redirect action
    const listener = new aws.lb.Listener("listener", {
        protocol: "HTTP",
        port: 80,
        defaultActions: [{
            type: "redirect",
            redirect: {
                protocol: "HTTPS",  // This fixes the issue
                port: "443",
                statusCode: "HTTP_301",
            },
        }],
    });
    

    anti-malware-edr

    Severity: high · Enforcement: advisory

    Ensures EC2 instances have anti-malware/EDR agents deployed

    • A.8.7 Protection against malware — Protection against malware shall be implemented and supported by appropriate user awareness.
    Remediation
    Fix: Deploy Anti-Malware/EDR Agent via User Data

    Include anti-malware or EDR agent installation commands in the instance’s userData:

    const instance = new aws.ec2.Instance("protected-instance", {
        instanceType: "t3.medium",
        ami: "ami-0c55b159cbfafe1f0",
        userData: "#!/bin/bash\nyum install -y amazon-ssm-agent\nsystemctl enable amazon-ssm-agent\nsystemctl start amazon-ssm-agent", // Install SSM agent
        subnetId: subnet.id,
    });
    

    api-gateway-access-logging

    Severity: medium · Enforcement: advisory

    Ensures API Gateway stages have access logging enabled

    • A.8.15 Logging — Logs that record activities, exceptions, faults and other relevant events shall be produced, stored, protected and analysed.
    Remediation
    Fix: Enable Access Logging for API Gateway Stage

    Configure the accessLogSettings property with a CloudWatch Log Group ARN to enable comprehensive audit logging:

    const logGroup = new aws.cloudwatch.LogGroup("api-logs", {
        retentionInDays: 30,
    });
    
    const stage = new aws.apigateway.Stage("my-stage", {
        restApi: api.id,
        stageName: "prod",
        deployment: deployment.id,
        accessLogSettings: { // Enable access logging
            destinationArn: logGroup.arn, // Specify CloudWatch Log Group
            format: "$context.requestId",
        },
    });
    

    api-gateway-authorization

    Severity: high · Enforcement: advisory

    Ensures API Gateway methods use strong authorization instead of NONE

    • A.5.15 Access control — Rules to control physical and logical access to information and other associated assets shall be established and implemented based on business and information security requirements.
    • A.8.3 Information access restriction — Access to information and other associated assets shall be restricted in accordance with the established topic-specific policy on access control.
    Remediation
    Fix: Enable Strong Authorization for API Gateway Method

    Set the authorization property to a strong authorization type (AWS_IAM, COGNITO_USER_POOLS, CUSTOM, or JWT) instead of “NONE”:

    const method = new aws.apigateway.Method("my-method", {
        restApi: api.id,
        resourceId: resource.id,
        httpMethod: "GET",
        authorization: "AWS_IAM", // Use strong authorization instead of "NONE"
        // For CUSTOM authorization, also specify the authorizer:
        // authorizerId: authorizer.id,
    });
    

    api-gateway-cache-encryption-enabled

    Severity: medium · Enforcement: advisory

    Ensures API Gateway method settings have cache data encryption enabled when caching is configured.

    • A.5.33 Protection of records — Records shall be protected from loss, destruction, falsification, unauthorized access and unauthorized release.
    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Enable cache data encryption for API Gateway method settings

    When enabling caching for API Gateway methods, ensure cache data encryption is also enabled to protect sensitive data at rest.

    import * as aws from "@pulumi/aws";
    
    const methodSettings = new aws.apigateway.MethodSettings("example-method-settings", {
        restApi: restApi.id,
        stageName: stage.stageName,
        methodPath: "*/*",
        settings: {
            cachingEnabled: true,
            cacheDataEncrypted: true,  // Enable cache encryption at rest
            cacheTtlInSeconds: 300,
        },
    });
    

    api-gateway-domain-name-configure-security-policy

    Severity: high · Enforcement: advisory

    Checks that ApiGateway Domain Name Security Policy uses secure/modern TLS encryption.

    • A.5.14 Information transfer — Information transfer rules, procedures, or agreements shall be in place for all types of transfer facilities within the organization and between the organization and other parties.
    • A.8.20 Networks security — Networks and network devices shall be secured, managed and controlled to protect information in systems and applications.
    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Configure TLS 1.2 Security Policy

    Set the securityPolicy to “TLS_1_2” to ensure the API Gateway domain name uses secure TLS encryption:

    const domainName = new apigateway.DomainName("my-domain", {
        domainName: "api.example.com",
        certificateArn: cert.arn,
        securityPolicy: "TLS_1_2", // Use TLS 1.2 for secure encryption
    });
    

    api-gateway-ssl-certificate-required

    Severity: high · Enforcement: advisory

    Ensures API Gateway REST API stages have client certificates configured for SSL/TLS authentication to protect data in transit.

    • A.5.14 Information transfer — Information transfer rules, procedures, or agreements shall be in place for all types of transfer facilities within the organization and between the organization and other parties.
    • A.8.20 Networks security — Networks and network devices shall be secured, managed and controlled to protect information in systems and applications.
    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Configure Client Certificate for API Gateway Stage

    First, create a client certificate:

    import * as aws from "@pulumi/aws";
    
    // Create a client certificate for SSL/TLS authentication
    const clientCert = new aws.apigateway.ClientCertificate("api-client-cert", {
        description: "Client certificate for API Gateway SSL authentication",
    });
    

    Then, associate the certificate with your API Gateway stage:

    const stage = new aws.apigateway.Stage("api-stage", {
        restApi: restApi.id,
        deployment: deployment.id,
        stageName: "production",
        clientCertificateId: clientCert.id, // Add this property to enable SSL certificate validation
    });
    

    api-gateway-v2-access-logging

    Severity: medium · Enforcement: advisory

    Ensures API Gateway V2 stages have access logging enabled

    • A.8.15 Logging — Logs that record activities, exceptions, faults and other relevant events shall be produced, stored, protected and analysed.
    Remediation
    Fix: Enable Access Logging for API Gateway V2 Stage

    Configure the accessLogSettings property with a CloudWatch Log Group ARN to enable comprehensive audit logging:

    const logGroup = new aws.cloudwatch.LogGroup("api-v2-logs", {
        retentionInDays: 30,
    });
    
    const stage = new aws.apigatewayv2.Stage("my-stage", {
        apiId: api.id,
        name: "prod",
        accessLogSettings: { // Enable access logging
            destinationArn: logGroup.arn, // Specify CloudWatch Log Group
            format: "$context.requestId",
        },
    });
    

    api-gateway-v2-domain-name-configure-domain-name-security-policy

    Severity: high · Enforcement: advisory

    Checks that any ApiGatewayV2 Domain Name Security Policy uses secure/modern TLS encryption.

    • A.5.14 Information transfer — Information transfer rules, procedures, or agreements shall be in place for all types of transfer facilities within the organization and between the organization and other parties.
    • A.8.20 Networks security — Networks and network devices shall be secured, managed and controlled to protect information in systems and applications.
    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Set TLS 1.2 Security Policy for API Gateway V2 Domain Name

    Configure the securityPolicy to “TLS_1_2” in the domain name configuration to enforce modern TLS encryption:

    const domainName = new aws.apigatewayv2.DomainName("my-domain", {
        domainName: "api.example.com",
        domainNameConfiguration: {
            certificateArn: certificate.arn,
            endpointType: "REGIONAL",
            securityPolicy: "TLS_1_2", // Use TLS 1.2 for secure encryption
        },
    });
    

    api-gateway-v2-domain-name-enable-domain-name-configuration

    Severity: high · Enforcement: advisory

    Checks that any ApiGatewayV2 Domain Name Configuration is enabled.

    • A.5.14 Information transfer — Information transfer rules, procedures, or agreements shall be in place for all types of transfer facilities within the organization and between the organization and other parties.
    Remediation
    Fix: Configure Domain Name Configuration for API Gateway V2

    Add the domainNameConfiguration property with the required TLS settings to enable secure custom domain name configuration:

    const domainName = new apigatewayv2.DomainName("my-domain", {
        domainName: "api.example.com",
        domainNameConfiguration: { // Enable domain name configuration
            certificateArn: certificate.arn,
            endpointType: "REGIONAL",
            securityPolicy: "TLS_1_2",
        },
    });
    

    api-gateway-waf-association

    Severity: critical · Enforcement: advisory

    Ensures public-facing API Gateways have WAF associations

    • A.8.20 Networks security — Networks and network devices shall be secured, managed and controlled to protect information in systems and applications.
    Remediation
    Fix: Associate WAF Web ACL with API Gateway Stage

    Create a WAF Web ACL association for your API Gateway stage:

    // Create a WAF Web ACL association for the API Gateway stage
    const wafAssociation = new aws.wafv2.WebAclAssociation("api-waf-association", {
        resourceArn: pulumi.interpolate`arn:aws:apigateway:${region}::/restapis/${restApi.id}/stages/${stage.stageName}`, // Stage ARN
        webAclArn: webAcl.arn, // Reference the WAF Web ACL ARN
    });
    

    apigateway-method-execution-logging

    Severity: medium · Enforcement: advisory

    API Gateway method settings must enable execution logging.

    • A.8.15 Logging — Logs that record activities, exceptions, faults and other relevant events shall be produced, stored, protected and analysed.
    Remediation
    Fix: Enable API Gateway Method Execution Logging

    Set settings.loggingLevel to ERROR or INFO so method execution is logged to CloudWatch Logs.

    const methodSettings = new aws.apigateway.MethodSettings("my-method-settings", {
        restApi: restApi.id,
        stageName: stage.stageName,
        methodPath: "*/*",
        settings: {
            loggingLevel: "INFO",
            metricsEnabled: true,
        },
    });
    

    appflow-connector-profile-configure-customer-managed-key

    Severity: low · Enforcement: advisory

    Check that AppFlow ConnectorProfile uses a customer-managed KMS key.

    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Configure Customer-Managed KMS Key for AppFlow Connector Profile

    Set the kmsArn property to reference a customer-managed KMS key:

    const connectorProfile = new aws.appflow.ConnectorProfile("my-connector-profile", {
        connectorProfileName: "salesforce-connector",
        connectorType: "Salesforce",
        connectionMode: "Public",
        kmsArn: kmsKey.arn, // Specify customer-managed KMS key ARN
        connectorProfileConfig: {
            connectorProfileCredentials: {
                salesforce: {
                    accessToken: salesforceAccessToken,
                    refreshToken: salesforceRefreshToken,
                    oauthRequest: {
                        authCode: authCode,
                        redirectUri: redirectUri,
                    },
                },
            },
        },
    });
    

    appflow-flow-configure-customer-managed-key

    Severity: low · Enforcement: advisory

    Check that AppFlow Flow uses a customer-managed KMS key.

    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Configure Customer-Managed KMS Key for AppFlow Flow

    Set the kmsArn property to specify a customer-managed KMS key for encrypting the AppFlow Flow:

    const flow = new aws.appflow.Flow("my-flow", {
        name: "my-appflow",
        kmsArn: kmsKey.arn, // Configure customer-managed KMS key
        sourceFlowConfig: {
            connectorType: "S3",
            sourceConnectorProperties: {
                s3: {
                    bucketName: sourceBucket.bucket,
                    bucketPrefix: "data/",
                },
            },
        },
        destinationFlowConfigs: [{
            connectorType: "S3",
            destinationConnectorProperties: {
                s3: {
                    bucketName: destBucket.bucket,
                },
            },
        }],
        tasks: [{
            taskType: "Map_all",
            sourceFields: [],
            connectorOperator: {
                s3: "NO_OP",
            },
        }],
        triggerConfig: {
            triggerType: "OnDemand",
        },
    });
    

    appsync-graphqlapi-logging

    Severity: medium · Enforcement: advisory

    AppSync GraphQL APIs must have logging configured.

    • A.8.15 Logging — Logs that record activities, exceptions, faults and other relevant events shall be produced, stored, protected and analysed.
    Remediation
    Fix: Enable AppSync GraphQL API Logging

    Configure the logConfig block so request and response activity is captured in CloudWatch Logs.

    const api = new aws.appsync.GraphQLApi("my-api", {
        authenticationType: "API_KEY",
        logConfig: {
            cloudwatchLogsRoleArn: loggingRole.arn,
            fieldLogLevel: "ALL",
        },
    });
    

    appsync-waf-association

    Severity: critical · Enforcement: advisory

    Ensures public-facing AppSync GraphQL APIs have WAF associations

    • A.8.20 Networks security — Networks and network devices shall be secured, managed and controlled to protect information in systems and applications.
    Remediation
    Fix: Associate WAF Web ACL with AppSync GraphQL API

    Create a WAF Web ACL association to protect your AppSync GraphQL API:

    // Create a WAF Web ACL association for the AppSync GraphQL API
    const wafAssociation = new aws.wafv2.WebAclAssociation("appsync-waf-association", {
        resourceArn: graphqlApi.arn, // Reference the GraphQL API ARN
        webAclArn: webAcl.arn, // Reference the WAF Web ACL ARN
    });
    

    athena-database-configure-customer-managed-key

    Severity: low · Enforcement: advisory

    Checks that Athena Databases storage uses a customer-managed-key.

    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Configure Customer-Managed Key Encryption for Athena Database

    Set the encryptionOption to “SSE_KMS” and specify a KMS key ARN in the encryptionConfiguration:

    const athenaDatabase = new aws.athena.Database("my-database", {
        name: "my_database",
        bucket: myBucket.id,
        encryptionConfiguration: {
            encryptionOption: "SSE_KMS", // Use customer-managed KMS key
            kmsKey: myKmsKey.arn, // Specify the KMS key ARN
        },
    });
    

    athena-database-disallow-unencrypted-database

    Severity: high · Enforcement: advisory

    Checks that Athena Databases storage is encrypted.

    • A.5.33 Protection of records — Records shall be protected from loss, destruction, falsification, unauthorized access and unauthorized release.
    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Enable Encryption for Athena Database

    Configure the encryptionConfiguration property to encrypt query results and data catalog:

    const athenaDatabase = new aws.athena.Database("my-database", {
        name: "my_database",
        bucket: dataBucket.id,
        encryptionConfiguration: { // Enable encryption
            encryptionOption: "SSE_S3", // Use SSE-S3, SSE-KMS, or CSE-KMS
        },
    });
    

    athena-workgroup-configure-customer-managed-key

    Severity: low · Enforcement: advisory

    Checks that Athena Workgroups use a customer-managed-key.

    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Configure Customer-Managed Key Encryption for Athena Workgroup

    Set the encryptionOption to “SSE_KMS” in the workgroup’s result configuration to enable customer-managed key encryption:

    const workgroup = new athena.Workgroup("my-workgroup", {
        name: "my-workgroup",
        configuration: {
            resultConfiguration: {
                outputLocation: "s3://my-bucket/query-results/",
                encryptionConfiguration: {
                    encryptionOption: "SSE_KMS", // Enable customer-managed key encryption
                    kmsKey: kmsKey.arn, // Optional: specify a specific KMS key
                },
            },
        },
    });
    

    athena-workgroup-disallow-unencrypted-workgroup

    Severity: high · Enforcement: advisory

    Checks that Athena Workgroups are encrypted.

    • A.5.33 Protection of records — Records shall be protected from loss, destruction, falsification, unauthorized access and unauthorized release.
    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Enable Encryption for Athena Workgroup Query Results

    Configure encryption for query results by adding an encryptionConfiguration within the workgroup’s resultConfiguration:

    const workgroup = new athena.Workgroup("my-workgroup", {
        name: "example-workgroup",
        configuration: {
            resultConfiguration: {
                outputLocation: "s3://my-query-results-bucket/",
                encryptionConfiguration: { // Add encryption configuration
                    encryptionOption: "SSE_KMS", // or "SSE_S3" or "CSE_KMS"
                    kmsKey: kmsKey.arn, // Required when using SSE_KMS or CSE_KMS
                },
            },
        },
    });
    

    athena-workgroup-enforce-configuration

    Severity: high · Enforcement: advisory

    Checks that Athena Workgroups enforce their configuration to their clients.

    • A.8.9 Configuration management — Configurations, including security configurations, of hardware, software, services and networks shall be established, documented, implemented, monitored and reviewed.
    Remediation
    Fix: Enable Workgroup Configuration Enforcement

    Set enforceWorkgroupConfiguration to true in the Athena Workgroup configuration to ensure clients use the workgroup’s settings:

    const workgroup = new athena.Workgroup("my-workgroup", {
        name: "my-workgroup",
        configuration: {
            enforceWorkgroupConfiguration: true, // Enforce workgroup configuration on clients
            resultConfiguration: {
                outputLocation: "s3://my-query-results/",
            },
        },
    });
    

    autoscaling-group-capacity-rebalancing

    Severity: low · Enforcement: advisory

    Auto Scaling groups must enable capacity rebalancing to proactively replace Spot Instances at risk of interruption.

    • A.8.6 Capacity management — The use of resources shall be monitored and adjusted in line with current and expected capacity requirements.
    Remediation
    Fix: Enable Capacity Rebalancing on the Auto Scaling Group

    Set capacityRebalance to true so the group proactively replaces Spot Instances before interruption.

    const group = new aws.autoscaling.Group("my-group", {
        capacityRebalance: true,
        // ... other configuration
    });
    

    backup-vault-encryption

    Severity: high · Enforcement: advisory

    AWS Backup vaults must be encrypted with a customer-managed KMS key

    • A.5.33 Protection of records — Records shall be protected from loss, destruction, falsification, unauthorized access and unauthorized release.
    • A.8.13 Information backup — Backup copies of information, software and systems shall be maintained and regularly tested in accordance with the agreed topic-specific policy on backup.
    Remediation
    Fix: Encrypt the Backup vault with a customer-managed KMS key

    Set kmsKeyArn so recovery points stored in the vault are encrypted with a customer-managed key rather than the default AWS-managed key:

    const vault = new aws.backup.Vault("vault", {
        kmsKeyArn: kmsKey.arn, // customer-managed KMS key
    });
    

    centralized-os-app-logging

    Severity: medium · Enforcement: advisory

    Ensures EC2 instances have logging agents configured to forward OS/application logs to central system

    • A.8.15 Logging — Logs that record activities, exceptions, faults and other relevant events shall be produced, stored, protected and analysed.
    Remediation
    Fix: Configure Logging Agent in EC2 Instance User Data

    Add a logging agent installation and configuration script to the instance’s userData to forward OS and application logs to a central logging system:

    const instance = new aws.ec2.Instance("web-server", {
        ami: "ami-0c55b159cbfafe1f0",
        instanceType: "t3.micro",
        userData: `#!/bin/bash
    ##### Install and configure CloudWatch Agent for centralized logging
    wget https://s3.amazonaws.com/amazoncloudwatch-agent/amazon_linux/amd64/latest/amazon-cloudwatch-agent.rpm
    rpm -U ./amazon-cloudwatch-agent.rpm
    ##### Configure agent to forward logs
    /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl \
        -a fetch-config -m ec2 -s -c ssm:AmazonCloudWatch-Config
    `, // Add logging agent to userData
        iamInstanceProfile: instanceProfile.name,
        subnetId: subnet.id,
    });
    

    cloudfront-distribution-configure-access-logging

    Severity: medium · Enforcement: advisory

    Checks that any CloudFront distributions have access logging configured.

    • A.8.15 Logging — Logs that record activities, exceptions, faults and other relevant events shall be produced, stored, protected and analysed.
    Remediation
    Fix: Configure CloudFront Access Logging

    Configure the loggingConfig property with an S3 bucket to store CloudFront access logs:

    const distribution = new cloudfront.Distribution("my-distribution", {
        enabled: true,
        loggingConfig: {
            bucket: logBucket.bucketDomainName, // S3 bucket for access logs
            includeCookies: false,
            prefix: "cloudfront-logs/",
        },
        // ... other distribution configuration
    });
    

    cloudfront-distribution-configure-secure-tls

    Severity: high · Enforcement: advisory

    Checks that CloudFront distributions uses secure/modern TLS encryption.

    • A.5.14 Information transfer — Information transfer rules, procedures, or agreements shall be in place for all types of transfer facilities within the organization and between the organization and other parties.
    • A.8.20 Networks security — Networks and network devices shall be secured, managed and controlled to protect information in systems and applications.
    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Configure Secure TLS Protocol Version for CloudFront

    Set the minimumProtocolVersion to “TLSv1.2_2021” in the viewer certificate configuration:

    const distribution = new cloudfront.Distribution("my-distribution", {
        enabled: true,
        origins: [/* ... */],
        defaultCacheBehavior: {/* ... */},
        viewerCertificate: {
            cloudfrontDefaultCertificate: true,
            minimumProtocolVersion: "TLSv1.2_2021", // Use secure TLS 1.2 with modern cipher suites
        },
    });
    

    cloudfront-distribution-configure-secure-tls-to-origin

    Severity: high · Enforcement: advisory

    Checks that CloudFront distributions communicate with custom origins using TLS 1.2 encryption only.

    • A.5.14 Information transfer — Information transfer rules, procedures, or agreements shall be in place for all types of transfer facilities within the organization and between the organization and other parties.
    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Configure TLS 1.2 for CloudFront Custom Origins

    Set the originSslProtocols in your custom origin configuration to only allow TLS 1.2:

    const distribution = new cloudfront.Distribution("my-distribution", {
        enabled: true,
        origins: [{
            domainName: "my-origin.example.com",
            originId: "myCustomOrigin",
            customOriginConfig: {
                httpPort: 80,
                httpsPort: 443,
                originProtocolPolicy: "https-only",
                originSslProtocols: ["TLSv1.2"], // Only allow TLS 1.2
            },
        }],
        defaultCacheBehavior: {
            targetOriginId: "myCustomOrigin",
            viewerProtocolPolicy: "redirect-to-https",
            allowedMethods: ["GET", "HEAD"],
            cachedMethods: ["GET", "HEAD"],
            forwardedValues: {
                queryString: false,
                cookies: { forward: "none" },
            },
        },
    });
    

    cloudfront-distribution-disallow-default-certificate

    Severity: medium · Enforcement: advisory

    CloudFront distributions must use a custom SSL certificate rather than the default CloudFront certificate.

    • A.5.14 Information transfer — Information transfer rules, procedures, or agreements shall be in place for all types of transfer facilities within the organization and between the organization and other parties.
    Remediation
    Fix: Use a Custom SSL Certificate for CloudFront

    Associate an ACM or IAM certificate instead of relying on the default CloudFront certificate.

    const distribution = new aws.cloudfront.Distribution("my-distribution", {
        // ...
        viewerCertificate: {
            acmCertificateArn: cert.arn,
            sslSupportMethod: "sni-only",
            minimumProtocolVersion: "TLSv1.2_2021",
        },
    });
    

    cloudfront-distribution-disallow-unencrypted-traffic

    Severity: critical · Enforcement: advisory

    Checks that CloudFront distributions only allow encypted ingress traffic.

    • A.5.14 Information transfer — Information transfer rules, procedures, or agreements shall be in place for all types of transfer facilities within the organization and between the organization and other parties.
    • A.8.20 Networks security — Networks and network devices shall be secured, managed and controlled to protect information in systems and applications.
    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Enforce HTTPS for CloudFront Distribution

    Set the viewerProtocolPolicy to “redirect-to-https” or “https-only” for both default and ordered cache behaviors to ensure all traffic is encrypted:

    const distribution = new cloudfront.Distribution("my-distribution", {
        enabled: true,
        defaultCacheBehavior: {
            targetOriginId: origin.originId,
            viewerProtocolPolicy: "redirect-to-https", // Enforce HTTPS for all traffic
            allowedMethods: ["GET", "HEAD"],
            cachedMethods: ["GET", "HEAD"],
            forwardedValues: {
                queryString: false,
                cookies: { forward: "none" },
            },
        },
        orderedCacheBehaviors: [{
            pathPattern: "/api/*",
            targetOriginId: origin.originId,
            viewerProtocolPolicy: "https-only", // Enforce HTTPS-only for API paths
            allowedMethods: ["GET", "HEAD", "OPTIONS"],
            cachedMethods: ["GET", "HEAD"],
            forwardedValues: {
                queryString: true,
                cookies: { forward: "none" },
            },
        }],
        origins: [origin],
        viewerCertificate: {
            cloudfrontDefaultCertificate: true,
        },
    });
    

    cloudfront-distribution-enable-access-logging

    Severity: medium · Enforcement: advisory

    Checks that any CloudFront distributions have access logging enabled.

    • A.8.15 Logging — Logs that record activities, exceptions, faults and other relevant events shall be produced, stored, protected and analysed.
    Remediation
    Fix: Enable Access Logging for CloudFront Distribution

    Configure the loggingConfig property to enable access logging and specify an S3 bucket to store the logs:

    const distribution = new aws.cloudfront.Distribution("my-distribution", {
        enabled: true,
        origins: [{
            domainName: bucket.bucketRegionalDomainName,
            originId: "myS3Origin",
        }],
        defaultCacheBehavior: {
            targetOriginId: "myS3Origin",
            viewerProtocolPolicy: "redirect-to-https",
            allowedMethods: ["GET", "HEAD"],
            cachedMethods: ["GET", "HEAD"],
            forwardedValues: {
                queryString: false,
                cookies: { forward: "none" },
            },
        },
        loggingConfig: {  // Enable access logging
            bucket: logBucket.bucketDomainName,  // S3 bucket for logs
            includeCookies: false,
            prefix: "cloudfront-logs/",
        },
        restrictions: {
            geoRestriction: {
                restrictionType: "none",
            },
        },
        viewerCertificate: {
            cloudfrontDefaultCertificate: true,
        },
    });
    

    cloudfront-distribution-enable-tls-to-origin

    Severity: high · Enforcement: advisory

    Checks that CloudFront distributions communicate with custom origins using TLS encryption.

    • A.5.14 Information transfer — Information transfer rules, procedures, or agreements shall be in place for all types of transfer facilities within the organization and between the organization and other parties.
    • A.8.20 Networks security — Networks and network devices shall be secured, managed and controlled to protect information in systems and applications.
    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Enable HTTPS-Only Protocol for CloudFront Custom Origins

    Set the originProtocolPolicy to “https-only” in the customOriginConfig for all custom origins to ensure encrypted communication:

    const distribution = new cloudfront.Distribution("my-distribution", {
        enabled: true,
        origins: [{
            domainName: "my-custom-origin.example.com",
            originId: "my-custom-origin",
            customOriginConfig: {
                httpPort: 80,
                httpsPort: 443,
                originProtocolPolicy: "https-only", // Enforce TLS encryption to origin
                originSslProtocols: ["TLSv1.2"],
            },
        }],
        defaultCacheBehavior: {
            targetOriginId: "my-custom-origin",
            viewerProtocolPolicy: "redirect-to-https",
            allowedMethods: ["GET", "HEAD"],
            cachedMethods: ["GET", "HEAD"],
            forwardedValues: {
                queryString: false,
                cookies: { forward: "none" },
            },
        },
    });
    

    cloudfront-waf-association

    Severity: critical · Enforcement: advisory

    Ensures CloudFront distributions have WAF associations

    • A.8.20 Networks security — Networks and network devices shall be secured, managed and controlled to protect information in systems and applications.
    Remediation
    Fix: Associate WAF Web ACL with CloudFront Distribution

    Set the webAclId property to associate your CloudFront distribution with a WAF Web ACL:

    const distribution = new aws.cloudfront.Distribution("my-distribution", {
        enabled: true,
        webAclId: webAcl.arn, // Associate the WAF Web ACL with the distribution
        origins: [{
            domainName: bucket.bucketRegionalDomainName,
            originId: "S3Origin",
        }],
        defaultCacheBehavior: {
            targetOriginId: "S3Origin",
            viewerProtocolPolicy: "redirect-to-https",
            allowedMethods: ["GET", "HEAD"],
            cachedMethods: ["GET", "HEAD"],
            forwardedValues: {
                queryString: false,
                cookies: { forward: "none" },
            },
        },
    });
    

    cloudtrail-cloudwatch-logs-integration

    Severity: medium · Enforcement: advisory

    Ensures CloudTrail trails have CloudWatch Logs integration enabled for real-time monitoring and analysis.

    • A.8.15 Logging — Logs that record activities, exceptions, faults and other relevant events shall be produced, stored, protected and analysed.
    Remediation
    Fix: Configure CloudWatch Logs Integration for CloudTrail

    Add the CloudWatch Logs group ARN and IAM role ARN to your CloudTrail trail configuration:

    const logGroup = new aws.cloudwatch.LogGroup("trail-log-group", {
        retentionInDays: 90,
    });
    
    const trailRole = new aws.iam.Role("trail-cloudwatch-role", {
        assumeRolePolicy: JSON.stringify({
            Version: "2012-10-17",
            Statement: [{
                Effect: "Allow",
                Principal: { Service: "cloudtrail.amazonaws.com" },
                Action: "sts:AssumeRole",
            }],
        }),
    });
    
    const trail = new aws.cloudtrail.Trail("my-trail", {
        s3BucketName: bucket.id,
        cloudWatchLogsGroupArn: logGroup.arn,  // Add this field
        cloudWatchLogsRoleArn: trailRole.arn,  // Add this field
    });
    

    cloudtrail-enabled

    Severity: critical · Enforcement: advisory

    Ensures CloudTrail is enabled with at least one active trail for audit logging.

    • A.8.15 Logging — Logs that record activities, exceptions, faults and other relevant events shall be produced, stored, protected and analysed.
    Remediation
    Fix: Enable CloudTrail for audit logging

    Create a CloudTrail trail to capture API activity and management events:

    import * as aws from "@pulumi/aws";
    
    // Create an S3 bucket for CloudTrail logs
    const trailBucket = new aws.s3.Bucket("cloudtrail-logs", {
        forceDestroy: true, // Only for demo - remove in production
    });
    
    // Create CloudTrail trail
    const trail = new aws.cloudtrail.Trail("main-trail", {
        s3BucketName: trailBucket.bucket,
        isMultiRegionTrail: true, // Enable for all regions
        includeGlobalServiceEvents: true,
        enableLogFileValidation: true, // Ensure log integrity
    });
    

    Key configuration:

    • Set isMultiRegionTrail: true to capture events across all AWS regions
    • Enable includeGlobalServiceEvents to capture IAM and STS events
    • Use enableLogFileValidation to ensure log integrity

    cloudtrail-kms-encryption-enabled

    Severity: high · Enforcement: advisory

    Ensures CloudTrail trails have encryption enabled using KMS keys.

    • A.5.33 Protection of records — Records shall be protected from loss, destruction, falsification, unauthorized access and unauthorized release.
    • A.8.15 Logging — Logs that record activities, exceptions, faults and other relevant events shall be produced, stored, protected and analysed.
    Remediation
    Fix: Enable KMS Encryption for CloudTrail

    Add a customer-managed KMS key to your CloudTrail trail configuration:

    import * as aws from "@pulumi/aws";
    
    // Create or reference a KMS key for CloudTrail encryption
    const trailKey = new aws.kms.Key("trail-key", {
        description: "KMS key for CloudTrail log encryption",
        enableKeyRotation: true,
    });
    
    const trail = new aws.cloudtrail.Trail("my-trail", {
        s3BucketName: bucket.id,
        kmsKeyId: trailKey.arn, // Add the KMS key ARN to enable encryption
    });
    

    cloudtrail-log-file-validation-enabled

    Severity: high · Enforcement: advisory

    Ensures CloudTrail trails have log file validation enabled to protect audit log integrity.

    • A.5.33 Protection of records — Records shall be protected from loss, destruction, falsification, unauthorized access and unauthorized release.
    • A.8.15 Logging — Logs that record activities, exceptions, faults and other relevant events shall be produced, stored, protected and analysed.
    Remediation
    Fix: Enable CloudTrail Log File Validation

    Update your CloudTrail trail configuration to enable log file validation:

    import * as aws from "@pulumi/aws";
    
    const trail = new aws.cloudtrail.Trail("my-trail", {
        s3BucketName: "my-cloudtrail-bucket",
        enableLogFileValidation: true, // Enable log file validation to ensure audit log integrity
    });
    

    This ensures CloudTrail logs are cryptographically signed, allowing you to verify they haven’t been modified after delivery.

    cloudtrail-multi-region-enabled

    Severity: high · Enforcement: advisory

    Ensures CloudTrail trails are configured as multi-region trails for comprehensive audit coverage.

    • A.8.15 Logging — Logs that record activities, exceptions, faults and other relevant events shall be produced, stored, protected and analysed.
    Remediation
    Fix: Enable Multi-Region Trail Configuration

    Set the isMultiRegionTrail property to true to enable comprehensive audit coverage across all AWS regions.

    const trail = new aws.cloudtrail.Trail("audit-trail", {
        s3BucketName: bucket.bucket,
        isMultiRegionTrail: true, // Enable multi-region trail for system-wide audit coverage
    });
    

    cloudtrail-s3-data-events-enabled

    Severity: medium · Enforcement: advisory

    Ensures CloudTrail trails have S3 data events enabled for comprehensive object-level logging.

    • A.8.15 Logging — Logs that record activities, exceptions, faults and other relevant events shall be produced, stored, protected and analysed.
    Remediation
    Fix: Enable S3 Data Events in CloudTrail

    Configure your CloudTrail trail to log S3 object-level operations by adding event selectors:

    import * as aws from "@pulumi/aws";
    
    const trail = new aws.cloudtrail.Trail("my-trail", {
        s3BucketName: trailBucket.bucket,
        // Enable S3 data events for all buckets
        eventSelectors: [{
            readWriteType: "All", // Log both read and write operations
            includeManagementEvents: true,
            dataResources: [{
                type: "AWS::S3::Object",
                values: ["arn:aws:s3:::*/*"], // Monitor all S3 objects
            }],
        }],
    });
    

    Alternatively, use advanced event selectors for more granular control:

    const trail = new aws.cloudtrail.Trail("my-trail", {
        s3BucketName: trailBucket.bucket,
        advancedEventSelectors: [{
            name: "Log S3 data events",
            fieldSelectors: [
                {
                    field: "eventCategory",
                    equals: ["Data"], // Data events category
                },
                {
                    field: "resources.type",
                    equals: ["AWS::S3::Object"], // S3 object operations
                },
            ],
        }],
    });
    

    cloudwatch-alarms-actions-required

    Severity: medium · Enforcement: advisory

    Ensures CloudWatch alarms have actions enabled and configured for proper incident response.

    • A.5.25 Assessment and decision on information security events — The organization shall assess information security events and decide if they are to be categorized as information security incidents.
    • A.5.26 Response to information security incidents — Information security incidents shall be responded to in accordance with the documented procedures.
    • A.8.16 Monitoring activities — Networks, systems and applications shall be monitored for anomalous behaviour and appropriate actions taken to evaluate potential information security incidents.
    Remediation
    Fix: Enable CloudWatch Alarm Actions

    Configure your CloudWatch alarm to have actions enabled and specify at least one action for the ALARM state:

    import * as aws from "@pulumi/aws";
    
    // Create SNS topic for alarm notifications
    const alarmTopic = new aws.sns.Topic("alarm-topic", {
        displayName: "CloudWatch Alarm Notifications",
    });
    
    // Create CloudWatch alarm with actions enabled
    const alarm = new aws.cloudwatch.MetricAlarm("my-alarm", {
        comparisonOperator: "GreaterThanThreshold",
        evaluationPeriods: 2,
        metricName: "CPUUtilization",
        namespace: "AWS/EC2",
        period: 120,
        statistic: "Average",
        threshold: 80,
        actionsEnabled: true,  // Enable actions (default: true)
        alarmActions: [alarmTopic.arn],  // Add SNS topic ARN for ALARM state
    });
    

    cloudwatch-log-group-kms-encryption-enabled

    Severity: high · Enforcement: advisory

    Ensures CloudWatch log groups have encryption enabled using KMS keys.

    • A.5.33 Protection of records — Records shall be protected from loss, destruction, falsification, unauthorized access and unauthorized release.
    • A.8.15 Logging — Logs that record activities, exceptions, faults and other relevant events shall be produced, stored, protected and analysed.
    Remediation
    Fix: Enable KMS Encryption for CloudWatch Log Group

    Add a KMS key to your CloudWatch log group resource to enable encryption at rest:

    import * as aws from "@pulumi/aws";
    
    const logGroup = new aws.cloudwatch.LogGroup("my-log-group", {
        name: "/aws/my-application",
        kmsKeyId: kmsKey.arn,  // Add KMS key ARN to enable encryption
        retentionInDays: 30,
    });
    

    cloudwatch-log-retention

    Severity: medium · Enforcement: advisory

    Ensures CloudWatch log groups have appropriate retention periods for compliance.

    • A.5.28 Collection of evidence — The organization shall establish and implement procedures for the identification, collection, acquisition and preservation of evidence related to information security events.
    • A.8.15 Logging — Logs that record activities, exceptions, faults and other relevant events shall be produced, stored, protected and analysed.
    Remediation
    Fix: Configure CloudWatch Log Group Retention Period

    Set the retentionInDays property to at least 365 days to meet audit record retention requirements.

    import * as aws from "@pulumi/aws";
    
    const logGroup = new aws.cloudwatch.LogGroup("my-log-group", {
        name: "/aws/lambda/my-function",
        retentionInDays: 365, // Set retention to at least 365 days for compliance
    });
    

    codebuild-project-artifact-encryption

    Severity: high · Enforcement: advisory

    Ensure CodeBuild project build artifacts are encrypted.

    • A.5.33 Protection of records — Records shall be protected from loss, destruction, falsification, unauthorized access and unauthorized release.
    Remediation
    Fix: Enable Encryption for CodeBuild Artifacts

    Do not set encryptionDisabled: true on primary or secondary artifacts so build outputs remain encrypted at rest.

    const project = new aws.codebuild.Project("build", {
        serviceRole: role.arn,
        source: { type: "NO_SOURCE" },
        environment: {
            computeType: "BUILD_GENERAL1_SMALL",
            image: "aws/codebuild/amazonlinux2-x86_64-standard:4.0",
            type: "LINUX_CONTAINER",
        },
        artifacts: {
            type: "S3",
            location: bucket.bucket,
            encryptionDisabled: false, // keep artifacts encrypted
        },
    });
    

    codebuild-project-envvar-awscred-check

    Severity: high · Enforcement: advisory

    Ensure CodeBuild project environment variables do not contain AWS credentials.

    • A.5.17 Authentication information — Allocation and management of authentication information shall be controlled by a management process, including advising personnel on appropriate handling of authentication information.
    Remediation
    Fix: Use Secure Storage for Credentials in CodeBuild
    const project = new aws.codebuild.Project("build", {
        environment: {
            environmentVariables: [
                {
                    name: "API_KEY",
                    value: "secret-arn",
                    type: "SECRETS_MANAGER",  // Use Secrets Manager for credentials
                },
                // OR
                {
                    name: "CONFIG_PARAM",
                    value: "param-name",
                    type: "PARAMETER_STORE",  // Use Parameter Store for config
                },
            ],
        },
        // ... other config
    });
    

    codebuild-project-logging

    Severity: medium · Enforcement: advisory

    Ensure CodeBuild projects have an enabled log destination.

    • A.8.15 Logging — Logs that record activities, exceptions, faults and other relevant events shall be produced, stored, protected and analysed.
    Remediation
    Fix: Enable Logging for CodeBuild Projects

    When configuring logsConfig, enable at least one destination so build logs are captured for audit.

    const project = new aws.codebuild.Project("build", {
        serviceRole: role.arn,
        artifacts: { type: "NO_ARTIFACTS" },
        source: { type: "NO_SOURCE" },
        environment: {
            computeType: "BUILD_GENERAL1_SMALL",
            image: "aws/codebuild/amazonlinux2-x86_64-standard:4.0",
            type: "LINUX_CONTAINER",
        },
        logsConfig: {
            cloudwatchLogs: {
                status: "ENABLED", // capture build logs
                groupName: "codebuild-logs",
            },
        },
    });
    

    codebuild-project-privileged-mode

    Severity: high · Enforcement: advisory

    Ensure CodeBuild projects do not run in privileged mode.

    • A.8.2 Privileged access rights — The allocation and use of privileged access rights shall be restricted and managed.
    Remediation
    Fix: Disable Privileged Mode on CodeBuild Projects

    Privileged mode grants the build container elevated access to the Docker daemon and host. Disable it unless Docker-in-Docker is strictly required.

    const project = new aws.codebuild.Project("build", {
        serviceRole: role.arn,
        artifacts: { type: "NO_ARTIFACTS" },
        source: { type: "NO_SOURCE" },
        environment: {
            computeType: "BUILD_GENERAL1_SMALL",
            image: "aws/codebuild/amazonlinux2-x86_64-standard:4.0",
            type: "LINUX_CONTAINER",
            privilegedMode: false, // do not run privileged
        },
    });
    

    codebuild-project-s3-logs-encryption

    Severity: medium · Enforcement: advisory

    Ensure CodeBuild project S3 build logs are encrypted.

    • A.5.33 Protection of records — Records shall be protected from loss, destruction, falsification, unauthorized access and unauthorized release.
    Remediation
    Fix: Enable Encryption for CodeBuild S3 Logs

    Do not set encryptionDisabled: true on the S3 logs configuration so build logs remain encrypted at rest.

    const project = new aws.codebuild.Project("build", {
        serviceRole: role.arn,
        artifacts: { type: "NO_ARTIFACTS" },
        source: { type: "NO_SOURCE" },
        environment: {
            computeType: "BUILD_GENERAL1_SMALL",
            image: "aws/codebuild/amazonlinux2-x86_64-standard:4.0",
            type: "LINUX_CONTAINER",
        },
        logsConfig: {
            s3Logs: {
                status: "ENABLED",
                location: `${bucket.id}/build-log`,
                encryptionDisabled: false, // keep S3 logs encrypted
            },
        },
    });
    

    config-recorder-enabled

    Severity: high · Enforcement: advisory

    Ensures AWS Config configuration recorders are enabled for tracking and auditing resource changes.

    • A.8.9 Configuration management — Configurations, including security configurations, of hardware, software, services and networks shall be established, documented, implemented, monitored and reviewed.
    Remediation
    Fix: Enable AWS Config Recorder

    Create a Config Recorder with RecorderStatus to track all resource changes:

    import * as aws from "@pulumi/aws";
    
    // Create Config Recorder
    const recorder = new aws.cfg.Recorder("config-recorder", {
        recordingGroup: {
            allSupported: true,  // Record all supported resource types
            includeGlobalResourceTypes: true,  // Include global resources (IAM, etc.)
        },
        roleArn: configRole.arn,  // IAM role with Config permissions
    });
    
    // Activate the recorder
    const recorderStatus = new aws.cfg.RecorderStatus("config-recorder-status", {
        name: recorder.name,
        isEnabled: true,  // Enable the recorder
    });
    

    config-snapshot-retention

    Severity: medium · Enforcement: advisory

    Ensures AWS Config retention configuration meets minimum 7-year requirement for compliance auditing.

    • A.8.9 Configuration management — Configurations, including security configurations, of hardware, software, services and networks shall be established, documented, implemented, monitored and reviewed.
    Remediation
    Fix: Set AWS Config retention period to minimum 7 years

    Configure the AWS Config retention configuration to retain snapshots for at least 2555 days (7 years):

    import * as aws from "@pulumi/aws";
    
    const configRetention = new aws.cfg.RetentionConfiguration("config-retention", {
        retentionPeriodInDays: 2555, // Set to 7 years (minimum required)
    });
    

    database-strict-network-access

    Severity: critical · Enforcement: advisory

    Ensures RDS instances have strict network access controls

    • A.8.3 Information access restriction — Access to information and other associated assets shall be restricted in accordance with the established topic-specific policy on access control.
    • A.8.20 Networks security — Networks and network devices shall be secured, managed and controlled to protect information in systems and applications.
    Remediation
    Fix: Configure Strict Network Access for Database Resources

    Restrict database access to specific internal sources only. Never allow public access (0.0.0.0/0) to database ports.

    // Create a security group with restricted ingress
    const dbSecurityGroup = new aws.ec2.SecurityGroup("db-sg", {
        vpcId: vpc.id,
        ingress: [{
            protocol: "tcp",
            fromPort: 3306,
            toPort: 3306,
            cidrBlocks: ["10.0.0.0/16"], // Restrict to internal VPC CIDR only
        }],
    });
    
    // Associate security group with RDS instance
    const db = new aws.rds.Instance("my-db", {
        engine: "mysql",
        instanceClass: "db.t3.micro",
        allocatedStorage: 20,
        vpcSecurityGroupIds: [dbSecurityGroup.id], // Attach security group
        dbSubnetGroupName: dbSubnetGroup.name,
    });
    
    // Ensure subnet group has at least 2 subnets
    const dbSubnetGroup = new aws.rds.SubnetGroup("db-subnet-group", {
        subnetIds: [privateSubnet1.id, privateSubnet2.id], // Minimum 2 subnets
    });
    

    dax-cluster-encryption-at-rest

    Severity: high · Enforcement: advisory

    Require DAX clusters to enable server-side encryption at rest

    • A.5.33 Protection of records — Records shall be protected from loss, destruction, falsification, unauthorized access and unauthorized release.
    Remediation
    Fix: Enable DAX Cluster Encryption At Rest

    Set serverSideEncryption.enabled to true on the DAX cluster.

    const cluster = new aws.dax.Cluster("my-cluster", {
        clusterName: "my-cluster",
        iamRoleArn: role.arn,
        nodeType: "dax.r4.large",
        replicationFactor: 1,
        serverSideEncryption: { enabled: true },
    });
    

    dax-cluster-endpoint-encryption

    Severity: high · Enforcement: advisory

    Require DAX clusters to use TLS endpoint encryption in transit

    • A.5.14 Information transfer — Information transfer rules, procedures, or agreements shall be in place for all types of transfer facilities within the organization and between the organization and other parties.
    Remediation
    Fix: Enable DAX Cluster Endpoint Encryption (TLS)

    Set clusterEndpointEncryptionType to "TLS" on the DAX cluster.

    const cluster = new aws.dax.Cluster("my-cluster", {
        clusterName: "my-cluster",
        iamRoleArn: role.arn,
        nodeType: "dax.r4.large",
        replicationFactor: 1,
        clusterEndpointEncryptionType: "TLS",
    });
    

    dms-endpoint-redis-tls

    Severity: high · Enforcement: advisory

    DMS Redis endpoints must use TLS for transmission

    • A.5.14 Information transfer — Information transfer rules, procedures, or agreements shall be in place for all types of transfer facilities within the organization and between the organization and other parties.
    Remediation
    Fix: Require TLS on DMS Redis Endpoint

    The default value of sslSecurityProtocol is "ssl-encryption". Remove the explicit "plaintext" override to restore TLS.

    new aws.dms.Endpoint("endpoint", {
        endpointId: "my-redis-endpoint",
        endpointType: "target",
        engineName: "redis",
        redisSettings: {
            authType: "none",
            port: 6379,
            serverName: "redis.example.com",
            sslSecurityProtocol: "ssl-encryption",
        },
    });
    

    dms-endpoint-ssl

    Severity: high · Enforcement: advisory

    DMS endpoints must require SSL/TLS connections

    • A.5.14 Information transfer — Information transfer rules, procedures, or agreements shall be in place for all types of transfer facilities within the organization and between the organization and other parties.
    Remediation
    Fix: Require SSL/TLS on DMS Endpoint

    Set sslMode to one of require, verify-ca, or verify-full.

    new aws.dms.Endpoint("endpoint", {
        endpointId: "my-endpoint",
        endpointType: "source",
        engineName: "mysql",
        sslMode: "verify-full",
    });
    

    dms-no-public-access

    Severity: critical · Enforcement: advisory

    Ensures DMS replication instances are not publicly accessible to maintain security.

    • A.5.15 Access control — Rules to control physical and logical access to information and other associated assets shall be established and implemented based on business and information security requirements.
    • A.8.3 Information access restriction — Access to information and other associated assets shall be restricted in accordance with the established topic-specific policy on access control.
    Remediation
    Fix: Disable Public Accessibility
    const replicationInstance = new aws.dms.ReplicationInstance("my-replication-instance", {
        replicationInstanceClass: "dms.t3.micro",
        publiclyAccessible: false,  // Set to false to prevent public access
        // ... other config
    });
    

    docdb-cluster-backup-retention

    Severity: medium · Enforcement: advisory

    Require DocumentDB clusters to retain automated backups for a minimum period

    • A.8.13 Information backup — Backup copies of information, software and systems shall be maintained and regularly tested in accordance with the agreed topic-specific policy on backup.
    Remediation
    Fix: Set DocumentDB Cluster Backup Retention

    Set backupRetentionPeriod to at least the required number of days.

    const cluster = new aws.docdb.Cluster("my-cluster", {
        clusterIdentifier: "my-docdb-cluster",
        masterUsername: "admin",
        masterPassword: password,
        backupRetentionPeriod: 7,
    });
    

    docdb-cluster-encryption-at-rest

    Severity: high · Enforcement: advisory

    Require DocumentDB clusters to enable storage encryption at rest

    • A.5.33 Protection of records — Records shall be protected from loss, destruction, falsification, unauthorized access and unauthorized release.
    Remediation
    Fix: Enable DocumentDB Cluster Encryption At Rest

    Set storageEncrypted to true on the DocumentDB cluster.

    const cluster = new aws.docdb.Cluster("my-cluster", {
        clusterIdentifier: "my-docdb-cluster",
        masterUsername: "admin",
        masterPassword: password,
        storageEncrypted: true,
    });
    

    docdb-clusterinstance-managed-service-patching

    Severity: medium · Enforcement: advisory

    Ensures DocumentDB cluster instances have automated minor version upgrades enabled

    • A.8.8 Management of technical vulnerabilities — Information about technical vulnerabilities of information systems in use shall be obtained, the organization’s exposure to such vulnerabilities shall be evaluated and appropriate measures shall be taken.
    Remediation
    Fix: Enable Automatic Minor Version Upgrades for DocumentDB Cluster Instance

    Set the autoMinorVersionUpgrade property to true to enable automated patching for managed service security updates:

    const clusterInstance = new aws.docdb.ClusterInstance("my-cluster-instance", {
        clusterIdentifier: cluster.id,
        instanceClass: "db.r5.large",
        autoMinorVersionUpgrade: true, // Enable automatic minor version upgrades
    });
    

    dynamodb-autoscaling-enabled

    Severity: low · Enforcement: advisory

    Ensures DynamoDB tables have auto-scaling or on-demand mode enabled for capacity management.

    • A.8.6 Capacity management — The use of resources shall be monitored and adjusted in line with current and expected capacity requirements.
    Remediation
    Fix: Enable DynamoDB Auto-Scaling or On-Demand Mode

    Configure auto-scaling targets and policies for your DynamoDB table’s read and write capacity, or switch to on-demand billing mode:

    import * as aws from "@pulumi/aws";
    
    const table = new aws.dynamodb.Table("myTable", {
        name: "my-table",
        billingMode: "PROVISIONED", // Use provisioned mode with auto-scaling
        readCapacity: 5,
        writeCapacity: 5,
        attributes: [{ name: "id", type: "S" }],
        hashKey: "id",
    });
    
    // Configure read capacity auto-scaling
    const readTarget = new aws.appautoscaling.Target("readTarget", {
        resourceId: pulumi.interpolate`table/${table.name}`,
        scalableDimension: "dynamodb:table:ReadCapacityUnits",
        serviceNamespace: "dynamodb",
        minCapacity: 5,
        maxCapacity: 100, // Set appropriate scaling limits
    });
    
    new aws.appautoscaling.Policy("readPolicy", {
        resourceId: readTarget.resourceId,
        scalableDimension: readTarget.scalableDimension,
        serviceNamespace: readTarget.serviceNamespace,
        policyType: "TargetTrackingScaling",
        targetTrackingScalingPolicyConfiguration: {
            targetValue: 70.0, // Target utilization percentage
            predefinedMetricSpecification: {
                predefinedMetricType: "DynamoDBReadCapacityUtilization",
            },
        },
    });
    
    // Configure write capacity auto-scaling
    const writeTarget = new aws.appautoscaling.Target("writeTarget", {
        resourceId: pulumi.interpolate`table/${table.name}`,
        scalableDimension: "dynamodb:table:WriteCapacityUnits",
        serviceNamespace: "dynamodb",
        minCapacity: 5,
        maxCapacity: 100,
    });
    
    new aws.appautoscaling.Policy("writePolicy", {
        resourceId: writeTarget.resourceId,
        scalableDimension: writeTarget.scalableDimension,
        serviceNamespace: writeTarget.serviceNamespace,
        policyType: "TargetTrackingScaling",
        targetTrackingScalingPolicyConfiguration: {
            targetValue: 70.0,
            predefinedMetricSpecification: {
                predefinedMetricType: "DynamoDBWriteCapacityUtilization",
            },
        },
    });
    
    // Alternative: Use on-demand billing mode (no auto-scaling needed)
    // const table = new aws.dynamodb.Table("myTable", {
    //     billingMode: "PAY_PER_REQUEST", // On-demand mode handles scaling automatically
    //     attributes: [{ name: "id", type: "S" }],
    //     hashKey: "id",
    // });
    

    dynamodb-kms-encryption-enabled

    Severity: high · Enforcement: advisory

    Ensures DynamoDB tables have encryption enabled using KMS keys.

    • A.5.33 Protection of records — Records shall be protected from loss, destruction, falsification, unauthorized access and unauthorized release.
    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Enable Customer-Managed KMS Encryption for DynamoDB Table

    Configure the DynamoDB table with a customer-managed KMS key for encryption at rest:

    import * as aws from "@pulumi/aws";
    
    // Create or reference a customer-managed KMS key
    const kmsKey = new aws.kms.Key("table-encryption-key", {
        description: "KMS key for DynamoDB table encryption",
        deletionWindowInDays: 10,
    });
    
    const table = new aws.dynamodb.Table("my-table", {
        // ... other configuration ...
        serverSideEncryption: {
            enabled: true,  // Enable encryption
            kmsKeyArn: kmsKey.arn,  // Use customer-managed KMS key (not AWS-managed)
        },
    });
    

    dynamodb-point-in-time-recovery-enabled

    Severity: medium · Enforcement: advisory

    DynamoDB tables must have point-in-time recovery enabled

    • A.5.29 Information security during disruption — The organization shall plan how to maintain information security at an appropriate level during disruption.
    • A.8.13 Information backup — Backup copies of information, software and systems shall be maintained and regularly tested in accordance with the agreed topic-specific policy on backup.
    • A.5.30 ICT readiness for business continuity — ICT readiness shall be planned, implemented, maintained and tested based on business continuity objectives and ICT continuity requirements.
    Remediation
    Fix: Enable Point-in-Time Recovery on DynamoDB Table

    Add the pointInTimeRecovery property to your DynamoDB table configuration and set enabled to true.

    const table = new aws.dynamodb.Table("my-table", {
        name: "my-table",
        attributes: [
            { name: "id", type: "S" },
        ],
        hashKey: "id",
        billingMode: "PAY_PER_REQUEST",
        // Enable point-in-time recovery for backup and recovery capabilities
        pointInTimeRecovery: {
            enabled: true,  // Set to true to enable PITR
        },
    });
    

    ebs-snapshot-not-publicly-restorable

    Severity: high · Enforcement: advisory

    Ensure EBS snapshots are not publicly restorable to prevent unauthorized data access.

    • A.5.15 Access control — Rules to control physical and logical access to information and other associated assets shall be established and implemented based on business and information security requirements.
    Remediation
    Fix: Keep Snapshots Private
    const snapshot = new aws.ebs.Snapshot("backup-snapshot", {
        volumeId: volume.id,
        description: "Private backup snapshot",
        tags: {
            Name: "db-backup",
        },
    });
    
    // Do NOT add aws.ec2.SnapshotCreateVolumePermission with accountId: "all"
    // Snapshots are private by default
    

    ebs-volume-configure-customer-managed-key

    Severity: low · Enforcement: advisory

    Check that encrypted EBS volumes use a customer-managed KMS key.

    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Configure Customer-Managed KMS Key for EBS Volume

    Specify a customer-managed KMS key using the kmsKeyId property when creating an encrypted EBS volume:

    const volume = new aws.ebs.Volume("my-volume", {
        availabilityZone: "us-west-2a",
        size: 100,
        encrypted: true,
        kmsKeyId: customerKey.arn, // Use customer-managed KMS key instead of default AWS-managed key
    });
    

    ebs-volume-disallow-unencrypted-volume

    Severity: high · Enforcement: advisory

    Checks that EBS volumes are encrypted.

    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Enable EBS Volume Encryption

    Set the encrypted property to true on the EBS volume:

    const volume = new aws.ebs.Volume("my-volume", {
        availabilityZone: "us-west-2a",
        size: 100,
        encrypted: true, // Enable encryption for the volume
    });
    

    ebs-volume-in-backup-plan

    Severity: medium · Enforcement: advisory

    Ensure EBS volumes are included in AWS Backup plans for automated backup and recovery capabilities.

    • A.8.13 Information backup — Backup copies of information, software and systems shall be maintained and regularly tested in accordance with the agreed topic-specific policy on backup.
    Remediation
    Fix: Add EBS Volume to Backup Plan
    // Create backup vault
    const vault = new aws.backup.Vault("ebs-vault", {
        name: "ebs-backup-vault",
    });
    
    // Create IAM role for AWS Backup
    const backupRole = new aws.iam.Role("backup-role", {
        assumeRolePolicy: JSON.stringify({
            Version: "2012-10-17",
            Statement: [{
                Effect: "Allow",
                Principal: { Service: "backup.amazonaws.com" },
                Action: "sts:AssumeRole",
            }],
        }),
        managedPolicyArns: ["arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForBackup"],
    });
    
    // Create backup plan
    const backupPlan = new aws.backup.Plan("ebs-backup-plan", {
        name: "daily-ebs-backups",
        rules: [{
            ruleName: "daily-backup",
            targetVaultName: vault.name,
            schedule: "cron(0 2 * * ? *)",
            lifecycle: {
                deleteAfter: 30,
            },
        }],
    });
    
    // Add EBS volumes to backup selection
    const backupSelection = new aws.backup.Selection("ebs-volumes", {
        name: "all-ebs-volumes",
        planId: backupPlan.id,
        iamRoleArn: backupRole.arn,
        resources: ["arn:aws:ec2:*:*:volume/*"],
    });
    

    ec2-clientvpn-connection-logging

    Severity: medium · Enforcement: advisory

    Client VPN endpoints must enable connection logging to record client connection events.

    • A.8.15 Logging — Logs that record activities, exceptions, faults and other relevant events shall be produced, stored, protected and analysed.
    Remediation
    Fix: Enable Connection Logging on the Client VPN Endpoint

    Set connectionLogOptions.enabled to true and provide a CloudWatch Logs group.

    const endpoint = new aws.ec2clientvpn.Endpoint("my-endpoint", {
        connectionLogOptions: {
            enabled: true,
            cloudwatchLogGroup: logGroup.name,
        },
        // ... other configuration
    });
    

    ec2-iam-profile-required

    Severity: medium · Enforcement: advisory

    EC2 instances must have IAM profile attached

    • A.5.15 Access control — Rules to control physical and logical access to information and other associated assets shall be established and implemented based on business and information security requirements.
    Remediation
    Fix: Attach IAM Instance Profile
    const role = new aws.iam.Role("ec2-role", {
        assumeRolePolicy: JSON.stringify({
            Version: "2012-10-17",
            Statement: [{
                Action: "sts:AssumeRole",
                Effect: "Allow",
                Principal: { Service: "ec2.amazonaws.com" },
            }],
        }),
    });
    
    const profile = new aws.iam.InstanceProfile("ec2-profile", {
        role: role.name,
    });
    
    const instance = new aws.ec2.Instance("app-server", {
        ami: "ami-12345678",
        instanceType: "t3.medium",
        iamInstanceProfile: profile.name,  // Attach IAM instance profile for role-based access
        subnetId: subnet.id,
    });
    

    ec2-imdsv2-required

    Severity: medium · Enforcement: advisory

    EC2 instances must use IMDSv2

    • A.5.15 Access control — Rules to control physical and logical access to information and other associated assets shall be established and implemented based on business and information security requirements.
    • A.8.3 Information access restriction — Access to information and other associated assets shall be restricted in accordance with the established topic-specific policy on access control.
    Remediation
    Fix: Enable IMDSv2 for EC2 Instance

    Configure the EC2 instance to require IMDSv2 by setting metadataOptions.httpTokens to "required":

    new aws.ec2.Instance("my-instance", {
        instanceType: "t3.micro",
        ami: "ami-12345678",
        metadataOptions: {
            httpTokens: "required",  // Enforce IMDSv2
        },
    });
    

    ec2-instance-disallow-public-ip

    Severity: high · Enforcement: advisory

    Checks that EC2 instances do not have a public IP address.

    • A.5.15 Access control — Rules to control physical and logical access to information and other associated assets shall be established and implemented based on business and information security requirements.
    • A.8.3 Information access restriction — Access to information and other associated assets shall be restricted in accordance with the established topic-specific policy on access control.
    Remediation
    Fix: Disable Public IP Address Assignment

    Set associatePublicIpAddress to false to prevent the instance from receiving a public IP address:

    const instance = new ec2.Instance("my-instance", {
        instanceType: "t3.micro",
        ami: "ami-12345678",
        associatePublicIpAddress: false, // Disable public IP assignment
        subnetId: privateSubnet.id,
    });
    

    ec2-instance-disallow-unencrypted-block-device

    Severity: high · Enforcement: advisory

    Checks that EC2 instances do not have unencrypted block devices.

    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Enable Encryption for EBS Block Devices

    Set the encrypted property to true for all EBS block devices attached to EC2 instances:

    const instance = new aws.ec2.Instance("my-instance", {
        ami: "ami-12345678",
        instanceType: "t3.micro",
        ebsBlockDevices: [{
            deviceName: "/dev/sdf",
            volumeSize: 20,
            encrypted: true, // Enable encryption for the EBS volume
        }],
    });
    

    ec2-instance-disallow-unencrypted-root-block-device

    Severity: high · Enforcement: advisory

    Checks that EC2 instances does not have unencrypted root volumes.

    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Enable Encryption for Root Block Device

    Set the encrypted property to true in the rootBlockDevice configuration:

    const instance = new aws.ec2.Instance("my-instance", {
        instanceType: "t3.micro",
        ami: "ami-12345678",
        rootBlockDevice: {
            encrypted: true, // Enable encryption for root volume
        },
    });
    

    ec2-launch-configuration-disallow-public-ip

    Severity: high · Enforcement: advisory

    Checks that EC2 Launch Configurations do not have a public IP address.

    • A.8.3 Information access restriction — Access to information and other associated assets shall be restricted in accordance with the established topic-specific policy on access control.
    Remediation
    Fix: Disable Public IP Assignment for Launch Configuration

    Set the associatePublicIpAddress property to false to prevent instances from receiving public IP addresses:

    const launchConfig = new aws.ec2.LaunchConfiguration("my-launch-config", {
        imageId: "ami-12345678",
        instanceType: "t3.micro",
        associatePublicIpAddress: false, // Disable public IP assignment
        securityGroups: [securityGroup.id],
    });
    

    ec2-launch-configuration-disallow-unencrypted-block-device

    Severity: high · Enforcement: advisory

    Checks that EC2 Launch Configurations do not have unencrypted block devices.

    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Enable EBS Block Device Encryption

    Set the encrypted property to true for all EBS block devices in the Launch Configuration:

    const launchConfig = new aws.ec2.LaunchConfiguration("my-launch-config", {
        imageId: "ami-12345678",
        instanceType: "t3.medium",
        ebsBlockDevices: [{
            deviceName: "/dev/sdf",
            volumeSize: 100,
            encrypted: true, // Enable encryption for all EBS block devices
        }],
    });
    

    ec2-launch-configuration-disallow-unencrypted-root-block-device

    Severity: high · Enforcement: advisory

    Checks that EC2 launch configuration do not have unencrypted root block device.

    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Enable Encryption for Root Block Device

    Set the encrypted property to true in the rootBlockDevice configuration:

    const launchConfig = new ec2.LaunchConfiguration("my-launch-config", {
        imageId: "ami-0c55b159cbfafe1f0",
        instanceType: "t2.micro",
        rootBlockDevice: {
            encrypted: true, // Enable encryption for root block device
        },
    });
    

    ec2-launch-template-configure-customer-managed-key

    Severity: low · Enforcement: advisory

    Check that encrypted EBS volume uses a customer-managed KMS key.

    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Specify Customer-Managed KMS Key for Encrypted EBS Volumes

    Add the kmsKeyId property to encrypted EBS block device mappings in your Launch Template:

    const launchTemplate = new aws.ec2.LaunchTemplate("my-template", {
        blockDeviceMappings: [{
            ebs: {
                encrypted: "true",
                kmsKeyId: customerManagedKey.id, // Specify customer-managed KMS key
                volumeSize: 20,
            },
        }],
    });
    

    ec2-launch-template-disallow-public-ip

    Severity: high · Enforcement: advisory

    Checks that EC2 Launch Templates do not have public IP addresses.

    • A.8.3 Information access restriction — Access to information and other associated assets shall be restricted in accordance with the established topic-specific policy on access control.
    Remediation
    Fix: Disable Public IP Assignment in Launch Template

    Set associatePublicIpAddress to false (or omit it) in the network interface configuration to prevent instances from receiving public IP addresses:

    const launchTemplate = new aws.ec2.LaunchTemplate("my-template", {
        imageId: "ami-12345678",
        instanceType: "t3.micro",
        networkInterfaces: [{
            associatePublicIpAddress: "false", // Disable public IP assignment
            securityGroups: [securityGroup.id],
            subnetId: privateSubnet.id,
        }],
    });
    

    ec2-launch-template-disallow-unencrypted-block-device

    Severity: high · Enforcement: advisory

    Checks that EC2 Launch Templates do not have unencrypted block device.

    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Enable EBS Volume Encryption in Launch Template

    Set the encrypted property to “true” for all block device mappings in the Launch Template:

    const launchTemplate = new aws.ec2.LaunchTemplate("my-template", {
        imageId: "ami-12345678",
        instanceType: "t3.micro",
        blockDeviceMappings: [{
            deviceName: "/dev/sda1",
            ebs: {
                encrypted: "true", // Enable encryption for the EBS volume
                volumeSize: 20,
                volumeType: "gp3",
            },
        }],
    });
    

    ec2-monitoring-enabled

    Severity: low · Enforcement: advisory

    EC2 instances must have detailed monitoring enabled

    • A.8.16 Monitoring activities — Networks, systems and applications shall be monitored for anomalous behaviour and appropriate actions taken to evaluate potential information security incidents.
    Remediation
    Fix: Enable Detailed Monitoring on EC2 Instance

    Set the monitoring property to true on your EC2 instance resource:

    const instance = new aws.ec2.Instance("my-instance", {
        ami: "ami-12345678",
        instanceType: "t3.micro",
        monitoring: true, // Enable detailed (1-minute interval) monitoring
    });
    

    ec2-security-group-disallow-inbound-http-traffic

    Severity: high · Enforcement: advisory

    Check that EC2 Security Groups do not allow inbound HTTP traffic.

    • A.5.14 Information transfer — Information transfer rules, procedures, or agreements shall be in place for all types of transfer facilities within the organization and between the organization and other parties.
    • A.8.20 Networks security — Networks and network devices shall be secured, managed and controlled to protect information in systems and applications.
    Remediation
    Fix: Remove HTTP Inbound Traffic Rules

    Remove any ingress rules that allow HTTP traffic on port 80, or use HTTPS (port 443) instead:

    const securityGroup = new ec2.SecurityGroup("my-sg", {
        vpcId: vpc.id,
        ingress: [
            {
                protocol: "tcp",
                fromPort: 443, // Use HTTPS instead of HTTP (port 80)
                toPort: 443,
                cidrBlocks: ["0.0.0.0/0"],
            },
            // Remove any rules with fromPort: 80 or toPort: 80
        ],
    });
    

    ec2-vpc-placement-required

    Severity: high · Enforcement: advisory

    EC2 instances must be placed in VPC for network isolation

    • A.8.20 Networks security — Networks and network devices shall be secured, managed and controlled to protect information in systems and applications.
    • A.8.22 Segregation of networks — Groups of information services, users and information systems shall be segregated in the organization’s networks.
    Remediation
    Fix: Place EC2 Instance in a VPC Subnet

    Add the subnetId property to your EC2 instance resource to ensure it’s deployed within a VPC for proper network isolation.

    new aws.ec2.Instance("my-instance", {
        ami: "ami-12345678",
        instanceType: "t3.micro",
        subnetId: mySubnet.id, // Specify a subnet to place instance in VPC
        // ... other configuration
    });
    

    ecr-image-scanning

    Severity: medium · Enforcement: advisory

    Ensures ECR repositories have image scanning enabled for vulnerability management

    • A.8.8 Management of technical vulnerabilities — Information about technical vulnerabilities of information systems in use shall be obtained, the organization’s exposure to such vulnerabilities shall be evaluated and appropriate measures shall be taken.
    Remediation
    Fix: Enable Image Scanning for ECR Repository

    Set the imageScanningConfiguration with scanOnPush: true to automatically scan container images for vulnerabilities when they are pushed:

    const repository = new aws.ecr.Repository("my-repo", {
        name: "my-application",
        imageScanningConfiguration: {
            scanOnPush: true, // Enable automatic vulnerability scanning
        },
    });
    

    ecr-repository-configure-customer-managed-key

    Severity: low · Enforcement: advisory

    Checks that ECR repositories use a customer-managed KMS key.

    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Configure Customer-Managed KMS Key for ECR Repository

    Set the encryptionConfiguration with encryptionType to “KMS” and provide a kmsKey ARN to use customer-managed encryption:

    const kmsKey = new aws.kms.Key("ecr-key", {
        description: "KMS key for ECR repository encryption",
    });
    
    const repo = new ecr.Repository("my-repo", {
        encryptionConfigurations: [{
            encryptionType: "KMS", // Use KMS encryption instead of AES256
            kmsKey: kmsKey.arn, // Specify customer-managed KMS key
        }],
    });
    

    ecr-repository-disallow-unencrypted-repository

    Severity: high · Enforcement: advisory

    Checks that ECR Repositories are encrypted.

    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Enable Encryption for ECR Repository

    Configure the encryptionConfigurations property to enable encryption at rest for your ECR repository:

    const repo = new ecr.Repository("my-repo", {
        name: "my-application-repo",
        encryptionConfigurations: [{ // Enable encryption
            encryptionType: "AES256", // Use AWS managed encryption (or "KMS" for customer-managed keys)
        }],
    });
    

    ecs-task-definition-image-scanning

    Severity: medium · Enforcement: advisory

    Ensures ECS task definitions use images from repositories with vulnerability scanning

    • A.8.8 Management of technical vulnerabilities — Information about technical vulnerabilities of information systems in use shall be obtained, the organization’s exposure to such vulnerabilities shall be evaluated and appropriate measures shall be taken.
    Remediation
    Fix: Use ECR Images with Scanning Enabled

    Update your ECS task definition to use container images from ECR repositories that have vulnerability scanning enabled:

    const taskDefinition = new aws.ecs.TaskDefinition("my-task", {
        family: "my-app",
        containerDefinitions: JSON.stringify([{
            name: "app",
            image: "123456789012.dkr.ecr.us-east-1.amazonaws.com/my-repo:latest", // Use ECR image with scanning
            memory: 512,
            cpu: 256,
        }]),
        requiresCompatibilities: ["FARGATE"],
        networkMode: "awsvpc",
        cpu: "256",
        memory: "512",
    });
    

    ecs-task-non-privileged-required

    Severity: high · Enforcement: advisory

    ECS task definitions must use non-privileged user for host mode

    • A.5.15 Access control — Rules to control physical and logical access to information and other associated assets shall be established and implemented based on business and information security requirements.
    • A.8.2 Privileged access rights — The allocation and use of privileged access rights shall be restricted and managed.
    Remediation
    Fix: Remove Privileged Container Settings
    const taskDefinition = new aws.ecs.TaskDefinition("app-task", {
        family: "app-task",
        containerDefinitions: JSON.stringify([{
            name: "app-container",
            image: "nginx:latest",
            privileged: false,  // Set to false to disable privileged mode
            user: "1000:1000",  // For host network mode: specify non-root user (UID:GID)
            linuxParameters: {
                capabilities: {
                    add: ["NET_BIND_SERVICE"],  // Avoid SYS_ADMIN, NET_ADMIN, or ALL
                },
            },
        }]),
    });
    

    efs-accesspoint-posix-user

    Severity: medium · Enforcement: advisory

    EFS access points must enforce a POSIX user identity so all file system requests are made with a defined user.

    • A.8.3 Information access restriction — Access to information and other associated assets shall be restricted in accordance with the established topic-specific policy on access control.
    Remediation
    Fix: Enforce a POSIX User Identity on the EFS Access Point

    Set the posixUser block so all requests through the access point use a defined user identity.

    const accessPoint = new aws.efs.AccessPoint("my-ap", {
        fileSystemId: fs.id,
        posixUser: {
            uid: 1000,
            gid: 1000,
        },
    });
    

    efs-file-system-configure-customer-managed-key

    Severity: low · Enforcement: advisory

    Check that encrypted EFS File system uses a customer-managed KMS key.

    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Configure Customer-Managed KMS Key for EFS Encryption

    Set the kmsKeyId property to specify a customer-managed KMS key for EFS file system encryption:

    const fileSystem = new aws.efs.FileSystem("my-efs", {
        encrypted: true,
        kmsKeyId: kmsKey.arn, // Use customer-managed KMS key instead of AWS-managed key
        lifecyclePolicy: {
            transitionToIa: "AFTER_30_DAYS",
        },
    });
    

    efs-file-system-disallow-unencrypted-file-system

    Severity: high · Enforcement: advisory

    Checks that EFS File Systems do not have an unencrypted file system.

    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Enable Encryption for EFS File System

    Set the encrypted property to true when creating an EFS file system:

    const fileSystem = new aws.efs.FileSystem("my-efs", {
        encrypted: true, // Enable encryption at rest
        kmsKeyId: kmsKey.arn, // Optional: specify a custom KMS key
    });
    

    eks-cluster-disallow-api-endpoint-public-access

    Severity: critical · Enforcement: advisory

    Check that EKS Clusters API Endpoint are not publicly accessible.

    • A.8.3 Information access restriction — Access to information and other associated assets shall be restricted in accordance with the established topic-specific policy on access control.
    Remediation
    Fix: Disable Public Access to EKS Cluster API Endpoint

    Set endpointPublicAccess to false and endpointPrivateAccess to true in the VPC configuration:

    const cluster = new eks.Cluster("my-cluster", {
        vpcConfig: {
            subnetIds: privateSubnetIds,
            endpointPublicAccess: false, // Disable public access to API endpoint
            endpointPrivateAccess: true, // Enable private access for internal communication
        },
        // ... other configuration
    });
    

    eks-cluster-enable-cluster-encryption-config

    Severity: high · Enforcement: advisory

    Check that EKS Cluster Encryption Config is enabled.

    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Enable EKS Cluster Encryption Configuration

    Configure the encryptionConfig property to encrypt Kubernetes secrets using AWS KMS:

    const cluster = new aws.eks.Cluster("my-cluster", {
        roleArn: clusterRole.arn,
        vpcConfig: {
            subnetIds: subnetIds,
        },
        encryptionConfig: { // Enable encryption for Kubernetes secrets
            provider: {
                keyArn: kmsKey.arn, // KMS key for encrypting secrets
            },
            resources: ["secrets"], // Encrypt Kubernetes secrets at rest
        },
    });
    

    eks-cluster-logging

    Severity: medium · Enforcement: advisory

    EKS clusters must enable control plane logging for all required log types.

    • A.8.15 Logging — Logs that record activities, exceptions, faults and other relevant events shall be produced, stored, protected and analysed.
    Remediation
    Fix: Enable Control Plane Logging on the EKS Cluster

    Set enabledClusterLogTypes to include all required control plane log types.

    const cluster = new aws.eks.Cluster("my-cluster", {
        enabledClusterLogTypes: ["api", "audit", "authenticator", "controllerManager", "scheduler"],
        // ... other configuration
    });
    

    elasticache-backup-retention

    Severity: medium · Enforcement: advisory

    ElastiCache Redis clusters must have automatic backup retention for 15 days

    • A.5.29 Information security during disruption — The organization shall plan how to maintain information security at an appropriate level during disruption.
    • A.8.13 Information backup — Backup copies of information, software and systems shall be maintained and regularly tested in accordance with the agreed topic-specific policy on backup.
    • A.5.30 ICT readiness for business continuity — ICT readiness shall be planned, implemented, maintained and tested based on business continuity objectives and ICT continuity requirements.
    Remediation
    Fix: Configure ElastiCache Backup Retention

    Set the snapshotRetentionLimit property to enable automatic backups with the required retention period:

    new aws.elasticache.ReplicationGroup("redis-cluster", {
        replicationGroupId: "my-redis-cluster",
        // Enable automatic backups with minimum 15 days retention
        snapshotRetentionLimit: 15,
        // Optional: Configure backup window during low-traffic periods
        snapshotWindow: "03:00-05:00",
        // Optional: Preserve data when cluster is deleted
        finalSnapshotIdentifier: "final-snapshot-redis-cluster",
    });
    

    elasticache-replicationgroup-encryption-at-rest

    Severity: high · Enforcement: advisory

    ElastiCache replication groups must have encryption at rest enabled

    • A.5.33 Protection of records — Records shall be protected from loss, destruction, falsification, unauthorized access and unauthorized release.
    Remediation
    Fix: Enable ElastiCache Encryption At Rest

    Set atRestEncryptionEnabled to true on the replication group.

    new aws.elasticache.ReplicationGroup("redis", {
        replicationGroupId: "my-redis",
        atRestEncryptionEnabled: true,
    });
    

    elasticache-replicationgroup-encryption-in-transit

    Severity: high · Enforcement: advisory

    ElastiCache replication groups must have encryption in transit enabled

    • A.5.14 Information transfer — Information transfer rules, procedures, or agreements shall be in place for all types of transfer facilities within the organization and between the organization and other parties.
    Remediation
    Fix: Enable ElastiCache Encryption In Transit

    Set transitEncryptionEnabled to true on the replication group.

    new aws.elasticache.ReplicationGroup("redis", {
        replicationGroupId: "my-redis",
        transitEncryptionEnabled: true,
    });
    

    elasticbeanstalk-managed-updates-enabled

    Severity: medium · Enforcement: advisory

    Elastic Beanstalk environments must have managed platform updates enabled

    • A.8.8 Management of technical vulnerabilities — Information about technical vulnerabilities of information systems in use shall be obtained, the organization’s exposure to such vulnerabilities shall be evaluated and appropriate measures shall be taken.
    Remediation
    Fix: Enable Managed Platform Updates

    Configure managed platform updates for your Elastic Beanstalk environment by adding the required settings:

    import * as aws from "@pulumi/aws";
    
    const environment = new aws.elasticbeanstalk.Environment("my-environment", {
        application: "my-app",
        solutionStackName: "64bit Amazon Linux 2023 v6.0.0 running Node.js 18",
        settings: [
            // Enable managed platform updates
            {
                namespace: "aws:elasticbeanstalk:managedactions",
                name: "ManagedActionsEnabled",
                value: "true",  // Required: Enable automated updates
            },
            {
                namespace: "aws:elasticbeanstalk:managedactions",
                name: "PreferredStartTime",
                value: "sun:02:00",  // Required: Set maintenance window
            },
            // Configure update level
            {
                namespace: "aws:elasticbeanstalk:managedactions:platformupdate",
                name: "UpdateLevel",
                value: "minor",  // Required: Set to "patch", "minor", or "all"
            },
            {
                namespace: "aws:elasticbeanstalk:managedactions:platformupdate",
                name: "InstanceRefreshEnabled",
                value: "true",  // Recommended: Enable for zero-downtime updates
            },
        ],
    });
    

    elasticsearch-cloudwatch-logging-enabled

    Severity: medium · Enforcement: advisory

    Elasticsearch domains must send logs to CloudWatch for audit tracking

    • A.8.15 Logging — Logs that record activities, exceptions, faults and other relevant events shall be produced, stored, protected and analysed.
    Remediation
    Fix: Enable CloudWatch Logging for Elasticsearch Domain

    Configure the logPublishingOptions property to send audit logs to CloudWatch:

    const logGroup = new aws.cloudwatch.LogGroup("es-audit-logs", {
        retentionInDays: 7
    });
    
    const domain = new aws.elasticsearch.Domain("my-domain", {
        // ... other configuration ...
        logPublishingOptions: [
            {
                logType: "AUDIT_LOGS",  // Enable audit logging
                enabled: true,
                cloudwatchLogGroupArn: logGroup.arn,
            },
        ],
    });
    

    elasticsearch-encryption-enabled

    Severity: high · Enforcement: advisory

    Elasticsearch domains must have encryption at rest enabled

    • A.5.33 Protection of records — Records shall be protected from loss, destruction, falsification, unauthorized access and unauthorized release.
    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Enable Encryption at Rest for Elasticsearch Domain

    Enable the encryptAtRest configuration on your Elasticsearch domain to encrypt data stored on disk:

    const domain = new aws.elasticsearch.Domain("my-domain", {
        domainName: "my-elasticsearch-domain",
        encryptAtRest: {
            enabled: true,  // Enable encryption at rest
        },
        // ... other configuration
    });
    

    elasticsearch-https-required

    Severity: high · Enforcement: advisory

    Elasticsearch domains must require HTTPS for client connections

    • A.5.14 Information transfer — Information transfer rules, procedures, or agreements shall be in place for all types of transfer facilities within the organization and between the organization and other parties.
    • A.8.20 Networks security — Networks and network devices shall be secured, managed and controlled to protect information in systems and applications.
    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Enable HTTPS enforcement for Elasticsearch domain

    Configure the domainEndpointOptions property to enforce HTTPS connections:

    import * as aws from "@pulumi/aws";
    
    const domain = new aws.elasticsearch.Domain("my-domain", {
        domainName: "my-elasticsearch-domain",
        domainEndpointOptions: {
            enforceHttps: true, // Enable HTTPS enforcement
            tlsSecurityPolicy: "Policy-Min-TLS-1-2-2019-07", // Optional: Set minimum TLS version
        },
        // ... other configuration
    });
    

    elasticsearch-node-to-node-encryption-enabled

    Severity: high · Enforcement: advisory

    Elasticsearch domains must have node-to-node encryption enabled

    • A.5.14 Information transfer — Information transfer rules, procedures, or agreements shall be in place for all types of transfer facilities within the organization and between the organization and other parties.
    • A.8.20 Networks security — Networks and network devices shall be secured, managed and controlled to protect information in systems and applications.
    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Enable node-to-node encryption for Elasticsearch domain

    Add the nodeToNodeEncryption property to your Elasticsearch domain configuration and set enabled to true:

    const esDomain = new aws.elasticsearch.Domain("my-domain", {
        domainName: "my-elasticsearch-domain",
        elasticsearchVersion: "7.10",
        clusterConfig: {
            instanceType: "r5.large.elasticsearch",
        },
        nodeToNodeEncryption: {
            enabled: true, // Enable encryption for inter-node communication
        },
        // ... other configuration
    });
    

    elasticsearch-vpc-required

    Severity: high · Enforcement: advisory

    Elasticsearch domains must be deployed in VPC for network isolation

    • A.8.20 Networks security — Networks and network devices shall be secured, managed and controlled to protect information in systems and applications.
    • A.8.22 Segregation of networks — Groups of information services, users and information systems shall be segregated in the organization’s networks.
    Remediation
    Fix: Deploy Elasticsearch Domain in VPC

    Add VPC configuration to your Elasticsearch domain to enable network isolation and boundary protection.

    import * as aws from "@pulumi/aws";
    
    const myElasticsearchDomain = new aws.elasticsearch.Domain("my-domain", {
        domainName: "my-domain",
        elasticsearchVersion: "7.10",
        clusterConfig: {
            instanceType: "r5.large.elasticsearch",
            instanceCount: 2,
        },
        // Add VPC configuration for network isolation
        vpcOptions: {
            subnetIds: [subnet1.id, subnet2.id], // Specify subnet IDs from your VPC
            securityGroupIds: [securityGroup.id], // Optional: specify security groups
        },
        ebsOptions: {
            ebsEnabled: true,
            volumeSize: 10,
        },
    });
    

    elb-acm-certificate-required

    Severity: high · Enforcement: advisory

    Ensure ELB Classic Load Balancers use ACM certificates for HTTPS/SSL listeners.

    • A.5.14 Information transfer — Information transfer rules, procedures, or agreements shall be in place for all types of transfer facilities within the organization and between the organization and other parties.
    Remediation
    Fix: Use ACM certificate for ELB HTTPS listener
    // Configure HTTPS listener with ACM certificate
    const elb = new aws.elb.LoadBalancer("elb", {
        listeners: [{
            lbProtocol: "HTTPS",
            lbPort: 443,
            sslCertificateId: certificate.arn,  // This fixes the issue
        }],
    });
    

    elb-cross-zone-load-balancing-enabled

    Severity: low · Enforcement: advisory

    Classic Load Balancers must have cross-zone load balancing enabled

    • A.8.14 Redundancy of information processing facilities — Information processing facilities shall be implemented with redundancy sufficient to meet availability requirements.
    Remediation
    Fix: Enable cross-zone load balancing on Classic Load Balancer

    Set the crossZoneLoadBalancing property to true to distribute traffic evenly across all availability zones.

    const loadBalancer = new aws.elb.LoadBalancer("my-load-balancer", {
        availabilityZones: ["us-west-2a", "us-west-2b"],
        listeners: [{
            instancePort: 80,
            instanceProtocol: "http",
            lbPort: 80,
            lbProtocol: "http",
        }],
        crossZoneLoadBalancing: true, // Enable cross-zone load balancing
    });
    

    elb-deletion-protection

    Severity: medium · Enforcement: advisory

    Load balancers must have deletion protection enabled

    • A.5.29 Information security during disruption — The organization shall plan how to maintain information security at an appropriate level during disruption.
    • A.5.30 ICT readiness for business continuity — ICT readiness shall be planned, implemented, maintained and tested based on business continuity objectives and ICT continuity requirements.
    Remediation
    Fix: Enable deletion protection on the load balancer

    Set the enableDeletionProtection property to true on your load balancer resource:

    const alb = new aws.lb.LoadBalancer("my-alb", {
        loadBalancerType: "application",
        enableDeletionProtection: true, // Enable deletion protection
        subnets: subnetIds,
    });
    

    elb-desync-mitigation

    Severity: medium · Enforcement: advisory

    Classic Load Balancers must use a defensive or strictest desync mitigation mode.

    • A.8.20 Networks security — Networks and network devices shall be secured, managed and controlled to protect information in systems and applications.
    Remediation
    Fix: Set desync mitigation mode

    Set desyncMitigationMode to defensive or strictest on the Classic Load Balancer.

    const elb = new aws.elb.LoadBalancer("elb", {
        availabilityZones: ["us-east-1a", "us-east-1b"],
        desyncMitigationMode: "strictest",
        listeners: [{ instancePort: 80, instanceProtocol: "http", lbPort: 80, lbProtocol: "http" }],
    });
    

    elb-load-balancer-configure-access-logging

    Severity: medium · Enforcement: advisory

    Check that ELB Load Balancers uses access logging.

    • A.8.15 Logging — Logs that record activities, exceptions, faults and other relevant events shall be produced, stored, protected and analysed.
    Remediation
    Fix: Enable Access Logging for ELB Load Balancer

    Configure the accessLogs property with enabled: true and specify an S3 bucket for storing access logs:

    const lb = new aws.elb.LoadBalancer("my-lb", {
        availabilityZones: ["us-west-2a", "us-west-2b"],
        listeners: [{
            instancePort: 80,
            instanceProtocol: "http",
            lbPort: 80,
            lbProtocol: "http",
        }],
        accessLogs: {
            enabled: true, // Enable access logging
            bucket: "my-logs-bucket", // S3 bucket for logs
        },
    });
    

    elb-load-balancer-configure-multi-availability-zone

    Severity: high · Enforcement: advisory

    Check that ELB Load Balancers uses more than one availability zone.

    • A.5.29 Information security during disruption — The organization shall plan how to maintain information security at an appropriate level during disruption.
    • A.8.14 Redundancy of information processing facilities — Information processing facilities shall be implemented with redundancy sufficient to meet availability requirements.
    • A.5.30 ICT readiness for business continuity — ICT readiness shall be planned, implemented, maintained and tested based on business continuity objectives and ICT continuity requirements.
    Remediation
    Fix: Configure Multiple Availability Zones for Load Balancer

    Specify at least two availability zones in the availabilityZones property to ensure high availability:

    const lb = new aws.elb.LoadBalancer("my-lb", {
        availabilityZones: ["us-east-1a", "us-east-1b"], // Configure multiple AZs for resilience
        listeners: [{
            instancePort: 8000,
            instanceProtocol: "http",
            lbPort: 80,
            lbProtocol: "http",
        }],
    });
    

    elb-load-balancer-disallow-unencrypted-traffic

    Severity: critical · Enforcement: advisory

    Check that ELB Load Balancers do not allow unencrypted (HTTP) traffic.

    • A.5.14 Information transfer — Information transfer rules, procedures, or agreements shall be in place for all types of transfer facilities within the organization and between the organization and other parties.
    • A.8.20 Networks security — Networks and network devices shall be secured, managed and controlled to protect information in systems and applications.
    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Use HTTPS Instead of HTTP for Load Balancer Listeners

    Configure all listeners to use HTTPS (port 443) instead of HTTP (port 80) to ensure encrypted traffic:

    const lb = new aws.elb.LoadBalancer("my-lb", {
        availabilityZones: ["us-west-2a", "us-west-2b"],
        listeners: [{
            instancePort: 443,
            instanceProtocol: "https",
            lbPort: 443,
            lbProtocol: "https", // Use HTTPS instead of HTTP
            sslCertificateId: "arn:aws:iam::123456789012:server-certificate/my-cert",
        }],
    });
    

    elb-load-balancer-enable-health-check

    Severity: high · Enforcement: advisory

    Check that ELB Load Balancers have a health check enabled.

    • A.5.29 Information security during disruption — The organization shall plan how to maintain information security at an appropriate level during disruption.
    • A.8.14 Redundancy of information processing facilities — Information processing facilities shall be implemented with redundancy sufficient to meet availability requirements.
    • A.5.30 ICT readiness for business continuity — ICT readiness shall be planned, implemented, maintained and tested based on business continuity objectives and ICT continuity requirements.
    Remediation
    Fix: Configure Health Check for Classic Load Balancer

    Add a healthCheck configuration block to your ELB Load Balancer to enable health monitoring:

    const lb = new aws.elb.LoadBalancer("my-load-balancer", {
        availabilityZones: ["us-west-2a", "us-west-2b"],
        listeners: [{
            instancePort: 80,
            instanceProtocol: "HTTP",
            lbPort: 80,
            lbProtocol: "HTTP",
        }],
        healthCheck: { // Enable health check configuration
            target: "HTTP:80/",
            interval: 30,
            timeout: 5,
            healthyThreshold: 2,
            unhealthyThreshold: 2,
        },
    });
    

    emr-kerberos-enabled

    Severity: high · Enforcement: advisory

    Ensure EMR clusters have Kerberos authentication enabled for enhanced security.

    • A.8.5 Secure authentication — Secure authentication technologies and procedures shall be implemented based on information access restrictions and the topic-specific policy on access control.
    Remediation
    Fix: Enable Kerberos Authentication for EMR Cluster
    const cluster = new aws.emr.Cluster("cluster", {
        kerberosAttributes: {
            realm: "EC2.INTERNAL",  // Kerberos realm
            kdcAdminPassword: kdcPassword.result,  // KDC admin password
        },
        // ... other config
    });
    

    emr-no-default-subnet

    Severity: high · Enforcement: advisory

    EMR clusters must specify explicit subnet configuration to prevent default subnet usage

    • A.5.15 Access control — Rules to control physical and logical access to information and other associated assets shall be established and implemented based on business and information security requirements.
    • A.8.3 Information access restriction — Access to information and other associated assets shall be restricted in accordance with the established topic-specific policy on access control.
    Remediation
    Fix: Specify Explicit Subnet Configuration
    const cluster = new aws.emr.Cluster("my-cluster", {
        name: "my-emr-cluster",
        releaseLabel: "emr-6.10.0",
        ec2Attributes: {
            subnetId: privateSubnet.id,  // Explicitly specify a private subnet
            emrManagedMasterSecurityGroup: masterSg.id,
            emrManagedSlaveSecurityGroup: slaveSg.id,
            instanceProfile: instanceProfile.arn,
        },
        // ... other configuration
    });
    

    emr-no-public-ip

    Severity: high · Enforcement: advisory

    EMR clusters must not be deployed in public subnets that auto-assign public IP addresses

    • A.5.15 Access control — Rules to control physical and logical access to information and other associated assets shall be established and implemented based on business and information security requirements.
    • A.8.3 Information access restriction — Access to information and other associated assets shall be restricted in accordance with the established topic-specific policy on access control.
    Remediation
    Fix: Deploy EMR Cluster in Private Subnet
    const privateSubnet = new aws.ec2.Subnet("private-subnet", {
        vpcId: vpc.id,
        cidrBlock: "10.0.1.0/24",
        mapPublicIpOnLaunch: false,  // Disable auto-assign public IP
        availabilityZone: "us-east-1a",
    });
    
    const emrCluster = new aws.emr.Cluster("my-cluster", {
        releaseLabel: "emr-6.10.0",
        ec2Attributes: {
            subnetId: privateSubnet.id,  // Use private subnet without public IP auto-assignment
            emrManagedMasterSecurityGroup: masterSecurityGroup.id,
            emrManagedSlaveSecurityGroup: slaveSecurityGroup.id,
        },
        // ... other cluster configuration
    });
    

    eventbridge-eventbus-policy-attached

    Severity: medium · Enforcement: advisory

    Ensure custom EventBridge event buses have a resource-based policy attached to control cross-account and cross-service access.

    • A.8.3 Information access restriction — Access to information and other associated assets shall be restricted in accordance with the established topic-specific policy on access control.
    Remediation
    Fix: Attach a Resource Policy to the Event Bus
    const eventBus = new aws.cloudwatch.EventBus("custom-bus", {
        name: "custom-bus",
    });
    
    const eventBusPolicy = new aws.cloudwatch.EventBusPolicy("custom-bus-policy", {
        eventBusName: eventBus.name,
        policy: JSON.stringify({
            Version: "2012-10-17",
            Statement: [{
                Sid: "AllowAccount",
                Effect: "Allow",
                Principal: { AWS: "arn:aws:iam::123456789012:root" },
                Action: "events:PutEvents",
                Resource: eventBus.arn,
            }],
        }),
    });
    

    eventbridge-global-endpoint-replication

    Severity: low · Enforcement: advisory

    EventBridge global endpoints must enable event replication

    • A.8.14 Redundancy of information processing facilities — Information processing facilities shall be implemented with redundancy sufficient to meet availability requirements.
    Remediation
    Fix: Enable Replication on EventBridge Global Endpoint

    Do not disable replication. Leave replicationConfig.state at ENABLED (the default).

    new aws.cloudwatch.EventEndpoint("endpoint", {
        eventBuses: [
            { eventBusArn: primaryBus.arn },
            { eventBusArn: secondaryBus.arn },
        ],
        routingConfig: { failoverConfig: { primary: { healthCheck: hc.arn }, secondary: { route: "us-west-2" } } },
        replicationConfig: { state: "ENABLED" },
    });
    

    eventbridge-schema-registry-policy-attached

    Severity: medium · Enforcement: advisory

    Ensure EventBridge schema registries have a resource-based policy attached to control cross-account and cross-service access.

    • A.8.3 Information access restriction — Access to information and other associated assets shall be restricted in accordance with the established topic-specific policy on access control.
    Remediation
    Fix: Attach a Resource Policy to the Schema Registry
    const registry = new aws.schemas.Registry("custom-registry", {
        name: "custom-registry",
    });
    
    const registryPolicy = new aws.schemas.RegistryPolicy("custom-registry-policy", {
        registryName: registry.name,
        policy: JSON.stringify({
            Version: "2012-10-17",
            Statement: [{
                Sid: "AllowAccount",
                Effect: "Allow",
                Principal: { AWS: "arn:aws:iam::123456789012:root" },
                Action: ["schemas:DescribeRegistry", "schemas:ListSchemas"],
                Resource: registry.arn,
            }],
        }),
    });
    

    guardduty-malware-detection-enabled

    Severity: high · Enforcement: advisory

    Ensures AWS GuardDuty is enabled with malware detection capabilities for threat protection.

    • A.8.7 Protection against malware — Protection against malware shall be implemented and supported by appropriate user awareness.
    • A.8.16 Monitoring activities — Networks, systems and applications shall be monitored for anomalous behaviour and appropriate actions taken to evaluate potential information security incidents.
    Remediation
    Fix: Enable GuardDuty with Malware Detection

    Create a GuardDuty Detector with EBS malware protection and S3 data events enabled:

    import * as aws from "@pulumi/aws";
    
    // Enable GuardDuty detector
    const detector = new aws.guardduty.Detector("guardduty-detector", {
        enable: true, // Ensure detector is enabled
    });
    
    // Enable EBS malware protection for EC2 instances
    new aws.guardduty.DetectorFeature("ebs-malware-protection", {
        detectorId: detector.id,
        name: "EBS_MALWARE_PROTECTION",
        status: "ENABLED", // Enable malware scanning for EBS volumes
    });
    
    // Enable S3 data events protection
    new aws.guardduty.DetectorFeature("s3-protection", {
        detectorId: detector.id,
        name: "S3_DATA_EVENTS",
        status: "ENABLED", // Enable S3 threat detection
    });
    

    iam-group-policy-least-privilege

    Severity: high · Enforcement: advisory

    Ensures IAM group policies follow least privilege principles

    • A.5.15 Access control — Rules to control physical and logical access to information and other associated assets shall be established and implemented based on business and information security requirements.
    • A.8.2 Privileged access rights — The allocation and use of privileged access rights shall be restricted and managed.
    Remediation
    Fix: Replace Wildcard Permissions with Specific Actions and Resources

    Replace wildcard actions and resources with explicit, scoped permissions:

    const groupPolicy = new aws.iam.GroupPolicy("my-group-policy", {
        group: myGroup.name,
        policy: JSON.stringify({
            Version: "2012-10-17",
            Statement: [{
                Effect: "Allow",
                Action: [
                    "cloudwatch:PutMetricData",  // Specify exact actions needed
                ],
                Resource: "*",  // Some AWS services require "*" for resource
                Condition: {
                    StringEquals: {
                        "cloudwatch:namespace": "MyApp",  // Use conditions to scope access
                    },
                },
            }],
        }),
    });
    

    iam-group-policy-restriction

    Severity: medium · Enforcement: advisory

    IAM group policies (inline policy attachments) should not be used

    • A.5.18 Access rights — Access rights to information and other associated assets shall be provisioned, reviewed, modified and removed in accordance with the organization’s topic-specific policy on and rules for access control.
    • A.8.2 Privileged access rights — The allocation and use of privileged access rights shall be restricted and managed.
    Remediation
    Fix: Use GroupPolicyAttachment with Managed Policy
    // Create a managed policy instead of inline policy
    const customPolicy = new aws.iam.Policy("custom-policy", {
        policy: JSON.stringify({
            Version: "2012-10-17",
            Statement: [{
                Effect: "Allow",
                Action: ["s3:ListBucket", "s3:GetBucketLocation"],
                Resource: "arn:aws:s3:::my-shared-bucket",
            }],
        }),
    });
    
    // Don't use aws.iam.GroupPolicy (inline attachment)
    // Instead, use GroupPolicyAttachment with managed policy
    new aws.iam.GroupPolicyAttachment("group-policy-attachment", {
        group: myGroup.name,
        policyArn: customPolicy.arn,  // Attach managed policy for consistent permission management
    });
    

    iam-password-complexity

    Severity: high · Enforcement: advisory

    IAM password policy must require character complexity (lowercase, uppercase, numbers, symbols)

    • A.5.17 Authentication information — Allocation and management of authentication information shall be controlled by a management process, including advising personnel on appropriate handling of authentication information.
    • A.8.5 Secure authentication — Secure authentication technologies and procedures shall be implemented based on information access restrictions and the topic-specific policy on access control.
    Remediation
    Fix: Enable all character complexity requirements in IAM password policy

    Update your IAM account password policy to require all character types:

    new aws.iam.AccountPasswordPolicy("account-password-policy", {
        requireLowercaseCharacters: true,  // Require lowercase letters
        requireUppercaseCharacters: true,  // Require uppercase letters
        requireNumbers: true,              // Require numbers
        requireSymbols: true,              // Require symbols
        minimumPasswordLength: 14,
    });
    

    iam-password-expiration

    Severity: high · Enforcement: advisory

    IAM password policy must expire passwords

    • A.5.17 Authentication information — Allocation and management of authentication information shall be controlled by a management process, including advising personnel on appropriate handling of authentication information.
    • A.8.5 Secure authentication — Secure authentication technologies and procedures shall be implemented based on information access restrictions and the topic-specific policy on access control.
    Remediation
    Fix: Configure Password Expiration in IAM Password Policy

    Set the maxPasswordAge property to enforce password expiration. Passwords should expire within 30-365 days based on your organization’s security requirements.

    import * as aws from "@pulumi/aws";
    
    const accountPasswordPolicy = new aws.iam.AccountPasswordPolicy("policy", {
        maxPasswordAge: 90,  // Passwords must be changed every 90 days
        minimumPasswordLength: 14,
        requireNumbers: true,
        requireSymbols: true,
        requireLowercaseCharacters: true,
        requireUppercaseCharacters: true,
    });
    

    iam-password-policy-minimum-password-length

    Severity: high · Enforcement: advisory

    Ensure IAM password policy requires minimum length of 14 or greater.

    • A.5.17 Authentication information — Allocation and management of authentication information shall be controlled by a management process, including advising personnel on appropriate handling of authentication information.
    • A.8.5 Secure authentication — Secure authentication technologies and procedures shall be implemented based on information access restrictions and the topic-specific policy on access control.
    Remediation
    Fix: Set Minimum Password Length to 14 Characters

    Set the minimumPasswordLength to 14 or greater for the IAM Account Password Policy:

    const passwordPolicy = new aws.iam.AccountPasswordPolicy("account-password-policy", {
        minimumPasswordLength: 14, // Set minimum length to at least 14 characters
    });
    

    iam-password-policy-prevent-reuse

    Severity: high · Enforcement: advisory

    Ensure IAM password policy prevents password reuse.

    • A.5.17 Authentication information — Allocation and management of authentication information shall be controlled by a management process, including advising personnel on appropriate handling of authentication information.
    • A.8.5 Secure authentication — Secure authentication technologies and procedures shall be implemented based on information access restrictions and the topic-specific policy on access control.
    Remediation
    Fix: Configure Password Reuse Prevention

    Set the passwordReusePrevention property to 24 to prevent users from reusing their previous 24 passwords:

    const accountPasswordPolicy = new aws.iam.AccountPasswordPolicy("password-policy", {
        minimumPasswordLength: 14,
        requireNumbers: true,
        requireSymbols: true,
        requireUppercaseCharacters: true,
        requireLowercaseCharacters: true,
        passwordReusePrevention: 24, // Prevent reuse of previous 24 passwords
    });
    

    iam-policy-least-privilege

    Severity: high · Enforcement: advisory

    Ensures IAM policies follow least privilege principles

    • A.5.15 Access control — Rules to control physical and logical access to information and other associated assets shall be established and implemented based on business and information security requirements.
    • A.8.2 Privileged access rights — The allocation and use of privileged access rights shall be restricted and managed.
    Remediation
    Fix: Replace Wildcard Permissions with Specific Actions and Resources

    Replace wildcard actions and resources with explicit, scoped permissions that grant only the minimum required access:

    const policy = new aws.iam.Policy("my-policy", {
        policy: JSON.stringify({
            Version: "2012-10-17",
            Statement: [{
                Effect: "Allow",
                Action: [
                    "s3:GetObject",        // Specify exact actions needed
                    "s3:PutObject",
                ],
                Resource: [
                    "arn:aws:s3:::my-bucket/*",  // Scope to specific resources
                ],
            }],
        }),
    });
    

    iam-policy-mfa-enforcement

    Severity: high · Enforcement: advisory

    IAM policies must require MFA for privileged actions

    • A.5.16 Identity management — The full life cycle of identities shall be managed.
    • A.8.5 Secure authentication — Secure authentication technologies and procedures shall be implemented based on information access restrictions and the topic-specific policy on access control.
    Remediation
    Fix: Add MFA condition to privileged IAM policy statements

    Add a Condition block to policy statements that allow privileged actions:

    new aws.iam.Policy("admin-policy", {
        policy: JSON.stringify({
            Version: "2012-10-17",
            Statement: [{
                Effect: "Allow",
                Action: [
                    "iam:*",
                    "organizations:*",
                    "s3:DeleteBucket",
                    "rds:DeleteDBInstance"
                ],
                Resource: "*",
                Condition: {
                    Bool: {
                        // Require MFA for privileged operations
                        "aws:MultiFactorAuthPresent": "true"
                    }
                }
            }]
        })
    });
    

    iam-role-assume-role-mfa-enforcement

    Severity: high · Enforcement: advisory

    Ensures IAM roles require MFA when assumed by human users (not AWS services)

    • A.5.16 Identity management — The full life cycle of identities shall be managed.
    • A.8.5 Secure authentication — Secure authentication technologies and procedures shall be implemented based on information access restrictions and the topic-specific policy on access control.
    Remediation
    Fix: Add MFA Condition to Role Trust Policy

    Add the aws:MultiFactorAuthPresent condition to any assume role statement that allows human principals to assume the role:

    const adminRole = new aws.iam.Role("admin-role", {
        assumeRolePolicy: JSON.stringify({
            Version: "2012-10-17",
            Statement: [{
                Effect: "Allow",
                Principal: {
                    AWS: "arn:aws:iam::123456789012:root" // Root account (human)
                },
                Action: "sts:AssumeRole",
                Condition: {
                    Bool: {
                        "aws:MultiFactorAuthPresent": "true" // Require MFA
                    }
                }
            }],
        }),
    });
    
    const userAssumeRole = new aws.iam.Role("user-role", {
        assumeRolePolicy: JSON.stringify({
            Version: "2012-10-17",
            Statement: [{
                Effect: "Allow",
                Principal: {
                    AWS: "arn:aws:iam::123456789012:user/john.doe" // IAM user (human)
                },
                Action: "sts:AssumeRole",
                Condition: {
                    Bool: {
                        "aws:MultiFactorAuthPresent": "true" // Require MFA
                    }
                }
            }],
        }),
    });
    
    // Service roles are automatically exempt (no MFA condition needed)
    const ecsTaskRole = new aws.iam.Role("ecs-task-role", {
        assumeRolePolicy: JSON.stringify({
            Version: "2012-10-17",
            Statement: [{
                Effect: "Allow",
                Principal: {
                    Service: "ecs-tasks.amazonaws.com" // Service principal - no MFA needed
                },
                Action: "sts:AssumeRole"
            }],
        }),
    });
    
    // Role principals are never flagged (could be cross-account service roles)
    const crossAccountRole = new aws.iam.Role("cross-account-role", {
        assumeRolePolicy: JSON.stringify({
            Version: "2012-10-17",
            Statement: [{
                Effect: "Allow",
                Principal: {
                    AWS: "arn:aws:iam::111111111111:role/service-role" // Role principal - not checked
                },
                Action: "sts:AssumeRole"
            }],
        }),
    });
    

    iam-role-inline-policy-restriction

    Severity: medium · Enforcement: advisory

    IAM roles must not have inline policies

    • A.5.18 Access rights — Access rights to information and other associated assets shall be provisioned, reviewed, modified and removed in accordance with the organization’s topic-specific policy on and rules for access control.
    • A.8.2 Privileged access rights — The allocation and use of privileged access rights shall be restricted and managed.
    Remediation
    Fix: Replace Inline Policies with Managed Policies
    // Create a managed policy
    const customPolicy = new aws.iam.Policy("custom-policy", {
        policy: JSON.stringify({
            Version: "2012-10-17",
            Statement: [{
                Effect: "Allow",
                Action: ["s3:GetObject", "s3:PutObject"],
                Resource: "arn:aws:s3:::my-bucket/*",
            }],
        }),
    });
    
    // Create the role without inline policies
    const role = new aws.iam.Role("app-role", {
        assumeRolePolicy: JSON.stringify({
            Version: "2012-10-17",
            Statement: [{
                Effect: "Allow",
                Principal: { Service: "ec2.amazonaws.com" },
                Action: "sts:AssumeRole",
            }],
        }),
        // Remove inlinePolicies property entirely
    });
    
    // Attach the managed policy instead
    new aws.iam.RolePolicyAttachment("role-policy-attachment", {
        role: role.name,
        policyArn: customPolicy.arn,  // Use managed policy for better governance
    });
    

    iam-role-least-privilege

    Severity: high · Enforcement: advisory

    Ensures IAM roles follow least privilege principles

    • A.5.15 Access control — Rules to control physical and logical access to information and other associated assets shall be established and implemented based on business and information security requirements.
    • A.8.2 Privileged access rights — The allocation and use of privileged access rights shall be restricted and managed.
    Remediation
    Fix: Replace Wildcard Permissions with Specific Actions and Resources

    Replace wildcard actions and resources in inline policies with explicit, scoped permissions:

    const role = new aws.iam.Role("my-role", {
        assumeRolePolicy: assumePolicyDoc,
        inlinePolicies: [{
            name: "my-inline-policy",
            policy: JSON.stringify({
                Version: "2012-10-17",
                Statement: [{
                    Effect: "Allow",
                    Action: [
                        "dynamodb:GetItem",    // Specify exact actions needed
                        "dynamodb:PutItem",
                    ],
                    Resource: [
                        "arn:aws:dynamodb:us-east-1:123456789012:table/MyTable",  // Scope to specific resources
                    ],
                }],
            }),
        }],
    });
    

    iam-role-mfa-enforcement

    Severity: high · Enforcement: advisory

    IAM roles must require MFA for privileged actions

    • A.5.16 Identity management — The full life cycle of identities shall be managed.
    • A.8.5 Secure authentication — Secure authentication technologies and procedures shall be implemented based on information access restrictions and the topic-specific policy on access control.
    Remediation
    Fix: Add MFA condition to privileged IAM role inline policies

    Add a Condition block to policy statements that allow privileged actions:

    new aws.iam.Role("admin-role", {
        assumeRolePolicy: JSON.stringify({
            Version: "2012-10-17",
            Statement: [{
                Effect: "Allow",
                Principal: { AWS: "arn:aws:iam::123456789012:root" },
                Action: "sts:AssumeRole"
            }]
        }),
        inlinePolicies: [{
            name: "admin-policy",
            policy: JSON.stringify({
                Version: "2012-10-17",
                Statement: [{
                    Effect: "Allow",
                    Action: ["iam:*", "organizations:*"],
                    Resource: "*",
                    Condition: {
                        Bool: {
                            // Require MFA for privileged operations
                            "aws:MultiFactorAuthPresent": "true"
                        }
                    }
                }]
            })
        }]
    });
    

    iam-role-policy-least-privilege

    Severity: high · Enforcement: advisory

    Ensures IAM role policies follow least privilege principles

    • A.5.15 Access control — Rules to control physical and logical access to information and other associated assets shall be established and implemented based on business and information security requirements.
    • A.8.2 Privileged access rights — The allocation and use of privileged access rights shall be restricted and managed.
    Remediation
    Fix: Replace Wildcard Permissions with Specific Actions and Resources

    Replace wildcard actions and resources with explicit, scoped permissions:

    const rolePolicy = new aws.iam.RolePolicy("my-role-policy", {
        role: myRole.id,
        policy: JSON.stringify({
            Version: "2012-10-17",
            Statement: [{
                Effect: "Allow",
                Action: [
                    "ec2:DescribeInstances",   // Specify exact actions needed
                    "ec2:StartInstances",
                    "ec2:StopInstances",
                ],
                Resource: [
                    "arn:aws:ec2:us-east-1:123456789012:instance/*",  // Scope to specific resources
                ],
            }],
        }),
    });
    

    iam-role-policy-mfa-enforcement

    Severity: high · Enforcement: advisory

    IAM role policies must require MFA for privileged actions

    • A.5.16 Identity management — The full life cycle of identities shall be managed.
    • A.8.5 Secure authentication — Secure authentication technologies and procedures shall be implemented based on information access restrictions and the topic-specific policy on access control.
    Remediation
    Fix: Add MFA condition to privileged IAM role policy statements

    Add a Condition block to policy statements that allow privileged actions:

    new aws.iam.RolePolicy("admin-role-policy", {
        role: adminRole.id,
        policy: JSON.stringify({
            Version: "2012-10-17",
            Statement: [{
                Effect: "Allow",
                Action: ["iam:CreateUser", "iam:DeleteUser", "iam:*"],
                Resource: "*",
                Condition: {
                    Bool: {
                        // Require MFA for privileged operations
                        "aws:MultiFactorAuthPresent": "true"
                    }
                }
            }]
        })
    });
    

    iam-role-policy-restriction

    Severity: medium · Enforcement: advisory

    IAM role policies (inline policy attachments) should not be used

    • A.5.18 Access rights — Access rights to information and other associated assets shall be provisioned, reviewed, modified and removed in accordance with the organization’s topic-specific policy on and rules for access control.
    • A.8.2 Privileged access rights — The allocation and use of privileged access rights shall be restricted and managed.
    Remediation
    Fix: Use RolePolicyAttachment with Managed Policy
    // Create a managed policy instead of inline policy
    const customPolicy = new aws.iam.Policy("custom-policy", {
        policy: JSON.stringify({
            Version: "2012-10-17",
            Statement: [{
                Effect: "Allow",
                Action: ["dynamodb:GetItem", "dynamodb:PutItem"],
                Resource: "arn:aws:dynamodb:*:*:table/MyTable",
            }],
        }),
    });
    
    // Don't use aws.iam.RolePolicy (inline attachment)
    // Instead, use RolePolicyAttachment with managed policy
    new aws.iam.RolePolicyAttachment("role-policy-attachment", {
        role: myRole.name,
        policyArn: customPolicy.arn,  // Attach managed policy for centralized governance
    });
    

    iam-role-session-duration

    Severity: medium · Enforcement: advisory

    Enforces maximum session duration for IAM roles

    • A.8.2 Privileged access rights — The allocation and use of privileged access rights shall be restricted and managed.
    Remediation
    Fix: Set Appropriate Maximum Session Duration for IAM Role

    Configure the maxSessionDuration property based on the role type to limit credential exposure window:

    const appRole = new aws.iam.Role("app-role", {
        assumeRolePolicy: JSON.stringify({
            Version: "2012-10-17",
            Statement: [{
                Effect: "Allow",
                Principal: { Service: "ec2.amazonaws.com" },
                Action: "sts:AssumeRole",
            }],
        }),
        maxSessionDuration: 3600, // 1 hour for general roles (default)
    });
    
    const adminRole = new aws.iam.Role("admin-role", {
        name: "AdminRole",
        assumeRolePolicy: JSON.stringify({
            Version: "2012-10-17",
            Statement: [{
                Effect: "Allow",
                Principal: { AWS: "arn:aws:iam::123456789012:root" },
                Action: "sts:AssumeRole",
            }],
        }),
        maxSessionDuration: 7200, // 2 hours for administrative roles
    });
    

    iam-user-group-membership-required

    Severity: medium · Enforcement: advisory

    IAM users must be members of groups for proper access management

    • A.5.16 Identity management — The full life cycle of identities shall be managed.
    • A.5.18 Access rights — Access rights to information and other associated assets shall be provisioned, reviewed, modified and removed in accordance with the organization’s topic-specific policy on and rules for access control.
    Remediation
    Fix: Add User to IAM Group
    const user = new aws.iam.User("developer", {
        name: "developer-user",
    });
    
    const group = new aws.iam.Group("developers", {
        name: "developers",
    });
    
    // Add user to group to satisfy group membership requirement
    new aws.iam.UserGroupMembership("developer-membership", {
        user: user.name,
        groups: [group.name],  // Assign user to appropriate groups
    });
    

    iam-user-mfa-console-access

    Severity: high · Enforcement: advisory

    Ensures IAM users with console access have MFA devices

    • A.5.16 Identity management — The full life cycle of identities shall be managed.
    • A.8.5 Secure authentication — Secure authentication technologies and procedures shall be implemented based on information access restrictions and the topic-specific policy on access control.
    Remediation
    Fix: Enable MFA for IAM User Console Access

    Create a Virtual MFA Device for each IAM user with console access:

    const user = new aws.iam.User("example-user", {
        name: "example-user",
    });
    
    const loginProfile = new aws.iam.UserLoginProfile("example-login", {
        user: user.name,
    });
    
    // Create Virtual MFA Device for the user
    const mfaDevice = new aws.iam.VirtualMfaDevice("example-user-mfa", {
        virtualMfaDeviceName: "example-user-mfa", // Name must match pattern: <username>-mfa or <username>-mfa-device
        userName: user.name, // Associate MFA device with the user
    });
    

    iam-user-no-policies-check

    Severity: high · Enforcement: advisory

    Ensure IAM users follow best practices by using groups and roles instead of direct policy attachments.

    • A.5.18 Access rights — Access rights to information and other associated assets shall be provisioned, reviewed, modified and removed in accordance with the organization’s topic-specific policy on and rules for access control.
    Remediation
    Fix: Use GroupMembership Instead of Direct Attachment
    const group = new aws.iam.Group("developers-group", {
        name: "Developers",
        // ... other required config
    });
    
    const groupPolicyAttachment = new aws.iam.GroupPolicyAttachment("group-policy", {
        group: group.name,
        policyArn: "arn:aws:iam::aws:policy/ReadOnlyAccess",
    });
    
    const user = new aws.iam.User("my-user", {
        name: "john.doe",
        // ... other required config
    });
    
    const groupMembership = new aws.iam.GroupMembership("group-members", {
        group: group.name,
        users: [user.name],  // Add users to group instead of direct policy attachment
    });
    

    iam-user-policy-least-privilege

    Severity: high · Enforcement: advisory

    Ensures IAM user policies follow least privilege principles

    • A.5.15 Access control — Rules to control physical and logical access to information and other associated assets shall be established and implemented based on business and information security requirements.
    • A.8.2 Privileged access rights — The allocation and use of privileged access rights shall be restricted and managed.
    Remediation
    Fix: Replace Wildcard Permissions with Specific Actions and Resources

    Replace wildcard actions and resources with explicit, scoped permissions:

    const userPolicy = new aws.iam.UserPolicy("my-user-policy", {
        user: myUser.name,
        policy: JSON.stringify({
            Version: "2012-10-17",
            Statement: [{
                Effect: "Allow",
                Action: [
                    "s3:ListBucket",         // Specify exact actions needed
                ],
                Resource: [
                    "arn:aws:s3:::my-bucket",  // Scope to specific resources
                ],
            }],
        }),
    });
    

    internet-gateway-authorized-vpc

    Severity: medium · Enforcement: advisory

    Internet gateways must only attach to authorized VPCs

    • A.8.20 Networks security — Networks and network devices shall be secured, managed and controlled to protect information in systems and applications.
    Remediation
    Fix: Attach Internet Gateway Only to Authorized VPCs

    Attach the internet gateway only to a VPC included in authorizedVpcIds.

    new aws.ec2.InternetGateway("igw", {
        vpcId: authorizedVpc.id, // must be in authorizedVpcIds
    });
    

    kinesis-stream-encryption

    Severity: high · Enforcement: advisory

    Kinesis streams must have KMS server-side encryption enabled

    • A.5.33 Protection of records — Records shall be protected from loss, destruction, falsification, unauthorized access and unauthorized release.
    Remediation
    Fix: Enable Kinesis Stream KMS Encryption

    Set encryptionType to "KMS" and provide a kmsKeyId.

    new aws.kinesis.Stream("stream", {
        name: "my-stream",
        shardCount: 1,
        encryptionType: "KMS",
        kmsKeyId: "alias/aws/kinesis",
    });
    

    kms-grant-access-control

    Severity: medium · Enforcement: advisory

    Validates KMS grants for least privilege access control

    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Configure KMS Grant with Least Privilege Access Control

    Specify explicit operations for the grant, add constraints for sensitive operations, and define a specific grantee principal:

    const grant = new aws.kms.Grant("my-kms-grant", {
        keyId: kmsKey.id,
        granteePrincipal: roleArn, // Specify a specific grantee principal
        operations: ["Encrypt", "Decrypt"], // Define specific operations
        constraints: {
            encryptionContextSubset: {
                "Department": "Finance", // Add constraints for sensitive operations
            },
        },
    });
    

    kms-key-creation

    Severity: medium · Enforcement: advisory

    Validates KMS key creation with appropriate specifications and origins

    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Configure KMS Key with Proper Specifications

    Add a description, configure an appropriate deletion window (7-30 days), and ensure key specifications match your security requirements:

    const key = new aws.kms.Key("my-key", {
        description: "Key for encrypting application data", // Add clear description
        customerMasterKeySpec: "SYMMETRIC_DEFAULT", // Use approved key spec
        keyUsage: "ENCRYPT_DECRYPT", // Specify key usage
        deletionWindowInDays: 30, // Set deletion window between 7-30 days
        enableKeyRotation: true,
    });
    

    kms-key-enable-key-rotation

    Severity: medium · Enforcement: advisory

    Checks that KMS Keys have key rotation enabled.

    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Enable Automatic Key Rotation for KMS Keys

    Set the enableKeyRotation property to true for all KMS keys to ensure cryptographic keys are automatically rotated annually:

    const key = new kms.Key("my-key", {
        description: "KMS key with automatic rotation",
        enableKeyRotation: true, // Enable automatic annual key rotation
    });
    

    kms-key-policy-access-control

    Severity: medium · Enforcement: advisory

    Validates KMS key policies for least privilege and separation of duties

    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Configure KMS Key Policy with Least Privilege Access Control

    Define an explicit key policy with specific principals and actions, avoiding wildcards:

    const keyPolicy = {
        Version: "2012-10-17",
        Statement: [
            {
                Sid: "Enable IAM User Permissions",
                Effect: "Allow",
                Principal: {
                    AWS: `arn:aws:iam::${accountId}:root`, // Specific account root
                },
                Action: "kms:*",
                Resource: "*",
            },
            {
                Sid: "Allow Key Administrators",
                Effect: "Allow",
                Principal: {
                    AWS: `arn:aws:iam::${accountId}:role/KeyAdminRole`, // Specific role ARN
                },
                Action: [
                    "kms:Create*",
                    "kms:Describe*",
                    "kms:Enable*",
                    "kms:List*",
                    "kms:Put*",
                    "kms:Update*",
                    "kms:Revoke*",
                    "kms:Disable*",
                    "kms:Get*",
                    "kms:Delete*",
                    "kms:ScheduleKeyDeletion",
                    "kms:CancelKeyDeletion", // Specific administrative actions only
                ],
                Resource: "*",
            },
            {
                Sid: "Allow Key Usage",
                Effect: "Allow",
                Principal: {
                    AWS: `arn:aws:iam::${accountId}:role/KeyUserRole`, // Specific user role ARN
                },
                Action: [
                    "kms:Decrypt",
                    "kms:EncryptionContext*",
                    "kms:GenerateDataKey", // Specific usage actions only
                ],
                Resource: "*",
            },
        ],
    };
    
    const key = new aws.kms.Key("my-key", {
        description: "My KMS key with least privilege policy",
        policy: JSON.stringify(keyPolicy), // Apply the policy with specific principals and actions
    });
    

    lambda-environment-variables-encryption

    Severity: high · Enforcement: advisory

    Ensures that all Lambda functions have their environment variables encrypted using AWS KMS

    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Encrypt Lambda Environment Variables with KMS

    Configure a KMS key for Lambda function environment variable encryption by setting the kmsKeyArn property:

    const kmsKey = new aws.kms.Key("lambda-env-key", {
        description: "KMS key for Lambda environment variable encryption",
    });
    
    const lambdaFunction = new aws.lambda.Function("my-function", {
        runtime: "nodejs18.x",
        handler: "index.handler",
        role: role.arn,
        code: new pulumi.asset.AssetArchive({
            ".": new pulumi.asset.FileArchive("./function"),
        }),
        environment: {
            variables: {
                DATABASE_URL: "postgres://example.com/db",
            },
        },
        kmsKeyArn: kmsKey.arn, // Encrypt environment variables with KMS
    });
    

    lambda-function-logging

    Severity: medium · Enforcement: advisory

    Ensures that all AWS Lambda functions have logging enabled to track output data processing

    • A.8.15 Logging — Logs that record activities, exceptions, faults and other relevant events shall be produced, stored, protected and analysed.
    Remediation
    Fix: Enable Lambda Function Logging Configuration

    Add the loggingConfig property to your Lambda function with an appropriate applicationLogLevel (DEBUG, INFO, or WARN):

    const myFunction = new aws.lambda.Function("my-function", {
        runtime: "nodejs18.x",
        handler: "index.handler",
        role: lambdaRole.arn,
        code: new pulumi.asset.AssetArchive({
            ".": new pulumi.asset.FileArchive("./app"),
        }),
        loggingConfig: {
            logFormat: "JSON",
            applicationLogLevel: "INFO", // Set log level to INFO or DEBUG for adequate logging
        },
    });
    

    lambda-permission-configure-source-arn

    Severity: critical · Enforcement: advisory

    Checks that lambda function permissions have a source arn specified.

    • A.5.15 Access control — Rules to control physical and logical access to information and other associated assets shall be established and implemented based on business and information security requirements.
    • A.8.3 Information access restriction — Access to information and other associated assets shall be restricted in accordance with the established topic-specific policy on access control.
    Remediation
    Fix: Configure Source ARN for Lambda Permission

    Add the sourceArn property to restrict which AWS service or resource can invoke the Lambda function:

    const lambdaPermission = new aws.lambda.Permission("my-permission", {
        action: "lambda:InvokeFunction",
        function: myFunction.name,
        principal: "apigateway.amazonaws.com",
        sourceArn: apiGateway.executionArn, // Specify the source ARN to restrict invocation
    });
    

    lambda-public-access-restricted

    Severity: critical · Enforcement: advisory

    Lambda functions must restrict public access through resource-based policies

    • A.8.3 Information access restriction — Access to information and other associated assets shall be restricted in accordance with the established topic-specific policy on access control.
    Remediation
    Fix: Restrict Lambda Function Access to Specific Principals
    const lambdaFunction = new aws.lambda.Function("myFunction", {
        runtime: "nodejs18.x",
        handler: "index.handler",
        role: role.arn,
        code: new pulumi.asset.AssetArchive({
            ".": new pulumi.asset.FileArchive("./lambda"),
        }),
    });
    
    // Grant access to specific AWS service instead of wildcard
    new aws.lambda.Permission("apiGatewayInvoke", {
        action: "lambda:InvokeFunction",
        function: lambdaFunction.name,
        principal: "apigateway.amazonaws.com",  // Specify AWS service instead of "*"
        sourceArn: apiGateway.executionArn,
    });
    
    // Or grant access to specific AWS account
    new aws.lambda.Permission("crossAccountInvoke", {
        action: "lambda:InvokeFunction",
        function: lambdaFunction.name,
        principal: "123456789012",  // Specify AWS account ID instead of "*"
    });
    

    lambda-runtime-restrictions

    Severity: medium · Enforcement: advisory

    Ensures that AWS Lambda functions are created only with approved runtime versions

    • A.8.8 Management of technical vulnerabilities — Information about technical vulnerabilities of information systems in use shall be obtained, the organization’s exposure to such vulnerabilities shall be evaluated and appropriate measures shall be taken.
    Remediation
    Fix: Use Approved Lambda Runtime

    Set the runtime property to an approved runtime version from the organization’s approved list:

    const myFunction = new aws.lambda.Function("my-function", {
        runtime: "nodejs20.x", // Use an approved runtime version
        handler: "index.handler",
        role: role.arn,
        code: new pulumi.asset.AssetArchive({
            ".": new pulumi.asset.FileArchive("./function"),
        }),
    });
    

    lambda-vpc-placement-required

    Severity: medium · Enforcement: advisory

    Lambda functions must be deployed in VPC for network isolation and security

    • A.8.20 Networks security — Networks and network devices shall be secured, managed and controlled to protect information in systems and applications.
    • A.8.22 Segregation of networks — Groups of information services, users and information systems shall be segregated in the organization’s networks.
    Remediation
    Fix: Configure Lambda Function VPC Placement

    Add a vpcConfig to your Lambda function with subnet and security group configurations:

    import * as aws from "@pulumi/aws";
    
    const myFunction = new aws.lambda.Function("myFunction", {
        runtime: "nodejs18.x",
        handler: "index.handler",
        role: lambdaRole.arn,
        code: new pulumi.asset.AssetArchive({
            ".": new pulumi.asset.FileArchive("./function"),
        }),
        // Add VPC configuration for network isolation
        vpcConfig: {
            subnetIds: [
                privateSubnet1.id,  // Use at least 2 subnets for high availability
                privateSubnet2.id,
            ],
            securityGroupIds: [lambdaSecurityGroup.id],  // Specify security groups for access control
        },
    });
    

    lb-access-logging

    Severity: medium · Enforcement: advisory

    ELBv2 load balancers must have access logging enabled.

    • A.8.15 Logging — Logs that record activities, exceptions, faults and other relevant events shall be produced, stored, protected and analysed.
    Remediation
    Fix: Enable access logging

    Configure accessLogs with enabled: true and an S3 bucket.

    const lb = new aws.lb.LoadBalancer("lb", {
        loadBalancerType: "application",
        subnets: [subnetAzA.id, subnetAzB.id],
        accessLogs: {
            enabled: true,
            bucket: logsBucket.bucket,
        },
    });
    

    lb-cross-zone-load-balancing

    Severity: medium · Enforcement: advisory

    Network Load Balancers must enable cross-zone load balancing.

    • A.8.14 Redundancy of information processing facilities — Information processing facilities shall be implemented with redundancy sufficient to meet availability requirements.
    Remediation
    Fix: Enable cross-zone load balancing

    Set enableCrossZoneLoadBalancing to true on the Network Load Balancer.

    const nlb = new aws.lb.LoadBalancer("nlb", {
        loadBalancerType: "network",
        subnets: [subnetAzA.id, subnetAzB.id],
        enableCrossZoneLoadBalancing: true,
    });
    

    lb-multi-az

    Severity: medium · Enforcement: advisory

    ELBv2 load balancers must span at least two Availability Zones.

    • A.8.14 Redundancy of information processing facilities — Information processing facilities shall be implemented with redundancy sufficient to meet availability requirements.
    Remediation
    Fix: Span multiple Availability Zones

    Attach the load balancer to subnets in at least two distinct Availability Zones.

    const lb = new aws.lb.LoadBalancer("lb", {
        loadBalancerType: "application",
        subnets: [subnetAzA.id, subnetAzB.id],
    });
    

    load-balancer-waf-association

    Severity: critical · Enforcement: advisory

    Ensures public-facing Load Balancers have WAF associations

    • A.8.20 Networks security — Networks and network devices shall be secured, managed and controlled to protect information in systems and applications.
    Remediation
    Fix: Associate WAF Web ACL with Load Balancer

    Create a WAF Web ACL association to protect your public-facing Load Balancer:

    // Create a WAF Web ACL association for the Load Balancer
    const wafAssociation = new aws.wafv2.WebAclAssociation("lb-waf-association", {
        resourceArn: loadBalancer.arn, // Reference the Load Balancer ARN
        webAclArn: webAcl.arn, // Reference the WAF Web ACL ARN
    });
    

    mq-broker-audit-logging

    Severity: medium · Enforcement: advisory

    Amazon MQ brokers must enable audit logging to record user management actions.

    • A.8.15 Logging — Logs that record activities, exceptions, faults and other relevant events shall be produced, stored, protected and analysed.
    Remediation
    Fix: Enable Audit Logging on the Amazon MQ Broker

    Set logs.audit to true to record user management actions.

    const broker = new aws.mq.Broker("my-broker", {
        logs: {
            audit: true,
        },
        // ... other configuration
    });
    

    msk-cluster-encryption-in-transit

    Severity: high · Enforcement: advisory

    MSK clusters must have in-cluster encryption in transit enabled

    • A.5.14 Information transfer — Information transfer rules, procedures, or agreements shall be in place for all types of transfer facilities within the organization and between the organization and other parties.
    Remediation
    Fix: Enable MSK In-Cluster Encryption In Transit

    Ensure encryptionInfo.encryptionInTransit.inCluster is not set to false (it defaults to true).

    new aws.msk.Cluster("cluster", {
        clusterName: "my-cluster",
        kafkaVersion: "3.5.1",
        numberOfBrokerNodes: 3,
        encryptionInfo: {
            encryptionInTransit: {
                inCluster: true,
                clientBroker: "TLS",
            },
        },
    });
    

    neptune-cluster-backup-retention

    Severity: medium · Enforcement: advisory

    Neptune clusters must retain automated backups for at least the configured minimum number of days.

    • A.8.13 Information backup — Backup copies of information, software and systems shall be maintained and regularly tested in accordance with the agreed topic-specific policy on backup.
    Remediation
    Fix: Set Neptune Cluster Backup Retention

    Set backupRetentionPeriod to at least the required number of days.

    const cluster = new aws.neptune.Cluster("cluster", {
        clusterIdentifier: "my-neptune-cluster",
        backupRetentionPeriod: 7,
    });
    

    neptune-cluster-encryption-at-rest

    Severity: high · Enforcement: advisory

    Neptune clusters must have storage encryption at rest enabled.

    • A.5.33 Protection of records — Records shall be protected from loss, destruction, falsification, unauthorized access and unauthorized release.
    Remediation
    Fix: Enable Neptune Cluster Encryption At Rest

    Set storageEncrypted to true when creating the cluster. Encryption at rest cannot be enabled on an existing unencrypted cluster.

    const cluster = new aws.neptune.Cluster("cluster", {
        clusterIdentifier: "my-neptune-cluster",
        storageEncrypted: true,
    });
    

    neptune-cluster-iam-authentication

    Severity: high · Enforcement: advisory

    Neptune clusters must have IAM database authentication enabled.

    • A.8.5 Secure authentication — Secure authentication technologies and procedures shall be implemented based on information access restrictions and the topic-specific policy on access control.
    Remediation
    Fix: Enable Neptune Cluster IAM Database Authentication

    Set iamDatabaseAuthenticationEnabled to true.

    const cluster = new aws.neptune.Cluster("cluster", {
        clusterIdentifier: "my-neptune-cluster",
        iamDatabaseAuthenticationEnabled: true,
    });
    

    neptune-clusterinstance-managed-service-patching

    Severity: medium · Enforcement: advisory

    Ensures Neptune cluster instances have automated minor version upgrades enabled

    • A.8.8 Management of technical vulnerabilities — Information about technical vulnerabilities of information systems in use shall be obtained, the organization’s exposure to such vulnerabilities shall be evaluated and appropriate measures shall be taken.
    Remediation
    Fix: Enable Automatic Minor Version Upgrades for Neptune Cluster Instance

    Set the autoMinorVersionUpgrade property to true to enable automated patching for managed service security updates:

    const neptuneInstance = new aws.neptune.ClusterInstance("my-neptune-instance", {
        clusterIdentifier: neptuneCluster.id,
        instanceClass: "db.r5.large",
        engine: "neptune",
        autoMinorVersionUpgrade: true, // Enable automatic minor version upgrades
    });
    

    neptune-clusterinstance-no-public-access

    Severity: critical · Enforcement: advisory

    Checks that Neptune Cluster Instances public access is not enabled.

    • A.5.15 Access control — Rules to control physical and logical access to information and other associated assets shall be established and implemented based on business and information security requirements.
    • A.8.3 Information access restriction — Access to information and other associated assets shall be restricted in accordance with the established topic-specific policy on access control.
    Remediation
    Fix: Disable Public Access for Neptune Cluster Instance

    Set the publiclyAccessible property to false:

    const neptuneInstance = new aws.neptune.ClusterInstance("neptune-instance", {
        clusterIdentifier: neptuneCluster.id,
        instanceClass: "db.r5.large",
        engine: "neptune",
        publiclyAccessible: false,  // Disable public access
    });
    

    networkfirewall-logging-enabled

    Severity: medium · Enforcement: advisory

    Ensure AWS Network Firewalls have a logging configuration for audit and monitoring purposes.

    • A.8.15 Logging — Logs that record activities, exceptions, faults and other relevant events shall be produced, stored, protected and analysed.
    Remediation
    Fix: Enable Network Firewall Logging
    const firewallLogGroup = new aws.cloudwatch.LogGroup("firewall-logs", {
        name: "/aws/network-firewall/example",
        retentionInDays: 30,
    });
    
    const loggingConfiguration = new aws.networkfirewall.LoggingConfiguration("example-logging", {
        firewallArn: firewall.arn,
        loggingConfiguration: {
            logDestinationConfigs: [{
                logDestination: {
                    logGroup: firewallLogGroup.name,
                },
                logDestinationType: "CloudWatchLogs",
                logType: "FLOW",
            }],
        },
    });
    

    networkfirewall-multi-az

    Severity: medium · Enforcement: advisory

    Network Firewalls must span at least two Availability Zones for resilience.

    • A.8.20 Networks security — Networks and network devices shall be secured, managed and controlled to protect information in systems and applications.
    Remediation
    Fix: Span Multiple Availability Zones

    Configure the firewall with subnet mappings in at least two different Availability Zones so inspection capacity remains available if a zone fails.

    new aws.networkfirewall.Firewall("example", {
        firewallPolicyArn: policy.arn,
        vpcId: vpc.id,
        subnetMappings: [
            { subnetId: subnetAzA.id },
            { subnetId: subnetAzB.id },
        ],
    });
    

    networkfirewall-policy-rule-group-associated

    Severity: medium · Enforcement: advisory

    Network Firewall policies must reference at least one rule group.

    • A.8.20 Networks security — Networks and network devices shall be secured, managed and controlled to protect information in systems and applications.
    Remediation
    Fix: Associate Rule Groups

    Reference at least one stateful or stateless rule group in the firewall policy so traffic is inspected against defined rules.

    new aws.networkfirewall.FirewallPolicy("example", {
        firewallPolicy: {
            statelessDefaultActions: ["aws:forward_to_sfe"],
            statelessFragmentDefaultActions: ["aws:forward_to_sfe"],
            statefulRuleGroupReferences: [{ resourceArn: ruleGroup.arn }],
        },
    });
    

    networkfirewall-policy-stateless-default-action

    Severity: medium · Enforcement: advisory

    Network Firewall policies must drop or forward unmatched packets to the stateful engine.

    • A.8.20 Networks security — Networks and network devices shall be secured, managed and controlled to protect information in systems and applications.
    Remediation
    Fix: Define Stateless Default Actions

    Specify statelessDefaultActions on the firewall policy so packets that match no stateless rule are handled explicitly.

    new aws.networkfirewall.FirewallPolicy("example", {
        firewallPolicy: {
            statelessDefaultActions: ["aws:forward_to_sfe"],
            statelessFragmentDefaultActions: ["aws:forward_to_sfe"],
        },
    });
    

    networkfirewall-policy-stateless-fragment-default-action

    Severity: medium · Enforcement: advisory

    Network Firewall policies must drop or forward fragmented packets to the stateful engine.

    • A.8.20 Networks security — Networks and network devices shall be secured, managed and controlled to protect information in systems and applications.
    Remediation
    Fix: Define Stateless Fragment Default Actions

    Specify statelessFragmentDefaultActions on the firewall policy so fragmented packets that match no stateless rule are handled explicitly.

    new aws.networkfirewall.FirewallPolicy("example", {
        firewallPolicy: {
            statelessDefaultActions: ["aws:forward_to_sfe"],
            statelessFragmentDefaultActions: ["aws:forward_to_sfe"],
        },
    });
    

    networkfirewall-stateless-rule-group-not-empty

    Severity: medium · Enforcement: advisory

    Stateless Network Firewall rule groups must contain at least one rule.

    • A.8.20 Networks security — Networks and network devices shall be secured, managed and controlled to protect information in systems and applications.
    Remediation
    Fix: Define Stateless Rules

    Add at least one stateless rule to the stateless rule group so it performs meaningful inspection.

    new aws.networkfirewall.RuleGroup("example", {
        capacity: 100,
        type: "STATELESS",
        ruleGroup: {
            rulesSource: {
                statelessRulesAndCustomActions: {
                    statelessRules: [{
                        priority: 1,
                        ruleDefinition: {
                            actions: ["aws:drop"],
                            matchAttributes: { protocols: [6] },
                        },
                    }],
                },
            },
        },
    });
    

    no-direct-user-access-keys

    Severity: high · Enforcement: advisory

    Prevents creation of direct IAM user access keys for human users

    • A.5.17 Authentication information — Allocation and management of authentication information shall be controlled by a management process, including advising personnel on appropriate handling of authentication information.
    • A.8.5 Secure authentication — Secure authentication technologies and procedures shall be implemented based on information access restrictions and the topic-specific policy on access control.
    Remediation
    Fix: Use IAM Roles Instead of Access Keys

    Remove the IAM access key resource and use IAM roles with temporary credentials instead:

    // Remove this - do not create IAM access keys
    // const accessKey = new aws.iam.AccessKey("user-key", {
    //     user: user.name,
    // });
    
    // Instead, use IAM roles for workloads
    const role = new aws.iam.Role("app-role", {
        assumeRolePolicy: JSON.stringify({
            Version: "2012-10-17",
            Statement: [{
                Effect: "Allow",
                Principal: { Service: "ec2.amazonaws.com" }, // Use appropriate service
                Action: "sts:AssumeRole",
            }],
        }),
    });
    
    // Attach necessary policies to the role
    new aws.iam.RolePolicyAttachment("app-policy", {
        role: role.name,
        policyArn: "arn:aws:iam::aws:policy/ReadOnlyAccess", // Use least-privilege policy
    });
    
    // For human users, use AWS SSO or federated identity instead of access keys
    

    no-hardcoded-secrets

    Severity: high · Enforcement: advisory

    Ensures EC2 instance userData does not contain hardcoded secrets

    • A.5.17 Authentication information — Allocation and management of authentication information shall be controlled by a management process, including advising personnel on appropriate handling of authentication information.
    Remediation
    Fix: Remove Hardcoded Secrets

    Remove hardcoded secrets from userData scripts.

    Example Violation
    const instance = new aws.ec2.Instance("web-server", {
        instanceType: "t3.micro",
        ami: "ami-12345678",
        userData: `#!/bin/bash
    export DATABASE_PASSWORD="mySecretPassword123"
    export API_KEY="sk_live_abc123def456789"
    mysql -u admin -p"hardcodedPassword" -h db.example.com
    `,
    });
    

    opensearch-access-control-enabled

    Severity: high · Enforcement: advisory

    OpenSearch domains must have fine-grained access control enabled

    • A.8.3 Information access restriction — Access to information and other associated assets shall be restricted in accordance with the established topic-specific policy on access control.
    Remediation
    Fix: Enable Fine-Grained Access Control for OpenSearch Domain

    Set advancedSecurityOptions.enabled to true to enforce fine-grained access control. Fine-grained access control requires both node-to-node encryption and HTTPS enforcement:

    const domain = new aws.opensearch.Domain("my-domain", {
        domainName: "my-opensearch-domain",
        nodeToNodeEncryption: { enabled: true },
        encryptAtRest: { enabled: true },
        domainEndpointOptions: { enforceHttps: true },
        advancedSecurityOptions: {
            enabled: true, // Enable fine-grained access control
            internalUserDatabaseEnabled: true,
            masterUserOptions: {
                masterUserName: masterUser,
                masterUserPassword: masterPassword,
            },
        },
        // ... other configuration
    });
    

    opensearch-encryption-enabled

    Severity: high · Enforcement: advisory

    OpenSearch domains must have encryption at rest enabled

    • A.5.33 Protection of records — Records shall be protected from loss, destruction, falsification, unauthorized access and unauthorized release.
    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Enable Encryption at Rest for OpenSearch Domain

    Enable the encryptAtRest configuration on your OpenSearch domain to encrypt data stored on disk:

    const domain = new aws.opensearch.Domain("my-domain", {
        domainName: "my-opensearch-domain",
        encryptAtRest: {
            enabled: true,  // Enable encryption at rest
        },
        // ... other configuration
    });
    

    opensearch-https-required

    Severity: high · Enforcement: advisory

    OpenSearch domains must require HTTPS for client connections

    • A.5.14 Information transfer — Information transfer rules, procedures, or agreements shall be in place for all types of transfer facilities within the organization and between the organization and other parties.
    • A.8.20 Networks security — Networks and network devices shall be secured, managed and controlled to protect information in systems and applications.
    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Do not disable HTTPS enforcement for OpenSearch domain

    The AWS provider defaults enforceHttps to true — never set it to false. Optionally pin a minimum TLS policy:

    import * as aws from "@pulumi/aws";
    
    const domain = new aws.opensearch.Domain("my-domain", {
        domainName: "my-opensearch-domain",
        domainEndpointOptions: {
            tlsSecurityPolicy: "Policy-Min-TLS-1-2-2019-07",
        },
        // ... other configuration
    });
    

    opensearch-node-to-node-encryption-enabled

    Severity: high · Enforcement: advisory

    OpenSearch domains must have node-to-node encryption enabled

    • A.5.14 Information transfer — Information transfer rules, procedures, or agreements shall be in place for all types of transfer facilities within the organization and between the organization and other parties.
    • A.8.20 Networks security — Networks and network devices shall be secured, managed and controlled to protect information in systems and applications.
    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Enable node-to-node encryption for OpenSearch domain

    Add the nodeToNodeEncryption property to your OpenSearch domain configuration and set enabled to true:

    const domain = new aws.opensearch.Domain("my-domain", {
        domainName: "my-opensearch-domain",
        engineVersion: "OpenSearch_2.11",
        clusterConfig: {
            instanceType: "r5.large.search",
        },
        nodeToNodeEncryption: {
            enabled: true, // Enable encryption for inter-node communication
        },
        // ... other configuration
    });
    

    opensearch-vpc-required

    Severity: high · Enforcement: advisory

    OpenSearch domains must be deployed in VPC for network isolation

    • A.8.20 Networks security — Networks and network devices shall be secured, managed and controlled to protect information in systems and applications.
    • A.8.22 Segregation of networks — Groups of information services, users and information systems shall be segregated in the organization’s networks.
    Remediation
    Fix: Deploy OpenSearch Domain in VPC

    Add VPC configuration to your OpenSearch domain to enable network isolation and boundary protection.

    import * as aws from "@pulumi/aws";
    
    const myOpensearchDomain = new aws.opensearch.Domain("my-domain", {
        domainName: "my-domain",
        engineVersion: "OpenSearch_2.11",
        clusterConfig: {
            instanceType: "r5.large.search",
            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,
        },
    });
    

    pubsub-least-privilege-iam

    Severity: medium · Enforcement: advisory

    Ensures IAM policies follow least privilege principles for Pub/Sub services (SNS, SQS, Kinesis)

    • A.5.15 Access control — Rules to control physical and logical access to information and other associated assets shall be established and implemented based on business and information security requirements.
    • A.8.2 Privileged access rights — The allocation and use of privileged access rights shall be restricted and managed.
    Remediation
    Fix: Use Specific Pub/Sub IAM Actions and Resource ARNs

    Replace wildcard permissions with specific actions and resource ARNs for Pub/Sub services:

    const queuePolicy = new aws.iam.Policy("queue-policy", {
        policy: JSON.stringify({
            Version: "2012-10-17",
            Statement: [{
                Effect: "Allow",
                Action: [
                    "sqs:SendMessage",      // Use specific actions instead of sqs:*
                    "sqs:ReceiveMessage",
                    "sqs:DeleteMessage",
                ],
                Resource: "arn:aws:sqs:us-east-1:123456789012:my-queue", // Use specific ARN instead of *
            }],
        }),
    });
    

    rds-cluster-configure-customer-managed-key

    Severity: low · Enforcement: advisory

    Checks that RDS Clusters storage uses a customer-managed KMS key.

    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Configure Customer-Managed KMS Key for RDS Cluster

    Specify a customer-managed KMS key for RDS Cluster storage encryption using the kmsKeyId property:

    const cluster = new rds.Cluster("my-cluster", {
        engine: "aurora-postgresql",
        storageEncrypted: true,
        kmsKeyId: kmsKey.arn, // Use customer-managed KMS key
        masterUsername: "admin",
        masterPassword: dbPassword,
    });
    

    rds-cluster-disallow-single-availability-zone

    Severity: high · Enforcement: advisory

    Check that RDS Cluster doesn’t use single availability zone.

    • A.5.29 Information security during disruption — The organization shall plan how to maintain information security at an appropriate level during disruption.
    • A.8.14 Redundancy of information processing facilities — Information processing facilities shall be implemented with redundancy sufficient to meet availability requirements.
    • A.5.30 ICT readiness for business continuity — ICT readiness shall be planned, implemented, maintained and tested based on business continuity objectives and ICT continuity requirements.
    Remediation
    Fix: Configure Multiple Availability Zones for RDS Cluster

    Specify at least two availability zones in the availabilityZones property to ensure high availability and resilience:

    const cluster = new rds.Cluster("my-cluster", {
        engine: "aurora-mysql",
        engineVersion: "8.0.mysql_aurora.3.04.0",
        availabilityZones: ["us-east-1a", "us-east-1b"], // Configure at least two AZs
        databaseName: "mydb",
        masterUsername: "admin",
        masterPassword: dbPassword,
        skipFinalSnapshot: true,
    });
    

    rds-cluster-disallow-unencrypted-storage

    Severity: high · Enforcement: advisory

    Checks that RDS Clusters storage is encrypted.

    • A.5.33 Protection of records — Records shall be protected from loss, destruction, falsification, unauthorized access and unauthorized release.
    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Enable RDS Cluster Storage Encryption

    Set the storageEncrypted property to true to enable encryption at rest for the RDS cluster:

    const cluster = new aws.rds.Cluster("my-cluster", {
        engine: "aurora-mysql",
        engineVersion: "8.0.mysql_aurora.3.02.0",
        masterUsername: "admin",
        masterPassword: dbPassword,
        storageEncrypted: true, // Enable storage encryption
        databaseName: "mydb",
        skipFinalSnapshot: true,
    });
    

    rds-cluster-enable-backup-retention

    Severity: medium · Enforcement: advisory

    Checks that RDS Clusters backup retention policy is enabled.

    • A.5.29 Information security during disruption — The organization shall plan how to maintain information security at an appropriate level during disruption.
    • A.8.13 Information backup — Backup copies of information, software and systems shall be maintained and regularly tested in accordance with the agreed topic-specific policy on backup.
    • A.5.30 ICT readiness for business continuity — ICT readiness shall be planned, implemented, maintained and tested based on business continuity objectives and ICT continuity requirements.
    Remediation
    Fix: Enable RDS Cluster Backup Retention

    Set the backupRetentionPeriod to a value between 1 and 35 days to enable automated backups:

    const cluster = new rds.Cluster("my-cluster", {
        engine: "aurora-mysql",
        masterUsername: "admin",
        masterPassword: dbPassword,
        backupRetentionPeriod: 7, // Enable backup retention (1-35 days)
        preferredBackupWindow: "03:00-04:00",
    });
    

    rds-cluster-iam-authentication

    Severity: high · Enforcement: advisory

    RDS clusters must have IAM database authentication enabled

    • A.8.5 Secure authentication — Secure authentication technologies and procedures shall be implemented based on information access restrictions and the topic-specific policy on access control.
    Remediation
    Fix: Enable IAM Database Authentication for RDS Cluster

    Set iamDatabaseAuthenticationEnabled to true on the cluster.

    new aws.rds.Cluster("cluster", {
        clusterIdentifier: "my-cluster",
        engine: "aurora-mysql",
        iamDatabaseAuthenticationEnabled: true,
    });
    

    rds-cluster-instance-disallow-public-access

    Severity: critical · Enforcement: advisory

    Checks that RDS Cluster Instances public access is not enabled.

    • A.5.15 Access control — Rules to control physical and logical access to information and other associated assets shall be established and implemented based on business and information security requirements.
    • A.8.3 Information access restriction — Access to information and other associated assets shall be restricted in accordance with the established topic-specific policy on access control.
    Remediation
    Fix: Disable Public Access for RDS Cluster Instance

    Set the publiclyAccessible property to false to ensure the RDS Cluster Instance is not accessible from the public internet:

    const clusterInstance = new aws.rds.ClusterInstance("my-cluster-instance", {
        clusterIdentifier: cluster.id,
        instanceClass: "db.r5.large",
        engine: "aurora-postgresql",
        publiclyAccessible: false, // Disable public access
    });
    

    rds-cluster-logging-enabled

    Severity: medium · Enforcement: advisory

    Ensure RDS clusters have logging enabled for monitoring and audit compliance.

    • A.8.15 Logging — Logs that record activities, exceptions, faults and other relevant events shall be produced, stored, protected and analysed.
    Remediation
    Fix: Enable CloudWatch logs exports

    For Aurora clusters (logging is configured at the cluster level, applies to all cluster instances):

    const cluster = new aws.rds.Cluster("myCluster", {
        engine: "aurora-postgresql",
        enabledCloudwatchLogsExports: ["postgresql"],  // This fixes the violation
    });
    

    Note: For Aurora databases, configure logging on the rds.Cluster resource. All cluster instances inherit this configuration.

    rds-cluster-secure-master-credentials

    Severity: high · Enforcement: advisory

    Ensures RDS clusters use secure credential management instead of hardcoded passwords

    • A.5.17 Authentication information — Allocation and management of authentication information shall be controlled by a management process, including advising personnel on appropriate handling of authentication information.
    Remediation
    Fix: Use AWS Secrets Manager for RDS Cluster Master Credentials

    Enable AWS-managed master password using Secrets Manager instead of hardcoded credentials:

    const dbCluster = new aws.rds.Cluster("my-cluster", {
        engine: "aurora-mysql",
        engineVersion: "8.0.mysql_aurora.3.02.0",
        manageMasterUserPassword: true, // Enable AWS Secrets Manager for master password
        masterUsername: "admin",
        // Do NOT set the masterPassword property - AWS Secrets Manager handles it
        vpcSecurityGroupIds: [securityGroup.id],
        dbSubnetGroupName: subnetGroup.name,
    });
    

    rds-clusterinstance-enhanced-monitoring

    Severity: medium · Enforcement: advisory

    RDS cluster instances must have enhanced monitoring enabled to provide detailed system-level metrics

    • A.8.16 Monitoring activities — Networks, systems and applications shall be monitored for anomalous behaviour and appropriate actions taken to evaluate potential information security incidents.
    Remediation
    Fix: Enable RDS Cluster Instance Enhanced Monitoring

    Configure the RDS cluster instance with monitoringInterval and monitoringRoleArn to enable enhanced monitoring:

    import * as aws from "@pulumi/aws";
    
    // Create IAM role for RDS enhanced monitoring
    const monitoringRole = new aws.iam.Role("rds-monitoring-role", {
        assumeRolePolicy: JSON.stringify({
            Version: "2012-10-17",
            Statement: [{
                Action: "sts:AssumeRole",
                Principal: { Service: "monitoring.rds.amazonaws.com" },
                Effect: "Allow",
            }],
        }),
    });
    
    new aws.iam.RolePolicyAttachment("rds-monitoring-policy", {
        role: monitoringRole.name,
        policyArn: "arn:aws:iam::aws:policy/service-role/AmazonRDSEnhancedMonitoringRole",
    });
    
    const clusterInstance = new aws.rds.ClusterInstance("my-cluster-instance", {
        clusterIdentifier: cluster.id,
        instanceClass: "db.r5.large",
        engine: cluster.engine,
        monitoringInterval: 60, // Valid values: 0, 1, 5, 10, 15, 30, 60
        monitoringRoleArn: monitoringRole.arn, // Required for enhanced monitoring
    });
    

    rds-clusterinstance-managed-service-patching

    Severity: medium · Enforcement: advisory

    Ensures RDS cluster instances have automated minor version upgrades enabled

    • A.8.8 Management of technical vulnerabilities — Information about technical vulnerabilities of information systems in use shall be obtained, the organization’s exposure to such vulnerabilities shall be evaluated and appropriate measures shall be taken.
    Remediation
    Fix: Enable Automatic Minor Version Upgrades for Aurora Cluster Instance

    Set the autoMinorVersionUpgrade property to true to enable automated patching for managed service security updates:

    const clusterInstance = new aws.rds.ClusterInstance("my-cluster-instance", {
        clusterIdentifier: cluster.id,
        instanceClass: "db.r5.large",
        engine: cluster.engine,
        autoMinorVersionUpgrade: true, // Enable automatic minor version upgrades
    });
    

    rds-clusterinstance-ssl-encryption

    Severity: high · Enforcement: advisory

    Ensures RDS cluster instances have SSL/TLS encryption enabled through parameter group configuration

    • A.5.14 Information transfer — Information transfer rules, procedures, or agreements shall be in place for all types of transfer facilities within the organization and between the organization and other parties.
    • A.8.20 Networks security — Networks and network devices shall be secured, managed and controlled to protect information in systems and applications.
    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Configure SSL/TLS Encryption for Aurora Cluster Instance

    Configure a parameter group to enforce SSL/TLS connections for your Aurora cluster instance:

    const clusterParamGroup = new aws.rds.ParameterGroup("cluster-params", {
        family: "aurora-postgresql14",
        parameters: [
            {
                name: "rds.force_ssl",
                value: "1", // Enforce SSL/TLS for all connections
            },
        ],
    });
    
    const clusterInstance = new aws.rds.ClusterInstance("my-cluster-instance", {
        clusterIdentifier: cluster.id,
        instanceClass: "db.r5.large",
        engine: cluster.engine,
        dbParameterGroupName: clusterParamGroup.name, // Attach parameter group with SSL enforcement
    });
    

    rds-deletion-protection

    Severity: medium · Enforcement: advisory

    RDS database instances must have deletion protection enabled to prevent accidental deletion and ensure data availability

    • A.5.29 Information security during disruption — The organization shall plan how to maintain information security at an appropriate level during disruption.
    • A.5.30 ICT readiness for business continuity — ICT readiness shall be planned, implemented, maintained and tested based on business continuity objectives and ICT continuity requirements.
    Remediation
    Fix: Enable RDS Deletion Protection

    Set the deletionProtection property to true on your RDS instance:

    import * as aws from "@pulumi/aws";
    
    const db = new aws.rds.Instance("myDatabase", {
        engine: "postgres",
        instanceClass: "db.t3.micro",
        allocatedStorage: 20,
        deletionProtection: true,  // Enable deletion protection
        // ... other configuration
    });
    

    rds-iam-authentication

    Severity: medium · Enforcement: advisory

    Ensures RDS instances have IAM database authentication enabled

    • A.5.17 Authentication information — Allocation and management of authentication information shall be controlled by a management process, including advising personnel on appropriate handling of authentication information.
    • A.8.5 Secure authentication — Secure authentication technologies and procedures shall be implemented based on information access restrictions and the topic-specific policy on access control.
    Remediation
    Fix: Enable IAM Database Authentication for RDS Instance

    Set the iamDatabaseAuthenticationEnabled property to true to enable IAM-based authentication for your RDS instance:

    const rdsInstance = new aws.rds.Instance("my-database", {
        engine: "mysql",
        instanceClass: "db.t3.micro",
        allocatedStorage: 20,
        username: "admin",
        iamDatabaseAuthenticationEnabled: true, // Enable IAM database authentication
        skipFinalSnapshot: true,
    });
    

    rds-instance-configure-customer-managed-key

    Severity: low · Enforcement: advisory

    Checks that RDS Instance storage uses a customer-managed KMS key.

    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Configure Customer-Managed KMS Key for RDS Instance

    Specify a customer-managed KMS key when enabling storage encryption on your RDS instance:

    const rdsInstance = new aws.rds.Instance("my-db", {
        allocatedStorage: 20,
        engine: "postgres",
        instanceClass: "db.t3.micro",
        storageEncrypted: true,
        kmsKeyId: kmsKey.arn, // Specify customer-managed KMS key ARN
        // ... other configuration
    });
    

    rds-instance-disallow-public-access

    Severity: critical · Enforcement: advisory

    Checks that RDS Instance public access is not enabled.

    • A.5.15 Access control — Rules to control physical and logical access to information and other associated assets shall be established and implemented based on business and information security requirements.
    • A.8.3 Information access restriction — Access to information and other associated assets shall be restricted in accordance with the established topic-specific policy on access control.
    Remediation
    Fix: Disable Public Access for RDS Instance

    Set publiclyAccessible to false to prevent the RDS instance from being accessible from the internet:

    const dbInstance = new aws.rds.Instance("my-database", {
        allocatedStorage: 20,
        engine: "mysql",
        engineVersion: "8.0",
        instanceClass: "db.t3.micro",
        dbSubnetGroupName: privateSubnetGroup.name,
        vpcSecurityGroupIds: [dbSecurityGroup.id],
        publiclyAccessible: false, // Disable public access
        username: dbUsername,
        password: dbPassword,
    });
    

    rds-instance-disallow-unencrypted-storage

    Severity: high · Enforcement: advisory

    Checks that RDS instance storage is encrypted.

    • A.5.33 Protection of records — Records shall be protected from loss, destruction, falsification, unauthorized access and unauthorized release.
    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Enable RDS Storage Encryption

    Set the storageEncrypted property to true to encrypt the RDS instance storage:

    const dbInstance = new aws.rds.Instance("my-db", {
        engine: "postgres",
        instanceClass: "db.t3.micro",
        allocatedStorage: 20,
        storageEncrypted: true, // Enable storage encryption
        username: "admin",
        password: adminPassword,
    });
    

    rds-instance-enable-backup-retention

    Severity: medium · Enforcement: advisory

    Checks that RDS Instances backup retention policy is enabled.

    • A.5.29 Information security during disruption — The organization shall plan how to maintain information security at an appropriate level during disruption.
    • A.8.13 Information backup — Backup copies of information, software and systems shall be maintained and regularly tested in accordance with the agreed topic-specific policy on backup.
    • A.5.30 ICT readiness for business continuity — ICT readiness shall be planned, implemented, maintained and tested based on business continuity objectives and ICT continuity requirements.
    Remediation
    Fix: Enable Backup Retention for RDS Instance

    Set the backupRetentionPeriod to a value between 1 and 35 days to enable automated backups:

    const dbInstance = new aws.rds.Instance("my-db", {
        engine: "mysql",
        instanceClass: "db.t3.micro",
        allocatedStorage: 20,
        backupRetentionPeriod: 7, // Enable backup retention (1-35 days)
        username: "admin",
        password: dbPassword,
    });
    

    rds-instance-enhanced-monitoring

    Severity: medium · Enforcement: advisory

    RDS database instances must have enhanced monitoring enabled to provide detailed system-level metrics

    • A.8.16 Monitoring activities — Networks, systems and applications shall be monitored for anomalous behaviour and appropriate actions taken to evaluate potential information security incidents.
    Remediation
    Fix: Enable RDS Instance Enhanced Monitoring

    Configure the RDS instance with monitoringInterval and monitoringRoleArn to enable enhanced monitoring:

    import * as aws from "@pulumi/aws";
    
    // Create IAM role for RDS enhanced monitoring
    const monitoringRole = new aws.iam.Role("rds-monitoring-role", {
        assumeRolePolicy: JSON.stringify({
            Version: "2012-10-17",
            Statement: [{
                Action: "sts:AssumeRole",
                Principal: { Service: "monitoring.rds.amazonaws.com" },
                Effect: "Allow",
            }],
        }),
    });
    
    new aws.iam.RolePolicyAttachment("rds-monitoring-policy", {
        role: monitoringRole.name,
        policyArn: "arn:aws:iam::aws:policy/service-role/AmazonRDSEnhancedMonitoringRole",
    });
    
    const db = new aws.rds.Instance("my-database", {
        engine: "postgres",
        instanceClass: "db.t3.micro",
        allocatedStorage: 20,
        // Enable enhanced monitoring with 60-second interval
        monitoringInterval: 60, // Valid values: 0, 1, 5, 10, 15, 30, 60
        monitoringRoleArn: monitoringRole.arn, // Required for enhanced monitoring
    });
    

    rds-instance-high-availability

    Severity: medium · Enforcement: advisory

    Ensures RDS instances have Multi-AZ deployment enabled for high availability

    • A.5.29 Information security during disruption — The organization shall plan how to maintain information security at an appropriate level during disruption.
    • A.8.14 Redundancy of information processing facilities — Information processing facilities shall be implemented with redundancy sufficient to meet availability requirements.
    • A.5.30 ICT readiness for business continuity — ICT readiness shall be planned, implemented, maintained and tested based on business continuity objectives and ICT continuity requirements.
    Remediation
    Fix: Enable Multi-AZ Deployment for RDS Instance

    Set the multiAz property to true to enable automatic failover to a standby replica in a different Availability Zone:

    const dbInstance = new aws.rds.Instance("my-database", {
        allocatedStorage: 20,
        engine: "mysql",
        engineVersion: "8.0",
        instanceClass: "db.t3.micro",
        username: "admin",
        password: dbPassword,
        multiAz: true, // Enable Multi-AZ deployment for high availability
        skipFinalSnapshot: true,
    });
    

    rds-instance-logging-enabled

    Severity: medium · Enforcement: advisory

    Ensure RDS database instances have logging enabled for monitoring and audit compliance.

    • A.8.15 Logging — Logs that record activities, exceptions, faults and other relevant events shall be produced, stored, protected and analysed.
    Remediation
    Fix: Enable CloudWatch logs exports

    For standalone RDS instances:

    const dbInstance = new aws.rds.Instance("myDb", {
        engine: "postgres",
        instanceClass: "db.t3.micro",
        allocatedStorage: 20,
        enabledCloudwatchLogsExports: ["postgresql"],  // This fixes the violation
    });
    

    rds-instance-managed-service-patching

    Severity: medium · Enforcement: advisory

    Ensures RDS instances have automated minor version upgrades enabled

    • A.8.8 Management of technical vulnerabilities — Information about technical vulnerabilities of information systems in use shall be obtained, the organization’s exposure to such vulnerabilities shall be evaluated and appropriate measures shall be taken.
    Remediation
    Fix: Enable Automatic Minor Version Upgrades for RDS

    Set the autoMinorVersionUpgrade property to true to enable automated patching for managed service security updates:

    const db = new aws.rds.Instance("my-database", {
        engine: "postgres",
        instanceClass: "db.t3.micro",
        allocatedStorage: 20,
        dbName: "mydb",
        username: "admin",
        password: dbPassword,
        autoMinorVersionUpgrade: true, // Enable automatic minor version upgrades
        skipFinalSnapshot: true,
    });
    

    rds-instance-ssl-encryption

    Severity: high · Enforcement: advisory

    Ensures RDS instances have SSL/TLS encryption enabled through parameter group configuration

    • A.5.14 Information transfer — Information transfer rules, procedures, or agreements shall be in place for all types of transfer facilities within the organization and between the organization and other parties.
    • A.8.20 Networks security — Networks and network devices shall be secured, managed and controlled to protect information in systems and applications.
    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Configure SSL/TLS Encryption for RDS Instance

    Configure a parameter group to enforce SSL/TLS connections for your RDS instance:

    const dbParamGroup = new aws.rds.ParameterGroup("db-params", {
        family: "mysql8.0",
        parameters: [
            {
                name: "require_secure_transport",
                value: "1", // Enforce SSL/TLS for all connections
            },
        ],
    });
    
    const db = new aws.rds.Instance("my-database", {
        engine: "mysql",
        instanceClass: "db.t3.micro",
        allocatedStorage: 20,
        parameterGroupName: dbParamGroup.name, // Attach parameter group with SSL enforcement
        username: "admin",
        password: dbPassword,
    });
    

    rds-private-subnet-validation

    Severity: high · Enforcement: advisory

    Validates that RDS DB subnet groups contain only private subnets

    • A.8.3 Information access restriction — Access to information and other associated assets shall be restricted in accordance with the established topic-specific policy on access control.
    Remediation
    Fix: Deploy RDS DB Subnet Group in Private Subnets

    Ensure the DB subnet group only contains subnets that do not have routes to an Internet Gateway. Private subnets should route internet-bound traffic through a NAT Gateway instead:

    const privateSubnetGroup = new aws.rds.SubnetGroup("db-subnet-group", {
        subnetIds: [
            privateSubnet1.id,  // Private subnet without Internet Gateway route
            privateSubnet2.id,  // Private subnet without Internet Gateway route
        ],
        tags: {
            Name: "Private DB Subnet Group",
        },
    });
    
    const db = new aws.rds.Instance("database", {
        dbSubnetGroupName: privateSubnetGroup.name,
        publiclyAccessible: false,
        // ... other configuration
    });
    

    rds-secure-master-credentials

    Severity: high · Enforcement: advisory

    Ensures RDS instances use secure credential management instead of hardcoded passwords

    • A.5.17 Authentication information — Allocation and management of authentication information shall be controlled by a management process, including advising personnel on appropriate handling of authentication information.
    Remediation
    Fix: Use AWS Secrets Manager for RDS Master Credentials

    Enable AWS-managed master password using Secrets Manager instead of hardcoded credentials:

    const dbInstance = new aws.rds.Instance("my-db", {
        allocatedStorage: 20,
        engine: "mysql",
        instanceClass: "db.t3.micro",
        manageMasterUserPassword: true, // Enable AWS Secrets Manager for master password
        username: "admin",
        // Do NOT set the password property - AWS Secrets Manager handles it
        vpcSecurityGroupIds: [securityGroup.id],
        dbSubnetGroupName: subnetGroup.name,
    });
    

    redshift-automatic-snapshots-required

    Severity: medium · Enforcement: advisory

    Ensures Redshift clusters have automatic snapshots enabled with minimum 7-day retention period.

    • A.5.29 Information security during disruption — The organization shall plan how to maintain information security at an appropriate level during disruption.
    • A.8.13 Information backup — Backup copies of information, software and systems shall be maintained and regularly tested in accordance with the agreed topic-specific policy on backup.
    • A.5.30 ICT readiness for business continuity — ICT readiness shall be planned, implemented, maintained and tested based on business continuity objectives and ICT continuity requirements.
    Remediation
    Fix: Enable Automatic Snapshots with Minimum Retention Period

    Set the automatedSnapshotRetentionPeriod property to at least 7 days on your Redshift cluster:

    import * as aws from "@pulumi/aws";
    
    const cluster = new aws.redshift.Cluster("myCluster", {
        clusterIdentifier: "my-redshift-cluster",
        nodeType: "dc2.large",
        numberOfNodes: 2,
        // Enable automatic snapshots with minimum 7-day retention
        automatedSnapshotRetentionPeriod: 7,
    });
    

    redshift-enhanced-vpc-routing-enabled

    Severity: medium · Enforcement: advisory

    Ensures Redshift clusters have enhanced VPC routing enabled for network isolation.

    • A.8.20 Networks security — Networks and network devices shall be secured, managed and controlled to protect information in systems and applications.
    • A.8.22 Segregation of networks — Groups of information services, users and information systems shall be segregated in the organization’s networks.
    Remediation
    Fix: Enable Enhanced VPC Routing

    Set the enhancedVpcRouting property to true on your Redshift cluster to ensure all COPY and UNLOAD traffic flows through your VPC infrastructure.

    const cluster = new aws.redshift.Cluster("my-cluster", {
        clusterIdentifier: "my-cluster",
        // ... other configuration ...
        enhancedVpcRouting: true, // Enable enhanced VPC routing for network isolation
    });
    

    redshift-kms-encryption-enabled

    Severity: high · Enforcement: advisory

    Ensures Redshift clusters have encryption enabled using KMS keys.

    • A.5.33 Protection of records — Records shall be protected from loss, destruction, falsification, unauthorized access and unauthorized release.
    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Enable Encryption at Rest for Redshift Cluster

    Enable encryption on your Redshift cluster by setting the ’encrypted’ property to true and providing a customer-managed KMS key.

    import * as aws from "@pulumi/aws";
    
    const cluster = new aws.redshift.Cluster("my-cluster", {
        clusterIdentifier: "my-redshift-cluster",
        encrypted: true, // Enable encryption at rest
        kmsKeyId: kmsKey.arn, // Use a customer-managed KMS key
        // ... other configuration
    });
    

    If you only need AWS managed encryption (not recommended), you can set ’encrypted’ to true without specifying ‘kmsKeyId’, but you must configure the policy to allow this by setting ‘requireCustomKMSKey’ to false in the policy configuration.

    redshift-logging-enabled

    Severity: medium · Enforcement: advisory

    Ensures Redshift clusters have logging configurations enabled for audit and monitoring purposes.

    • A.8.15 Logging — Logs that record activities, exceptions, faults and other relevant events shall be produced, stored, protected and analysed.
    Remediation
    Fix: Enable Redshift cluster logging

    Create a redshift.Logging resource to enable audit logging for your Redshift cluster. Configure either S3 or CloudWatch as the log destination to capture connection logs and user activity logs.

    import * as aws from "@pulumi/aws";
    
    const cluster = new aws.redshift.Cluster("my-cluster", {
        clusterIdentifier: "my-redshift-cluster",
        // ... other cluster configuration
    });
    
    // Add logging configuration for the cluster
    const clusterLogging = new aws.redshift.Logging("my-cluster-logging", {
        clusterIdentifier: cluster.clusterIdentifier,
        logDestinationType: "s3", // or "cloudwatch"
        bucketName: "my-audit-logs-bucket", // Required for S3 destination
        s3KeyPrefix: "redshift-logs/", // Optional: organize logs with prefix
        logExports: ["connectionlog", "useractivitylog"], // Enable audit log types
    });
    

    redshift-maintenance-required

    Severity: medium · Enforcement: advisory

    Ensures Redshift clusters have proper maintenance settings configured for automated updates.

    • A.8.8 Management of technical vulnerabilities — Information about technical vulnerabilities of information systems in use shall be obtained, the organization’s exposure to such vulnerabilities shall be evaluated and appropriate measures shall be taken.
    Remediation
    Fix: Configure Redshift Maintenance Settings

    Add a preferred maintenance window and enable automatic version upgrades to allow automated security updates and system baseline changes.

    const cluster = new aws.redshift.Cluster("my-cluster", {
        clusterIdentifier: "my-redshift-cluster",
        // ... other configuration ...
    
        // Configure maintenance window for automated updates
        preferredMaintenanceWindow: "sun:05:00-sun:06:00", // Weekly maintenance window
    
        // Enable automatic version upgrades for security patches
        allowVersionUpgrade: true,
    });
    

    redshift-public-access-prohibited

    Severity: critical · Enforcement: advisory

    Ensures Redshift clusters prohibit public access to prevent unauthorized connections.

    • A.5.15 Access control — Rules to control physical and logical access to information and other associated assets shall be established and implemented based on business and information security requirements.
    • A.8.3 Information access restriction — Access to information and other associated assets shall be restricted in accordance with the established topic-specific policy on access control.
    Remediation
    Fix: Disable Public Access for Redshift Cluster
    const cluster = new aws.redshift.Cluster("data-warehouse", {
        clusterIdentifier: "my-cluster",
        nodeType: "dc2.large",
        masterUsername: "admin",
        masterPassword: password.result,
        publiclyAccessible: false,  // Disable public access to prevent internet exposure
        vpcSecurityGroupIds: [securityGroup.id],
        clusterSubnetGroupName: subnetGroup.name,
    });
    

    redshift-ssl-required

    Severity: high · Enforcement: advisory

    Ensures Redshift clusters have encryption in transit enabled through SSL parameter configuration.

    • A.5.14 Information transfer — Information transfer rules, procedures, or agreements shall be in place for all types of transfer facilities within the organization and between the organization and other parties.
    • A.8.20 Networks security — Networks and network devices shall be secured, managed and controlled to protect information in systems and applications.
    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Enable SSL/TLS encryption for Redshift cluster connections

    Create a parameter group with require_ssl set to true and associate it with your Redshift cluster:

    import * as aws from "@pulumi/aws";
    
    // Create parameter group with SSL requirement
    const parameterGroup = new aws.redshift.ParameterGroup("secure-parameter-group", {
        family: "redshift-1.0",
        parameters: [
            {
                name: "require_ssl",
                value: "true", // Enable SSL/TLS encryption in transit
            },
        ],
    });
    
    // Associate parameter group with Redshift cluster
    const cluster = new aws.redshift.Cluster("my-cluster", {
        clusterIdentifier: "my-secure-cluster",
        clusterParameterGroupName: parameterGroup.name, // Reference the secure parameter group
        // ... other cluster configuration
    });
    

    resource-tagging

    Severity: low · Enforcement: advisory

    Ensures all AWS resources must include tags for proper change tracking

    • A.5.9 Inventory of information and other associated assets — An inventory of information and other associated assets, including owners, shall be developed and maintained.
    Remediation
    Fix: Add Required Tags to AWS Resources

    Add a tags property with meaningful values to enable proper change tracking and documentation:

    const instance = new aws.ec2.Instance("my-instance", {
        ami: "ami-0c55b159cbfafe1f0",
        instanceType: "t3.micro",
        tags: {
            Environment: "production", // Add meaningful tags for change tracking
            Owner: "team-name",
            Application: "web-app",
        },
    });
    

    restrict-default-iam-user-creation

    Severity: medium · Enforcement: advisory

    Ensures that default IAM user accounts are not allowed to be created

    • A.8.2 Privileged access rights — The allocation and use of privileged access rights shall be restricted and managed.
    Remediation
    Fix: Use Descriptive User Names

    Use specific, descriptive user names that follow your organization’s naming conventions instead of generic default names:

    const iamUser = new aws.iam.User("my-iam-user", {
        name: "john.doe", // Use descriptive, organization-specific user names
        // Avoid generic names like: root, admin, administrator, default, user, guest, test, demo
    });
    

    s3-accesspoint-public-access-block

    Severity: high · Enforcement: advisory

    S3 access points must block all public access

    • A.8.20 Networks security — Networks and network devices shall be secured, managed and controlled to protect information in systems and applications.
    Remediation
    Fix: Block Public Access on S3 Access Point

    All four publicAccessBlockConfiguration settings default to true. Do not explicitly set any of them to false.

    new aws.s3.AccessPoint("ap", {
        bucket: bucket.id,
        name: "my-access-point",
        publicAccessBlockConfiguration: {
            blockPublicAcls: true,
            blockPublicPolicy: true,
            ignorePublicAcls: true,
            restrictPublicBuckets: true,
        },
    });
    

    s3-bucket-access-logging

    Severity: medium · Enforcement: advisory

    Ensures each S3 bucket has access logging enabled

    • A.8.15 Logging — Logs that record activities, exceptions, faults and other relevant events shall be produced, stored, protected and analysed.
    Remediation
    Fix: Enable S3 Bucket Access Logging

    Create a BucketLogging resource with a target bucket and prefix to enable access logging:

    const myBucket = new aws.s3.Bucket("my-bucket", {
        // Bucket configuration
    });
    
    const logBucket = new aws.s3.Bucket("log-bucket", {
        // Configure log bucket settings
    });
    
    const bucketLogging = new aws.s3.BucketLogging("my-bucket-logging", {
        bucket: myBucket.id,
        targetBucket: logBucket.id, // Specify target bucket for logs
        targetPrefix: "logs/my-bucket/", // Specify prefix for organization
    });
    

    s3-bucket-acl-prohibited

    Severity: medium · Enforcement: advisory

    Prohibit user-permission ACLs on S3 buckets; use bucket policies and Block Public Access instead.

    • A.5.15 Access control — Rules to control physical and logical access to information and other associated assets shall be established and implemented based on business and information security requirements.
    • A.8.3 Information access restriction — Access to information and other associated assets shall be restricted in accordance with the established topic-specific policy on access control.
    Remediation
    Fix: Remove User-Permission ACLs

    Manage S3 access with bucket policies and S3 Block Public Access rather than ACL grants. Use the canned private ACL and omit grants.

    const bucketAcl = new aws.s3.BucketAcl("acl", {
        bucket: bucket.id,
        acl: "private",
    });
    

    s3-bucket-encryption

    Severity: high · Enforcement: advisory

    S3 buckets must have server-side encryption configured using BucketServerSideEncryptionConfiguration resource

    • A.5.33 Protection of records — Records shall be protected from loss, destruction, falsification, unauthorized access and unauthorized release.
    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Configure S3 Bucket Server-Side Encryption

    Create a separate BucketServerSideEncryptionConfigurationV2 resource for your S3 bucket with encryption rules. Use AES256 or KMS encryption:

    const bucket = new aws.s3.BucketV2("my-bucket", {
        bucket: "my-secure-bucket",
    });
    
    // Add encryption configuration resource
    const bucketEncryption = new aws.s3.BucketServerSideEncryptionConfiguration("my-bucket-encryption", {
        bucket: bucket.id,
        rules: [{
            applyServerSideEncryptionByDefault: {
                sseAlgorithm: "aws:kms", // Enable KMS encryption
                kmsMasterKeyId: kmsKey.arn, // Specify customer-managed key
            },
            bucketKeyEnabled: true, // Enable bucket key for cost optimization
        }],
    });
    

    s3-bucket-least-privilege

    Severity: critical · Enforcement: advisory

    Prevents overly permissive S3 bucket policies

    • A.5.15 Access control — Rules to control physical and logical access to information and other associated assets shall be established and implemented based on business and information security requirements.
    • A.8.2 Privileged access rights — The allocation and use of privileged access rights shall be restricted and managed.
    Remediation
    Fix: Use Specific Actions, Resources, and Principals

    Replace wildcard (*) values in S3 bucket policy statements with specific, scoped permissions:

    const bucketPolicy = new aws.s3.BucketPolicy("policy", {
        bucket: bucket.id,
        policy: bucket.arn.apply(arn => JSON.stringify({
            Version: "2012-10-17",
            Statement: [{
                Effect: "Allow",
                Principal: {
                    AWS: "arn:aws:iam::123456789012:role/specific-role" // Specify exact principal ARN
                },
                Action: ["s3:GetObject", "s3:PutObject"], // Use specific S3 actions
                Resource: `${arn}/*` // Scope to specific bucket
            }]
        }))
    });
    

    s3-bucket-lifecycle

    Severity: medium · Enforcement: advisory

    Ensures each S3 bucket has lifecycle rules configured for retention/disposal

    • A.8.10 Information deletion — Information stored in information systems, devices or in any other storage media shall be deleted when no longer required.
    Remediation
    Fix: Configure Lifecycle Rules for S3 Bucket

    Create a BucketLifecycleConfiguration resource with at least one enabled rule:

    const myBucket = new aws.s3.Bucket("my-bucket", {
        // Bucket configuration
    });
    
    const lifecycleConfig = new aws.s3.BucketLifecycleConfiguration("my-bucket-lifecycle", {
        bucket: myBucket.id,
        rules: [
            {
                id: "delete-old-objects",
                status: "Enabled", // Rule must be enabled
                expiration: {
                    days: 90, // Define retention period (e.g., expire after 90 days)
                },
            },
        ],
    });
    

    s3-bucket-macie-access

    Severity: medium · Enforcement: advisory

    Ensures S3 buckets allow AWS Macie access for data classification and discovery

    • A.8.12 Data leakage prevention — Data leakage prevention measures shall be applied to systems, networks and any other devices that process, store or transmit sensitive information.
    Remediation
    Fix: Allow AWS Macie Service Access in S3 Bucket Policy

    Add an Allow statement for the AWS Macie service principal in your S3 bucket policy, or ensure Deny statements exclude the Macie service-linked role:

    const bucketPolicy = new aws.s3.BucketPolicy("my-bucket-policy", {
        bucket: bucket.id,
        policy: bucket.arn.apply(arn => JSON.stringify({
            Version: "2012-10-17",
            Statement: [
                {
                    Effect: "Allow",
                    Principal: {
                        Service: "macie.amazonaws.com" // Allow Macie service access
                    },
                    Action: [
                        "s3:GetObject",
                        "s3:GetBucketLocation",
                        "s3:ListBucket"
                    ],
                    Resource: [
                        arn,
                        `${arn}/*`
                    ]
                }
            ]
        }))
    });
    

    s3-bucket-object-lock-enabled

    Severity: medium · Enforcement: advisory

    S3 buckets must have object lock enabled to protect audit information and prevent unauthorized deletion

    • A.5.33 Protection of records — Records shall be protected from loss, destruction, falsification, unauthorized access and unauthorized release.
    • A.8.15 Logging — Logs that record activities, exceptions, faults and other relevant events shall be produced, stored, protected and analysed.
    Remediation
    Fix: Enable S3 Bucket Object Lock with Retention Rules

    Configure object lock on your S3 bucket to enable write-once-read-many (WORM) protection for audit data:

    import * as aws from "@pulumi/aws";
    
    const auditBucket = new aws.s3.BucketV2("audit-logs", {
        bucket: "my-audit-logs",
        objectLockEnabled: true, // Enable object lock on bucket creation
    });
    
    new aws.s3.BucketObjectLockConfigurationV2("audit-logs-lock-config", {
        bucket: auditBucket.id,
        objectLockEnabled: "Enabled", // Explicitly enable object lock
        rule: {
            defaultRetention: {
                mode: "COMPLIANCE", // Use COMPLIANCE for immutable protection
                days: 90, // Retain objects for 90 days minimum
            },
        },
    });
    

    Note: Object lock can only be enabled during bucket creation. If you need to enable it on an existing bucket, you must create a new bucket with object lock enabled and migrate your data.

    s3-bucket-policy-grantee-check

    Severity: high · Enforcement: advisory

    Ensure S3 bucket policies do not grant access to inappropriate principals for proper access control.

    • A.5.15 Access control — Rules to control physical and logical access to information and other associated assets shall be established and implemented based on business and information security requirements.
    Remediation
    Fix: Use Specific Principals
    const policy = new aws.s3.BucketPolicy("policy", {
        bucket: bucket.id,
        policy: JSON.stringify({
            Statement: [{
                Principal: { AWS: "arn:aws:iam::123456789012:root" },  // Specific account, not "*"
                Action: "s3:GetObject",
                Resource: pulumi.interpolate`${bucket.arn}/*`,
            }],
        }),
    });
    

    s3-bucket-public-access-block

    Severity: critical · Enforcement: advisory

    Ensures each S3 bucket has a public access block with all settings enabled

    • A.5.15 Access control — Rules to control physical and logical access to information and other associated assets shall be established and implemented based on business and information security requirements.
    • A.8.3 Information access restriction — Access to information and other associated assets shall be restricted in accordance with the established topic-specific policy on access control.
    Remediation
    Fix: Enable All Public Access Block Settings

    Create a BucketPublicAccessBlock resource with all four settings set to true:

    const myBucket = new aws.s3.Bucket("my-bucket", {
        // Bucket configuration
    });
    
    const publicAccessBlock = new aws.s3.BucketPublicAccessBlock("my-bucket-public-access-block", {
        bucket: myBucket.id,
        blockPublicAcls: true,       // Blocks new public ACLs
        blockPublicPolicy: true,     // Blocks new public bucket policies
        ignorePublicAcls: true,      // Ignores existing public ACLs
        restrictPublicBuckets: true, // Restricts public access to buckets with public policies
    });
    

    s3-bucket-replication

    Severity: medium · Enforcement: advisory

    Ensures S3 buckets have replication configured for enhanced availability

    • A.5.29 Information security during disruption — The organization shall plan how to maintain information security at an appropriate level during disruption.
    • A.8.13 Information backup — Backup copies of information, software and systems shall be maintained and regularly tested in accordance with the agreed topic-specific policy on backup.
    • A.5.30 ICT readiness for business continuity — ICT readiness shall be planned, implemented, maintained and tested based on business continuity objectives and ICT continuity requirements.
    Remediation
    Fix: Configure Replication for S3 Bucket

    Create a BucketReplicationConfig resource with an IAM role and replication rules:

    // Create destination bucket
    const destBucket = new aws.s3.Bucket("dest-bucket", {
        bucket: "my-dest-bucket",
    });
    
    // Create replication IAM role
    const replicationRole = new aws.iam.Role("replication-role", {
        assumeRolePolicy: JSON.stringify({
            Version: "2012-10-17",
            Statement: [{
                Effect: "Allow",
                Principal: { Service: "s3.amazonaws.com" },
                Action: "sts:AssumeRole",
            }],
        }),
    });
    
    // Enable versioning on source bucket (required for replication)
    const sourceBucketVersioning = new aws.s3.BucketVersioning("source-versioning", {
        bucket: sourceBucket.id,
        versioningConfiguration: { status: "Enabled" },
    });
    
    // Configure replication using BucketReplicationConfig
    const replication = new aws.s3.BucketReplicationConfig("replication", {
        bucket: sourceBucket.id,
        role: replicationRole.arn,
        rules: [{
            id: "replicate-all",
            status: "Enabled",
            destination: {
                bucket: destBucket.arn,
            },
            filter: {},
        }],
    }, { dependsOn: [sourceBucketVersioning] });
    

    s3-bucket-ssl-enforcement-required

    Severity: high · Enforcement: advisory

    S3 buckets must enforce SSL/TLS for all requests to ensure encryption in transit

    • A.5.14 Information transfer — Information transfer rules, procedures, or agreements shall be in place for all types of transfer facilities within the organization and between the organization and other parties.
    • A.8.20 Networks security — Networks and network devices shall be secured, managed and controlled to protect information in systems and applications.
    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Add Bucket Policy to Enforce SSL/TLS

    Add a bucket policy that denies all requests made without SSL/TLS encryption:

    import * as aws from "@pulumi/aws";
    
    const bucket = new aws.s3.BucketV2("my-bucket", {
        bucket: "my-secure-bucket",
    });
    
    // Add bucket policy to enforce SSL/TLS
    const bucketPolicy = new aws.s3.BucketPolicy("my-bucket-policy", {
        bucket: bucket.id,
        policy: bucket.arn.apply(arn => JSON.stringify({
            Version: "2012-10-17",
            Statement: [{
                Sid: "DenyInsecureTransport",
                Effect: "Deny",
                Principal: "*",
                Action: "s3:*",
                Resource: [
                    arn,
                    `${arn}/*`,
                ],
                Condition: {
                    Bool: {
                        "aws:SecureTransport": "false"  // Deny when SecureTransport is false
                    }
                }
            }]
        }))
    });
    

    s3-bucket-versioning

    Severity: medium · Enforcement: advisory

    S3 buckets must have versioning enabled using BucketVersioning resource

    • A.5.33 Protection of records — Records shall be protected from loss, destruction, falsification, unauthorized access and unauthorized release.
    • A.8.13 Information backup — Backup copies of information, software and systems shall be maintained and regularly tested in accordance with the agreed topic-specific policy on backup.
    Remediation
    Fix: Enable S3 Bucket Versioning

    Create a separate BucketVersioning resource with status set to “Enabled” for each S3 bucket:

    const bucket = new aws.s3.BucketV2("my-bucket", {
        bucket: "my-data-bucket",
    });
    
    const versioning = new aws.s3.BucketVersioning("my-bucket-versioning", {
        bucket: bucket.id,
        versioningConfiguration: {
            status: "Enabled", // Enable versioning for data integrity and recovery
        },
    });
    

    sagemaker-endpoint-kms-encryption-enabled

    Severity: high · Enforcement: advisory

    Ensures SageMaker endpoint configurations have encryption enabled using KMS keys.

    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Enable KMS encryption for SageMaker endpoint configuration

    Add the kmsKeyArn property to your SageMaker endpoint configuration to enable encryption at rest:

    const endpointConfig = new aws.sagemaker.EndpointConfiguration("example", {
        productionVariants: [{
            modelName: model.name,
            initialInstanceCount: 1,
            instanceType: "ml.t2.medium",
        }],
        kmsKeyArn: kmsKey.arn, // Add KMS key ARN to enable encryption at rest
    });
    

    sagemaker-notebook-internet-access-disabled

    Severity: high · Enforcement: advisory

    Ensures SageMaker notebook instances have direct internet access disabled.

    • A.5.15 Access control — Rules to control physical and logical access to information and other associated assets shall be established and implemented based on business and information security requirements.
    • A.8.3 Information access restriction — Access to information and other associated assets shall be restricted in accordance with the established topic-specific policy on access control.
    Remediation
    Fix: Disable Direct Internet Access
    const notebookInstance = new aws.sagemaker.NotebookInstance("ml-notebook", {
        instanceType: "ml.t3.medium",
        roleArn: role.arn,
        directInternetAccess: "Disabled",  // Disable direct internet access
        subnetId: subnet.id,  // Must specify subnet when internet access is disabled
        securityGroups: [securityGroup.id],  // Control network access via security groups
    });
    

    sagemaker-notebook-kms-encryption-enabled

    Severity: high · Enforcement: advisory

    Ensures SageMaker notebook instances have encryption enabled using KMS keys.

    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Enable KMS encryption for SageMaker notebook instance

    Add the kmsKeyId property to your SageMaker notebook instance configuration to enable encryption at rest:

    import * as aws from "@pulumi/aws";
    
    const notebookInstance = new aws.sagemaker.NotebookInstance("example", {
        name: "my-notebook",
        instanceType: "ml.t2.medium",
        roleArn: role.arn,
        kmsKeyId: kmsKey.id, // Add KMS key ID to enable encryption at rest
    });
    

    sagemaker-notebook-root-access

    Severity: high · Enforcement: advisory

    SageMaker notebook instances must disable root access to enforce least privilege for notebook users.

    • A.8.2 Privileged access rights — The allocation and use of privileged access rights shall be restricted and managed.
    Remediation
    Fix: Disable Root Access on the SageMaker Notebook Instance

    Set rootAccess to "Disabled" to enforce least privilege for notebook users.

    const notebook = new aws.sagemaker.NotebookInstance("my-notebook", {
        rootAccess: "Disabled",
        // ... other configuration
    });
    

    secrets-manager-rotation-required

    Severity: medium · Enforcement: advisory

    Ensures Secrets Manager secrets have automatic rotation enabled with proper scheduling and frequency limits.

    • A.5.17 Authentication information — Allocation and management of authentication information shall be controlled by a management process, including advising personnel on appropriate handling of authentication information.
    Remediation
    Fix: Enable Automatic Rotation for Secrets Manager Secret

    Configure a SecretRotation resource with rotation rules to automatically rotate your secret credentials at regular intervals.

    import * as aws from "@pulumi/aws";
    
    const mySecret = new aws.secretsmanager.Secret("mySecret", {
        name: "my-database-credentials",
    });
    
    // Create rotation configuration with Lambda function
    const rotationLambda = new aws.lambda.Function("rotationLambda", {
        // Lambda function configuration for rotation
    });
    
    // Add automatic rotation to the secret
    const secretRotation = new aws.secretsmanager.SecretRotation("mySecretRotation", {
        secretId: mySecret.id,
        rotationLambdaArn: rotationLambda.arn,
        rotationRules: {
            automaticallyAfterDays: 30, // Rotate every 30 days (must be <= configured maximum)
            // Or use scheduleExpression: "cron(0 0 1 * ? *)" for cron-based rotation
        },
    });
    

    secrets-manager-secret-configure-customer-managed-key

    Severity: low · Enforcement: advisory

    Check that Secrets Manager Secrets use a customer-manager KMS key.

    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Configure Customer-Managed KMS Key for Secrets Manager Secret

    Set the kmsKeyId property to reference a customer-managed KMS key for encrypting the secret:

    const secret = new aws.secretsmanager.Secret("my-secret", {
        name: "my-application-secret",
        kmsKeyId: kmsKey.arn, // Use customer-managed KMS key
        description: "Sensitive application credentials",
    });
    

    security-group-default-deny

    Severity: high · Enforcement: advisory

    Ensures Security Groups follow default deny with explicit allow principle

    • A.6.7 Remote working — Security measures shall be implemented when personnel are working remotely to protect information accessed, processed or stored outside the organization’s premises.
    • A.8.20 Networks security — Networks and network devices shall be secured, managed and controlled to protect information in systems and applications.
    • A.8.22 Segregation of networks — Groups of information services, users and information systems shall be segregated in the organization’s networks.
    Remediation
    Fix: Replace Unrestricted CIDR Blocks with Specific IP Ranges

    Replace 0.0.0.0/0 in ingress and egress rules with specific CIDR blocks or security group references to follow the default deny with explicit allow principle:

    const webSecurityGroup = new aws.ec2.SecurityGroup("web-sg", {
        vpcId: vpc.id,
        ingress: [{
            protocol: "tcp",
            fromPort: 443,
            toPort: 443,
            cidrBlocks: ["10.0.0.0/16"], // Use specific CIDR block instead of 0.0.0.0/0
        }],
        egress: [{
            protocol: "tcp",
            fromPort: 443,
            toPort: 443,
            cidrBlocks: ["10.0.0.0/16"], // Use specific CIDR block instead of 0.0.0.0/0
        }],
    });
    

    security-hub-enabled

    Severity: high · Enforcement: advisory

    Ensures AWS Security Hub is enabled for continuous monitoring and security assessment.

    • A.5.36 Compliance with policies, rules and standards for information security — Compliance with the organization’s information security policy, topic-specific policies, rules and standards shall be regularly reviewed.
    • A.8.16 Monitoring activities — Networks, systems and applications shall be monitored for anomalous behaviour and appropriate actions taken to evaluate potential information security incidents.
    Remediation
    Fix: Enable AWS Security Hub

    Add an AWS Security Hub Account resource to your Pulumi program to enable continuous monitoring:

    import * as aws from "@pulumi/aws";
    
    // Enable Security Hub for continuous monitoring
    const securityHub = new aws.securityhub.Account("security-hub", {
        // Security Hub will be enabled in the current region
    });
    

    sfn-statemachine-logging

    Severity: medium · Enforcement: advisory

    Step Functions state machines must have execution logging enabled.

    • A.8.15 Logging — Logs that record activities, exceptions, faults and other relevant events shall be produced, stored, protected and analysed.
    Remediation
    Fix: Enable Step Functions State Machine Logging

    Set the loggingConfiguration.level to a value other than OFF so execution history is logged to CloudWatch Logs.

    const stateMachine = new aws.sfn.StateMachine("my-state-machine", {
        roleArn: role.arn,
        definition: stateMachineDefinition,
        loggingConfiguration: {
            logDestination: `${logGroup.arn}:*`,
            level: "ALL",
        },
    });
    

    sns-kms-encryption-enabled

    Severity: high · Enforcement: advisory

    Ensures SNS topics have encryption enabled using KMS keys.

    • A.5.33 Protection of records — Records shall be protected from loss, destruction, falsification, unauthorized access and unauthorized release.
    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Enable KMS encryption for SNS topic

    Add the kmsMasterKeyId property to your SNS topic to enable encryption at rest using a KMS key.

    const myTopic = new aws.sns.Topic("myTopic", {
        name: "my-topic",
        kmsMasterKeyId: "alias/aws/sns", // Add KMS key ID or ARN for encryption
    });
    

    sqs-encryption

    Severity: high · Enforcement: advisory

    Ensures SQS queues have server-side encryption enabled

    • A.5.33 Protection of records — Records shall be protected from loss, destruction, falsification, unauthorized access and unauthorized release.
    • A.8.24 Use of cryptography — Rules for the effective use of cryptography, including cryptographic key management, shall be defined and implemented.
    Remediation
    Fix: Enable Server-Side Encryption for SQS Queue

    Set the kmsMasterKeyId property to enable server-side encryption with AWS KMS:

    const queue = new aws.sqs.Queue("my-queue", {
        name: "my-secure-queue",
        kmsMasterKeyId: "alias/aws/sqs", // Enable encryption with AWS-managed KMS key
        // Or use a customer-managed key:
        // kmsMasterKeyId: customerKey.arn,
    });
    

    ssm-document-not-public

    Severity: high · Enforcement: advisory

    SSM documents must not be shared publicly

    • A.8.20 Networks security — Networks and network devices shall be secured, managed and controlled to protect information in systems and applications.
    Remediation
    Fix: Remove Public Sharing from SSM Document

    Do not share the document with all. Share only with specific account IDs.

    new aws.ssm.Document("doc", {
        name: "my-doc",
        documentType: "Command",
        content: JSON.stringify({ schemaVersion: "2.2", mainSteps: [] }),
        permissions: {
            type: "Share",
            account_ids: "123456789012", // specific accounts, never "all"
        },
    });
    

    subnet-multi-az

    Severity: high · Enforcement: advisory

    Ensures subnets are distributed across multiple availability zones

    • A.8.14 Redundancy of information processing facilities — Information processing facilities shall be implemented with redundancy sufficient to meet availability requirements.
    • A.5.30 ICT readiness for business continuity — ICT readiness shall be planned, implemented, maintained and tested based on business continuity objectives and ICT continuity requirements.
    Remediation
    Fix: Distribute Subnets Across Multiple Availability Zones

    Create subnets in at least 2 different availability zones to ensure high availability and fault tolerance:

    const subnet1 = new aws.ec2.Subnet("subnet-az1", {
        vpcId: vpc.id,
        cidrBlock: "10.0.1.0/24",
        availabilityZone: "us-east-1a", // Specify explicit AZ
    });
    
    const subnet2 = new aws.ec2.Subnet("subnet-az2", {
        vpcId: vpc.id,
        cidrBlock: "10.0.2.0/24",
        availabilityZone: "us-east-1b", // Use different AZ for redundancy
    });
    

    vpc-endpoint-security-policy

    Severity: high · Enforcement: advisory

    Ensures that VPC endpoints are associated with security policies that limit access to specified resources

    • A.8.21 Security of network services — Security mechanisms, service levels and service requirements of network services shall be identified, implemented and monitored.
    Remediation
    Fix: Configure Restrictive VPC Endpoint Policy

    Add a policy to your VPC endpoint that specifies explicit principals and resources instead of wildcards:

    const vpcEndpoint = new aws.ec2.VpcEndpoint("my-endpoint", {
        vpcId: vpc.id,
        serviceName: "com.amazonaws.us-west-2.s3",
        policy: JSON.stringify({
            Version: "2012-10-17",
            Statement: [{
                Effect: "Allow",
                Principal: {
                    AWS: "arn:aws:iam::123456789012:role/MyRole" // Specify explicit principal ARN
                },
                Action: "s3:GetObject",
                Resource: "arn:aws:s3:::my-bucket/*" // Specify explicit resource ARN
            }]
        }),
    });
    

    vpc-nacl-no-unrestricted-ssh-rdp

    Severity: high · Enforcement: advisory

    Network ACLs must not allow unrestricted SSH/RDP ingress from the internet

    • A.8.20 Networks security — Networks and network devices shall be secured, managed and controlled to protect information in systems and applications.
    Remediation
    Fix: Remove Unrestricted SSH/RDP from Network ACL

    Remove or restrict ingress rules that allow SSH (port 22) or RDP (port 3389) from 0.0.0.0/0 or ::/0.

    new aws.ec2.NetworkAcl("acl", {
        vpcId: vpc.id,
        ingress: [{
            protocol: "tcp",
            ruleNo: 100,
            action: "allow",
            cidrBlock: "10.0.0.0/16", // restrict to a trusted network
            fromPort: 22,
            toPort: 22,
        }],
    });
    

    vpc-network-acl-unused

    Severity: medium · Enforcement: advisory

    Ensure VPC network ACLs are not unused to maintain proper network security asset management.

    • A.8.9 Configuration management — Configurations, including security configurations, of hardware, software, services and networks shall be established, documented, implemented, monitored and reviewed.
    Remediation
    Fix: Associate NetworkAcl with subnet
    const nacl = new aws.ec2.NetworkAcl("nacl", {
        subnetIds: [subnet.id],  // This fixes the violation
        // ... other required config
    });
    

    vpc-route-table-internet-gateway-restricted

    Severity: medium · Enforcement: advisory

    Ensures VPC route tables restrict public access to internet gateways appropriately.

    • A.8.20 Networks security — Networks and network devices shall be secured, managed and controlled to protect information in systems and applications.
    • A.8.22 Segregation of networks — Groups of information services, users and information systems shall be segregated in the organization’s networks.
    • A.8.21 Security of network services — Security mechanisms, service levels and service requirements of network services shall be identified, implemented and monitored.
    Remediation
    Fix: Restrict Route Table Internet Gateway Access

    Remove or restrict overly broad routes to internet gateways in your VPC route table.

    import * as aws from "@pulumi/aws";
    
    // Create route table without unrestricted internet access
    const routeTable = new aws.ec2.RouteTable("example", {
        vpcId: vpc.id,
        routes: [
            // ❌ INCORRECT: Avoid routes with 0.0.0.0/0 to internet gateway
            // {
            //     cidrBlock: "0.0.0.0/0",
            //     gatewayId: igw.id,
            // },
    
            // ✅ CORRECT: Use specific CIDR blocks or route through NAT gateway instead
            {
                cidrBlock: "10.0.0.0/8", // Private network range
                gatewayId: igw.id,
            },
            // Or use NAT gateway for controlled outbound access
            {
                cidrBlock: "0.0.0.0/0",
                natGatewayId: natGateway.id, // NAT gateway provides controlled egress
            },
        ],
    });
    

    Alternatively, exempt specific route tables from this check by configuring the policy.

    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.

    • A.8.9 Configuration management — Configurations, including security configurations, of hardware, software, services and networks shall be established, documented, implemented, monitored and reviewed.
    Remediation
    Fix: Attach security group to instance or ENI
    const instance = new aws.ec2.Instance("instance", {
        vpcSecurityGroupIds: [securityGroup.id],  // This fixes the violation
        // ... other required config
    });
    

    vpc-subnet-auto-assign-public-ip-disabled

    Severity: high · Enforcement: advisory

    Ensures VPC subnets have auto-assign public IP disabled to prevent unintended internet exposure.

    • A.5.15 Access control — Rules to control physical and logical access to information and other associated assets shall be established and implemented based on business and information security requirements.
    • A.8.3 Information access restriction — Access to information and other associated assets shall be restricted in accordance with the established topic-specific policy on access control.
    Remediation
    Fix: Disable Auto-Assign Public IP for VPC Subnets
    const subnet = new aws.ec2.Subnet("private-subnet", {
        vpcId: vpc.id,
        cidrBlock: "10.0.1.0/24",
        mapPublicIpOnLaunch: false,  // Disable auto-assign public IP to prevent unintended internet exposure
    });
    

    vpc-subnet-flow-logs

    Severity: medium · Enforcement: advisory

    Ensures all VPCs and subnets have flow logs enabled

    • A.8.15 Logging — Logs that record activities, exceptions, faults and other relevant events shall be produced, stored, protected and analysed.
    Remediation
    Fix: Enable VPC Flow Logs for Network Monitoring

    Create a VPC Flow Log resource and associate it with your VPC or subnet to capture network traffic information:

    const vpc = new aws.ec2.Vpc("my-vpc", {
        cidrBlock: "10.0.0.0/16",
    });
    
    // Enable flow logs for the VPC
    const flowLog = new aws.ec2.FlowLog("vpc-flow-log", {
        vpcId: vpc.id, // Associate flow log with VPC
        trafficType: "ALL", // Capture all traffic (ACCEPT, REJECT, ALL)
        logDestinationType: "cloud-watch-logs",
        logDestination: logGroup.arn,
        iamRoleArn: flowLogRole.arn,
    });
    

    wafv2-logging-enabled

    Severity: medium · Enforcement: advisory

    Ensures WAFv2 Web ACLs have logging configurations enabled for audit and monitoring purposes.

    • A.8.15 Logging — Logs that record activities, exceptions, faults and other relevant events shall be produced, stored, protected and analysed.
    Remediation
    Fix: Enable WAFv2 Web ACL Logging

    Create a WebAclLoggingConfiguration resource to enable logging for your WAFv2 Web ACL:

    import * as aws from "@pulumi/aws";
    
    // Create a Kinesis Data Firehose delivery stream for WAF logs
    const wafLogStream = new aws.kinesis.FirehoseDeliveryStream("waf-logs", {
        destination: "extended_s3",
        extendedS3Configuration: {
            roleArn: logRole.arn,
            bucketArn: logBucket.arn,
            prefix: "waf-logs/",
        },
    });
    
    // Enable logging for the Web ACL
    const webAclLogging = new aws.wafv2.WebAclLoggingConfiguration("web-acl-logging", {
        resourceArn: myWebAcl.arn, // Reference to your Web ACL
        logDestinationConfigs: [
            wafLogStream.arn, // Link to Kinesis Firehose stream
        ],
    });
    

    Alternatively, you can log directly to CloudWatch Logs or S3.

      The infrastructure as code platform for any cloud.