Skip to main content

S3 Logs Should Have Encryption Enabled CodeBuild Project

More Info:

This rule ensures that encryption is enabled for logs stored in Amazon S3 for an AWS CodeBuild project. Enabling encryption helps protect sensitive build logs from unauthorized access or tampering. It ensures that logs are encrypted while stored, providing an additional layer of security.

Risk Level

Medium

Address

Security

Compliance Standards

  • APRA CPS 234 (Australia)
  • AWS Startup Security Baseline
  • BSI C5 (Germany)
  • Brazil LGPD
  • CCPA / CPRA (California)
  • CIS Critical Security Controls v8
  • CMMC 2.0
  • CSA Cloud Controls Matrix v4
  • Cloudanix Best Practice
  • DPDPA
  • Digital Operational Resilience Act (EU)
  • ISO/IEC 27017
  • ISO/IEC 27018
  • ISO/IEC 27701
  • KSA PDPL
  • MAS Technology Risk Management (Singapore)
  • MITRE ATT&CK (Cloud)
  • NIST SP 800-171
  • NYDFS 23 NYCRR 500
  • Reserve Bank of India (RBI) Cyber Security Framework
  • SWIFT Customer Security Controls Framework
  • Sarbanes-Oxley IT General Controls
  • Securities and Exchange Board of India (SEBI) - Cloud Security Adoption Framework
  • UK NCSC Cyber Assessment Framework

Triage and Remediation

Remediation

Using Console

To remediate “S3 Logs Should Have Encryption Enabled” for an AWS CodeBuild project via the AWS Console, you need to:

  1. Ensure the S3 bucket used for CodeBuild logs has default encryption enabled
  2. Ensure the CodeBuild project logging configuration uses that bucket (and, optionally, a KMS key)

1. Identify the S3 bucket used for CodeBuild logs

  1. Go to AWS ConsoleCodeBuild.
  2. In the left menu, click Build projects.
  3. Click on your CodeBuild project.
  4. Go to the Build details page → click Edit.
  5. Scroll down to the Logs section.
  6. Under S3 logs, note:
    • Whether S3 logging is Enabled.
    • The S3 bucket name and path prefix (this is the bucket you will configure).

If S3 logs are Disabled, turn them On and specify the desired S3 bucket. Then continue.


2. Enable encryption on the S3 bucket

  1. Go to S3 in the AWS Console.
  2. Click on the bucket identified in step 1.
  3. Go to the Properties tab.
  4. Scroll to Default encryption and click Edit.
  5. Turn Enable on.
  6. Choose one:
    • Server-side encryption with Amazon S3-managed keys (SSE-S3)
      • Simple and usually sufficient: select AES-256 (SSE-S3).
    • Server-side encryption with AWS KMS keys (SSE-KMS)
      • Choose AWS managed key or a customer managed KMS key.
  7. Click Save changes.

This ensures all new objects (including CodeBuild logs) written to this bucket are encrypted.


3. (Optional) Ensure CodeBuild log config is consistent with KMS usage

If you chose SSE-KMS:

  1. Stay in the S3 bucket’s Permissions tab.
  2. Make sure the KMS key policy allows CodeBuild and any IAM roles used by CodeBuild to use the key (kms:Encrypt, kms:Decrypt, kms:GenerateDataKey, kms:DescribeKey as needed).
  3. If you used a customer managed key, go to AWS KMSCustomer managed keys → select the key:
    • Under Key policy, ensure the CodeBuild service role is allowed to use the key.

4. Confirm/adjust CodeBuild project logging settings

  1. Go back to CodeBuildBuild projects → select your project.
  2. Click Edit.
  3. In the Logs section:
    • Under S3 logs, ensure Enabled is selected.
    • Verify the S3 bucket is the encrypted one you configured.
    • Optionally set S3 log prefix for organization.
  4. Click Update artifacts / Update / Save at the bottom (exact text may vary).

