Skip to content

aws-resource-logging-off

Ensure that the resource has some form of audit logging enabled to help with forensics

Access / audit / activity logs are a critical requirement for tracking unauthorized access when investigating security incidents.

This rule currently applies to the following list of resources and because logging configuration is specific to each resource type, we provide you the link to the relevant documentation regarding logging configuration.

Supported services

API Gateway Stage

Secure examples

resource "aws_api_gateway_stage" "demo" {
    rest_api_id     = "${var.api_id}"
    stage_name      = "some-stage-name"
    deployment_id   = "${aws_api_gateway_deployment.apiDeployment.id}"
    description     = "Stage demo"
    access_log_settings {
        destination_arn     = "${module.api_stage_log_group.arn}"
        format              = "$context.error.message,$context.error.messageString,$context.identity.sourceIp,$context.identity.caller,$context.identity.user,$context.requestTime,$context.httpMethod,$context.resourcePath,$context.protocol,$context.status,$context.responseLength,$context.requestId"
    }
}
AWSTemplateFormatVersion: "2010-09-09"
Resources:
MyStage:
    Type: AWS::ApiGateway::Stage
    Properties:
    StageName: Prod
    Description: Prod Stage
    RestApiId: MyRestApi
    DeploymentId: TestDeployment
    DocumentationVersion: MyDocumentationVersion
    ClientCertificateId: ClientCertificate
    Variables:
        Stack: Prod
    AccessLogSetting:
        DestinationArn: 'arn:aws:logs:us-east-1:123456789:log-group:my-log-group'
        Format: >-
        {"requestId":"$context.requestId", "ip": "$context.identity.sourceIp",
        "caller":"$context.identity.caller",
        "user":"$context.identity.user","requestTime":"$context.requestTime",
        "eventType":"$context.eventType","routeKey":"$context.routeKey",
        "status":"$context.status","connectionId":"$context.connectionId"}
    MethodSettings:
        - ResourcePath: /
        HttpMethod: GET
        MetricsEnabled: true
        DataTraceEnabled: false
        - ResourcePath: /stack
        HttpMethod: POST
        MetricsEnabled: true
        DataTraceEnabled: false
        ThrottlingBurstLimit: 999
        - ResourcePath: /stack
        HttpMethod: GET
        MetricsEnabled: true
        DataTraceEnabled: false
        ThrottlingBurstLimit: 555

More information

ALB / ELBv2

Secure examples

resource "aws_lb" "test" {
    name               = "test-lb-tf"
    internal           = false
    load_balancer_type = "application"
    security_groups    = [aws_security_group.lb_sg.id]
    subnets            = aws_subnet.public.*.id

    access_logs {
        bucket  = aws_s3_bucket.lb_logs.bucket
        prefix  = "test-lb"
        enabled = true
    }
}
AWSTemplateFormatVersion: 2010-09-09
Resources:
    Resource0:
        Type: 'AWS::ElasticLoadBalancingV2::LoadBalancer'
        Properties:
        Name: MyLB
        LoadBalancerAttributes:
        - Key: access_logs.s3.enabled
            Value: "true"
        - Key: access_logs.s3.bucket 
            Value: MyBucket
        Subnets:
        - SubnetID0
        - SubnetID1

More information

Classic LB (ELBv1)

Secure examples

resource "aws_lb" "test" {
    name               = "test-lb-tf"
    internal           = false
    load_balancer_type = "application"
    security_groups    = [aws_security_group.lb_sg.id]
    subnets            = aws_subnet.public.*.id

    access_logs {
        bucket  = aws_s3_bucket.lb_logs.bucket
        prefix  = "test-lb"
        enabled = true
    }
}
Resources:
    LoadBalancer:
        Type: AWS::ElasticLoadBalancingV2::LoadBalancer
        Properties:
            Name: "my-alb"
            Type: application
            Scheme: internet-facing
            SecurityGroups:
                * !Ref SecurityGroup
            Subnets: !Ref Subnets
            LoadBalancerAttributes:
                * Key: access_logs.s3.enabled
                  Value: true
                * Key: access_logs.s3.prefix
                  Value: "my-access-logs"
                * Key: access_logs.s3.bucket
                  Value: !Ref AccessLogBucket

More information

DocsDB

Secure examples

