Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/python-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@ jobs:
python-version: "3.13"
- name: Run Agentless API Call unit tests
run: |
cd aws_quickstart
cd aws_agentless
python -B -S -m unittest datadog_agentless_api_call_test.py -v
38 changes: 38 additions & 0 deletions aws_agentless/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Datadog Agentless Scanning CloudFormation Templates

This directory contains CloudFormation templates for deploying Datadog Agentless Scanning in AWS accounts.

Datadog Agentless Scanning enables vulnerability scanning of your AWS resources (hosts, containers, Lambda functions, and sensitive data in S3 buckets) without requiring the installation of agents.

## Templates

- **`datadog_agentless_scanning.yaml`**: Main template for deploying the complete Agentless Scanner infrastructure, including EC2 instances, Auto Scaling Groups, IAM roles, and optional VPC resources.
- **`datadog_agentless_delegate_role.yaml`**: Template for creating a delegate role that allows the Agentless Scanner from one account to scan resources in another account (cross-account scanning).
- **`datadog_agentless_delegate_role_snapshot.yaml`**: Template that extends an existing delegate role with permissions to copy snapshots across regions.
- **`datadog_agentless_api_call.py`**: Python Lambda function that registers the Agentless Scanning features with the Datadog API.
- **`datadog_agentless_api_call_test.py`**: Unit tests for the API call Lambda function.

## Release Process

**Important:** These templates must be released to the `datadog-cloudformation-template` S3 bucket before they can be used by customers.

### Releasing a New Version

1. Update the version in `version.txt`
2. Run the release script:
```bash
./release.sh <S3_BUCKET_NAME>
```
Example:
```bash
./release.sh datadog-cloudformation-template
```

The release script will automatically:
- Update the pinned agentless version in `aws_quickstart/main_extended.yaml` to match the new version
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is outdated after your latest changes—as is the agentless release script.

- Validate that the version doesn't already exist in S3
- Replace version placeholders in templates
- Inject the Python Lambda code into the YAML templates
- Upload templates to `s3://<S3_BUCKET_NAME>/aws_agentless/<VERSION>/`

**Note:** After running the release script, you must commit both the agentless templates AND the updated `aws_quickstart/main_extended.yaml` file to ensure version consistency.
Original file line number Diff line number Diff line change
Expand Up @@ -198,3 +198,4 @@ def timeout_handler(_signal, _frame):


signal.signal(signal.SIGALRM, timeout_handler)

Original file line number Diff line number Diff line change
Expand Up @@ -246,3 +246,4 @@ def test_other_error_raises_exception(self, mock_urlopen):

if __name__ == "__main__":
unittest.main()

Original file line number Diff line number Diff line change
Expand Up @@ -360,3 +360,4 @@ Metadata:
Parameters:
- AgentlessSensitiveDataScanning
- AccountId

Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,4 @@ Resources:
'aws:TagKeys': DatadogAgentlessScanner*
StringEquals:
'aws:RequestTag/DatadogAgentlessScanner': 'true'

Original file line number Diff line number Diff line change
Expand Up @@ -1131,3 +1131,4 @@ Metadata:
default: "AgentlessLambdaScanning *"
AgentlessSensitiveDataScanning:
default: "AgentlessSensitiveDataScanning *"

104 changes: 104 additions & 0 deletions aws_agentless/release.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
#!/bin/bash

# Usage: ./release.sh <S3_Bucket>

set -e

# Read the S3 bucket
if [ -z "$1" ]; then
echo "Must specify a S3 bucket to publish the template"
exit 1
else
BUCKET=$1
fi

# Read the version
VERSION=$(head -n 1 version.txt)