5. Validate

  1. Trigger a new build for that project.
  2. Go to the S3 bucketObjects.
  3. Open a recent log object → under Properties, confirm:
    • Server-side encryption is shown (either SSE-S3 or SSE-KMS with the selected key).

Your CodeBuild S3 logs are now encrypted, satisfying the “S3 Logs Should Have Encryption Enabled” requirement.

Using CLI

To fix “S3 Logs Should Have Encryption Enabled” for an AWS CodeBuild project via AWS CLI, you must update the project’s logsConfig.s3Logs to have encryptionDisabled=false (or omit it) and ensure the S3 bucket is encrypted.

Below are minimal step‑by‑step CLI instructions.


1. Identify the CodeBuild project and inspect its log config

aws codebuild batch-get-projects \
--names MyCodeBuildProject \
--query 'projects[0].logsConfig.s3Logs'

Check if you see encryptionDisabled: true.


If your log bucket isn’t already encrypted, turn on default SSE-S3 or SSE-KMS.

SSE-S3 (S3-managed keys):

aws s3api put-bucket-encryption \
--bucket my-codebuild-logs-bucket \
--server-side-encryption-configuration '{
"Rules": [
{
"ApplyServerSideEncryptionByDefault": {
"SSEAlgorithm": "AES256"
}
}
]
}'

SSE-KMS (customer-managed KMS key):

aws s3api put-bucket-encryption \
--bucket my-codebuild-logs-bucket \
--server-side-encryption-configuration '{
"Rules": [
{
"ApplyServerSideEncryptionByDefault": {
"SSEAlgorithm": "aws:kms",
"KMSMasterKeyID": "arn:aws:kms:us-east-1:111122223333:key/your-kms-key-id"
}
}
]
}'

3. Get the full current project definition

You must provide the full project configuration to update-project, not just the logs.

aws codebuild batch-get-projects \
--names MyCodeBuildProject \
--query 'projects[0]' \
--output json > project.json

4. Edit project.json to fix logsConfig.s3Logs

In project.json, find logsConfig.s3Logs and set:

"logsConfig": {
"cloudWatchLogs": {
"status": "DISABLED"
},
"s3Logs": {
"status": "ENABLED",
"location": "my-codebuild-logs-bucket/my-logs-prefix",
"encryptionDisabled": false
}
}

Notes:

  • status must be "ENABLED".
  • location is bucket-name[/optional/prefix].
  • encryptionDisabled: false (or remove the field) ensures encryption is enabled. CodeBuild will use SSE-S3 for objects it writes; the bucket policy/encryption settings will enforce SSE-S3 or SSE-KMS as configured.

Do not change other fields unless needed.


5. Update the project using the modified JSON

aws codebuild update-project \
--cli-input-json file://project.json

6. Verify the change

aws codebuild batch-get-projects \
--names MyCodeBuildProject \
--query 'projects[0].logsConfig.s3Logs'

You should now see "status": "ENABLED" and either no encryptionDisabled field or encryptionDisabled: false. The S3 bucket should also show encryption configuration via:

aws s3api get-bucket-encryption \
--bucket my-codebuild-logs-bucket
Using Python

To fix this for an AWS CodeBuild project using Python/boto3 you need to do two things:

  1. Ensure the S3 bucket used for CodeBuild logs has encryption enabled
  2. Ensure the CodeBuild project is configured to use encrypted S3 logs (i.e., encryptionDisabled=False)

Below are step‑by‑step instructions and an example Python remediation script.


1. Identify the CodeBuild project and its S3 log settings

First, find the project and its current S3 log configuration.

import boto3

codebuild = boto3.client('codebuild')

project_name = "YOUR_CODEBUILD_PROJECT_NAME"

response = codebuild.batch_get_projects(names=[project_name])
project = response['projects'][0]

print(project.get('logsConfig', {}))

Look for:

"logsConfig": {
"s3Logs": {
"status": "ENABLED",
"location": "your-logs-bucket/path",
"encryptionDisabled": false,
"bucketOwnerAccess": "FULL"
},
"cloudWatchLogs": { ... }
}