resource "aws_docdb_cluster" "docdb_audit_logging_enabled" {
    cluster_identifier      = "another-cluster"
    engine                  = "docdb"
    master_username         = "admin"
    master_password         = "unsafe-pass"
    backup_retention_period = 5
    preferred_backup_window = "07:00-09:00"
    skip_final_snapshot     = true

    enabled_cloudwatch_logs_exports = ["audit"]
}
AWSTemplateFormatVersion: "2010-09-09"
Resources:
    DocDBEnabled:
        Type: AWS::DocDB::DBCluster
        Properties:
            MasterUsername: name
            MasterUserPassword: password
            StorageEncrypted: true
            EnableCloudwatchLogsExports: ["audit", "profiler"]

More information

Elasticsearch

Secure examples

resource "aws_elasticsearch_domain" "example" {
    # .. other configuration ...

    log_publishing_options {
        cloudwatch_log_group_arn = aws_cloudwatch_log_group.example.arn
        log_type                 = "AUDIT_LOGS"
    }
}
AWSTemplateFormatVersion: 2010-09-09
Resources:
    ElasticsearchDomain:
        Type: AWS::Elasticsearch::Domain
        Properties:
            ElasticsearchVersion: !Ref ElasticsearchVersion
            DomainName: !Ref ElasticsearchName
            ...
            LogPublishingOption:
                CloudWatchLogsLogGroupArn: "some-cloudwatch-arn"
                Enabled: true

More information

EKS

Secure examples

resource "aws_eks_cluster" "example" {
    name                      = var.cluster_name
    # ... other configuration ...

    depends_on = [aws_cloudwatch_log_group.example]
    enabled_cluster_log_types = ["api", "audit"]
}

resource "aws_cloudwatch_log_group" "example" {
    # The log group name format is /aws/eks/<cluster-name>/cluster
    # Reference: https://docs.aws.amazon.com/eks/latest/userguide/control-plane-logs.html
    name              = "/aws/eks/${var.cluster_name}/cluster"
    retention_in_days = 7

    # ... potentially other configuration ...
}

More information

MSK

Secure examples

resource "aws_msk_cluster" "example" {
    cluster_name           = "example"
    kafka_version          = "2.4.1"
    number_of_broker_nodes = 3

    # Other configs...

    logging_info {
        broker_logs {
            s3 {
                enabled = true
                bucket  = aws_s3_bucket.bucket.id
                prefix  = "logs/msk-"
            }
        }
    }
}
AWSTemplateFormatVersion: "2010-09-09"
Description: MSK Cluster with required properties.
Resources:
    TestCluster7:
        Type: 'AWS::MSK::Cluster'
        Properties:
            ClusterName: ClusterWithRequiredProperties
            KafkaVersion: 2.2.1
            LoggingInfo:
                BrokerLogs:
                    S3:
                        Enabled: false
                        Prefix: "logs/msk-"
                        Bucket: "bucket-arn"

More information

MQ

Secure examples

resource "aws_mq_broker" "some-broker" {
    # ... Other configs
    logs {
        general = var.general_log
        audit   = var.audit_log
    }
}

More information

Neptune cluster

Secure examples

resource "aws_neptune_cluster" "some-cluster" {
    # Other configs...
    enable_cloudwatch_logs_exports      = ["audit"]
}
AWSTemplateFormatVersion: 2010-09-09
Resources:
    NeptuneDBClusterEmpty:
        Type: "AWS::Neptune::DBCluster"
        Properties:
            DBClusterIdentifier: DBClusterIdentifier
            EnableCloudwatchLogsExports: ["audit"]

More information

RDS

Secure examples

resource "aws_db_instance" "mysql" {
    allocated_storage = 5
    engine            = "mysql"
    instance_class    = "db.t3.small"
    password          = "mysql"
    username          = "mysql"

    enabled_cloudwatch_logs_exports = ["error", "audit"]
}
AWSTemplateFormatVersion: 2010-09-09
Resources:
    RDSCluster:
        Type: 'AWS::RDS::DBCluster'
        Properties:
            MasterUsername: !Ref DBUsername
            MasterUserPassword: !Ref DBPassword
            DBClusterIdentifier: aurora-postgresql-cluster
            Engine: aurora-postgresql
            EngineVersion: '10.7'
            DBClusterParameterGroupName: default.aurora-postgresql10
            EnableCloudwatchLogsExports:
                - postgresql

More information

Redshift

Secure examples

resource "aws_redshift_cluster" "some-db" {
    cluster_identifier = "some-db"
    database_name      = "mydb"
    master_username    = "foo"
    master_password    = "some-pass"
    node_type          = "dc1.large"
    cluster_type       = "single-node"
    encrypted = true
    logging {
        enable = true
    }
}
AWSTemplateFormatVersion: 2010-09-09
Resources:
    RedshiftCluster:
        Type: AWS::Redshift::Cluster
        Properties:
            LoggingProperties:
                BucketName: "Some bucket name"

More information