# Update the pinned version in aws_quickstart/main_extended.yaml
MAIN_EXTENDED_PATH="../aws_quickstart/main_extended.yaml"
if [ -f "$MAIN_EXTENDED_PATH" ]; then
echo "⚠️ Checking if we need to update pinned agentless version in aws_quickstart/main_extended.yaml to ${VERSION}"
# Check if the version is already set in main_extended.yaml
if grep -q "aws_agentless/${VERSION}/" "$MAIN_EXTENDED_PATH"; then
echo "✓ Version ${VERSION} is already pinned in main_extended.yaml"
else
# Update both TemplateURL lines that reference aws_agentless versions
sed -i.bak -E "s|(https://datadog-cloudformation-template\.s3\.amazonaws\.com/aws_agentless/)v[0-9]+\.[0-9]+\.[0-9]+/|\1${VERSION}/|g" "$MAIN_EXTENDED_PATH"
if [ -f "${MAIN_EXTENDED_PATH}.bak" ]; then
echo "✓ Updated pinned version in main_extended.yaml (backup saved as main_extended.yaml.bak)"
echo " Please review and commit this change along with the agentless templates"
# Clean up backup file after informing user
rm "${MAIN_EXTENDED_PATH}.bak"
fi
fi
else
echo "⚠️ WARNING: Could not find ${MAIN_EXTENDED_PATH} - skipping version pin update"
fi
echo ""

# Confirm the bucket for the current release doesn't already exist so we don't overwrite it
set +e
EXIT_CODE=0
response=$(aws s3api head-object \
--bucket "${BUCKET}" \
--key "aws_agentless/${VERSION}/datadog_agentless_scanning.yaml" > /dev/null 2>&1)

if [[ ${?} -eq 0 ]]; then
echo "S3 bucket path ${BUCKET}/aws_agentless/${VERSION} already exists. Please up the version."
exit 1
fi
set -e

# Upload templates to a private bucket -- useful for testing
if [[ $# -eq 2 ]] && [[ $2 = "--private" ]]; then
PRIVATE_TEMPLATE=true
else
PRIVATE_TEMPLATE=false
fi

# Confirm to proceed
for i in *.yaml; do
[ -f "$i" ] || break
echo "About to upload $i to s3://${BUCKET}/aws_agentless/${VERSION}/$i"
done
read -p "Continue (y/n)?" CONT
if [ "$CONT" != "y" ]; then
echo "Exiting"
exit 1
fi

# Process Agentless Scanning templates
for template in datadog_agentless_delegate_role.yaml datadog_agentless_scanning.yaml datadog_agentless_delegate_role_snapshot.yaml; do
# Note: unlike main templates, here we remove the 'v' prefix from the version
perl -i.bak -pe "s/<VERSION_PLACEHOLDER>/${VERSION#v}/g" "$template"

# Replace ZIPFILE_PLACEHOLDER with the contents of the Python file
perl -i -pe '
# Read the Python script from stdin
BEGIN { $p = do { local $/; <STDIN> } }
# Find the placeholder and capture its indentation
/^(\s+)<ZIPFILE_PLACEHOLDER>/ && (
# Replace with the Python script, preserving the indentation
$_ = join("\n", map { $1 . $_ } split(/\n/, $p)) . "\n"
)
' "$template" < datadog_agentless_api_call.py
done

trap 'mv datadog_agentless_scanning.yaml.bak datadog_agentless_scanning.yaml;
mv datadog_agentless_delegate_role.yaml.bak datadog_agentless_delegate_role.yaml;
mv datadog_agentless_delegate_role_snapshot.yaml.bak datadog_agentless_delegate_role_snapshot.yaml;
' EXIT

# Upload
if [ "$PRIVATE_TEMPLATE" = true ] ; then
aws s3 cp . s3://${BUCKET}/aws_agentless/${VERSION} --recursive --exclude "*" --include "*.yaml"
else
aws s3 cp . s3://${BUCKET}/aws_agentless/${VERSION} --recursive --exclude "*" --include "*.yaml" \
--grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers
fi
echo "Done uploading the agentless templates, and here is the CloudFormation quick launch URL"
echo "https://console.aws.amazon.com/cloudformation/home#/stacks/create/review?stackName=datadog-agentless-scanning&templateURL=https://${BUCKET}.s3.amazonaws.com/aws_agentless/${VERSION}/datadog_agentless_scanning.yaml"

echo "Done!"

1 change: 1 addition & 0 deletions aws_agentless/version.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
v5.0.0
4 changes: 2 additions & 2 deletions aws_quickstart/main_extended.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -222,8 +222,8 @@ Resources:
Properties:
TemplateURL: !If
- IsCrossAccountScanning
- 'https://<BUCKET_PLACEHOLDER>.s3.amazonaws.com/aws/<VERSION_PLACEHOLDER>/datadog_agentless_delegate_role.yaml'
- 'https://<BUCKET_PLACEHOLDER>.s3.amazonaws.com/aws/<VERSION_PLACEHOLDER>/datadog_agentless_scanning.yaml'
- 'https://datadog-cloudformation-template.s3.amazonaws.com/aws_agentless/<AGENTLESS_VERSION_PLACEHOLDER>/datadog_agentless_delegate_role.yaml'
- 'https://datadog-cloudformation-template.s3.amazonaws.com/aws_agentless/<AGENTLESS_VERSION_PLACEHOLDER>/datadog_agentless_scanning.yaml'
Parameters:
DatadogAPIKey: !Ref APIKey
DatadogAPPKey: !Ref APPKey
Expand Down
24 changes: 4 additions & 20 deletions aws_quickstart/release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ fi
# Read the version
VERSION=$(head -n 1 version.txt)

# Read the agentless version
AGENTLESS_VERSION=$(head -n 1 ../aws_agentless/version.txt)

# Confirm the bucket for the current release doesn't already exist so we don't overwrite it
set +e
EXIT_CODE=0
Expand Down Expand Up @@ -54,29 +57,10 @@ perl -pi -e "s/<VERSION_PLACEHOLDER>/${VERSION}/g" main_v2.yaml
cp main_extended.yaml main_extended.yaml.bak
perl -pi -e "s/<BUCKET_PLACEHOLDER>/${BUCKET}/g" main_extended.yaml
perl -pi -e "s/<VERSION_PLACEHOLDER>/${VERSION}/g" main_extended.yaml

# Process Agentless Scanning templates
for template in datadog_agentless_delegate_role.yaml datadog_agentless_scanning.yaml datadog_agentless_delegate_role_snapshot.yaml; do
# Note: unlike above, here we remove the 'v' prefix from the version
perl -i.bak -pe "s/<VERSION_PLACEHOLDER>/${VERSION#v}/g" "$template"

# Replace ZIPFILE_PLACEHOLDER with the contents of the Python file
perl -i -pe '
# Read the Python script from stdin
BEGIN { $p = do { local $/; <STDIN> } }
# Find the placeholder and capture its indentation
/^(\s+)<ZIPFILE_PLACEHOLDER>/ && (
# Replace with the Python script, preserving the indentation
$_ = join("\n", map { $1 . $_ } split(/\n/, $p)) . "\n"
)
' "$template" < datadog_agentless_api_call.py
done
perl -pi -e "s/<AGENTLESS_VERSION_PLACEHOLDER>/${AGENTLESS_VERSION}/g" main_extended.yaml

trap 'mv main_v2.yaml.bak main_v2.yaml;
mv main_extended.yaml.bak main_extended.yaml;
mv datadog_agentless_scanning.yaml.bak datadog_agentless_scanning.yaml;
mv datadog_agentless_delegate_role.yaml.bak datadog_agentless_delegate_role.yaml;
mv datadog_agentless_delegate_role_snapshot.yaml.bak datadog_agentless_delegate_role_snapshot.yaml;
' EXIT

# Upload
Expand Down
2 changes: 1 addition & 1 deletion aws_quickstart/version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v4.1.5
v4.1.6
Loading