You need:

  • "status": "ENABLED"
  • "encryptionDisabled": false (or omitted; default is encrypted if bucket has default SSE)
  • The location bucket to have default SSE.

2. Enable default encryption on the S3 bucket used for logs

If the S3 bucket doesn’t have default encryption, enable it (SSE-S3 or SSE-KMS).

import boto3
from urllib.parse import urlparse

s3 = boto3.client('s3')

# Extract bucket name from the "location" field, e.g. "my-logs-bucket/logs/path"
location = project.get('logsConfig', {}).get('s3Logs', {}).get('location')
bucket_name = location.split('/', 1)[0] if location else "YOUR_LOGS_BUCKET"

# Option A: SSE-S3 (AES256) - simplest
s3.put_bucket_encryption(
Bucket=bucket_name,
ServerSideEncryptionConfiguration={
'Rules': [{
'ApplyServerSideEncryptionByDefault': {
'SSEAlgorithm': 'AES256'
}
}]
}
)

# Option B (optional): SSE-KMS (if you want a specific KMS key)
# kms_key_arn = "arn:aws:kms:REGION:ACCOUNT:key/KEY_ID"
# s3.put_bucket_encryption(
# Bucket=bucket_name,
# ServerSideEncryptionConfiguration={
# 'Rules': [{
# 'ApplyServerSideEncryptionByDefault': {
# 'SSEAlgorithm': 'aws:kms',
# 'KMSMasterKeyID': kms_key_arn
# }
# }]
# }
# )

This ensures that all new objects, including CodeBuild logs, are encrypted by default.


3. Ensure CodeBuild S3 logs are enabled and not marked as unencrypted

You now need to update the CodeBuild project so that:

  • S3 logs are ENABLED
  • encryptionDisabled is False or omitted

The update_project API requires you to send a mostly complete project definition. The simplest way is:

  1. Get existing project definition
  2. Modify it
  3. Call update_project
import copy
import boto3

codebuild = boto3.client('codebuild')
project_name = "YOUR_CODEBUILD_PROJECT_NAME"

# 1. Get the existing project
resp = codebuild.batch_get_projects(names=[project_name])
project = resp['projects'][0]

# 2. Build the update payload from the existing project
update_args = {
'name': project['name'],
'description': project.get('description'),
'source': project['source'],
'artifacts': project['artifacts'],
'environment': project['environment'],
'serviceRole': project['serviceRole'],
'timeoutInMinutes': project.get('timeoutInMinutes'),
'queuedTimeoutInMinutes': project.get('queuedTimeoutInMinutes'),
'encryptionKey': project.get('encryptionKey'),
'tags': project.get('tags'),
'vpcConfig': project.get('vpcConfig'),
'badgeEnabled': project.get('badgeEnabled'),
'logsConfig': project.get('logsConfig', {}),
'fileSystemLocations': project.get('fileSystemLocations'),
'buildBatchConfig': project.get('buildBatchConfig'),
'concurrentBuildLimit': project.get('concurrentBuildLimit'),
'cache': project.get('cache'),
'secondarySources': project.get('secondarySources'),
'secondaryArtifacts': project.get('secondaryArtifacts'),
'sourceVersion': project.get('sourceVersion'),
}

# Clean out any None values (CodeBuild API doesn’t like explicit None)
update_args = {k: v for k, v in update_args.items() if v is not None}

# 3. Adjust S3 logs config
logs_config = update_args.get('logsConfig', {})

# Make sure s3Logs is defined
s3_logs = logs_config.get('s3Logs', {})
s3_logs['status'] = 'ENABLED'
# Use same bucket; if you want a path, include "/logs/" etc.
s3_logs['location'] = bucket_name
s3_logs['encryptionDisabled'] = False # explicitly enforce encryption

logs_config['s3Logs'] = s3_logs
update_args['logsConfig'] = logs_config

# 4. Update the project
codebuild.update_project(**update_args)
print("Updated CodeBuild project to use encrypted S3 logs.")

4. (Optional) Simple remediation script that just sets S3 log encryption

If you only want a focused script that:

  • Takes a project name and bucket
  • Ensures bucket encryption
  • Enables S3 logs with encryption
import boto3

def remediate_codebuild_s3_logs(project_name, bucket_name, region=None):
session = boto3.Session(region_name=region)
codebuild = session.client('codebuild')
s3 = session.client('s3')

# 1) Enable default encryption on bucket
s3.put_bucket_encryption(
Bucket=bucket_name,
ServerSideEncryptionConfiguration={
'Rules': [{
'ApplyServerSideEncryptionByDefault': {
'SSEAlgorithm': 'AES256'
}
}]
}
)

# 2) Get existing project
resp = codebuild.batch_get_projects(names=[project_name])
if not resp['projects']:
raise ValueError(f"Project {project_name} not found")
project = resp['projects'][0]

# 3) Build update payload
update_args = {
'name': project['name'],
'source': project['source'],
'artifacts': project['artifacts'],
'environment': project['environment'],
'serviceRole': project['serviceRole'],
}

# Include optional fields if present
optional_fields = [
'description','timeoutInMinutes','queuedTimeoutInMinutes','encryptionKey',
'tags','vpcConfig','badgeEnabled','logsConfig','fileSystemLocations',
'buildBatchConfig','concurrentBuildLimit','cache',
'secondarySources','secondaryArtifacts','sourceVersion'
]
for f in optional_fields:
if f in project:
update_args[f] = project[f]

# Ensure S3 logs are enabled and encrypted
logs_config = update_args.get('logsConfig', {})
s3_logs = logs_config.get('s3Logs', {})
s3_logs['status'] = 'ENABLED'
s3_logs['location'] = bucket_name
s3_logs['encryptionDisabled'] = False
logs_config['s3Logs'] = s3_logs
update_args['logsConfig'] = logs_config

codebuild.update_project(**update_args)
print(f"Remediated S3 logs for project {project_name} with encrypted bucket {bucket_name}")

# Example usage
# remediate_codebuild_s3_logs("my-codebuild-project", "my-logs-bucket", region="us-east-1")

This aligns with the “S3 logs should have encryption enabled” control: logs are stored in an S3 bucket with default SSE, and the CodeBuild project is configured not to disable encryption.

Using Terraform
resource "aws_codebuild_project" "THIS_PROJECT" {
name = "CODEBUILD_PROJECT_NAME" # replace with your project name
service_role = "CODEBUILD_SERVICE_ROLE_ARN"
artifacts {
type = "NO_ARTIFACTS"
}
environment {
compute_type = "BUILD_GENERAL1_SMALL"
image = "aws/codebuild/standard:7.0"
type = "LINUX_CONTAINER"
privileged_mode = false
}
source {
type = "GITHUB"
location = "GITHUB_REPO_URL"
git_clone_depth = 1
}

# Ensure S3 logs have encryption enabled
logs_config {
s3_logs {
status = "ENABLED"
location = "S3_BUCKET_NAME/OPTIONAL_PREFIX" # e.g. "my-logs-bucket/codebuild"
encryption_disabled = false
}

# If you also use CloudWatch logs, keep them here so they are not removed
cloudwatch_logs {
status = "ENABLED"
group_name = "CLOUDWATCH_LOG_GROUP_NAME"
stream_name = "CLOUDWATCH_LOG_STREAM_NAME"
}
}
}

This change does not replace the CodeBuild project; it updates the logs configuration in place, but note that logs_config is managed as a whole, so any existing CloudWatch/S3 log settings must be represented in this block or Terraform will remove them.

To verify, terraform plan should show an in-place update (~) to aws_codebuild_project.THIS_PROJECT.logs_config.s3_logs.encryption_disabled changing from true (or null) to false (and any other log settings you added/updated).

Additional Reading: