From 2425ab173a227658c4f4461671046b3ddbc85d5c Mon Sep 17 00:00:00 2001 From: Moez Ezzeddine Date: Tue, 2 Jun 2026 17:27:54 +0200 Subject: [PATCH 1/6] feat(aws_quickstart): add datadog_agentless_delegate_role_saas.yaml for SaaS-mode Agentless Scanning Co-Authored-By: Claude Sonnet 4.6 --- aws_quickstart/CHANGELOG.md | 4 + .../datadog_agentless_delegate_role_saas.yaml | 377 ++++++++++++++++++ aws_quickstart/release.sh | 2 +- 3 files changed, 382 insertions(+), 1 deletion(-) create mode 100644 aws_quickstart/datadog_agentless_delegate_role_saas.yaml diff --git a/aws_quickstart/CHANGELOG.md b/aws_quickstart/CHANGELOG.md index c5b31e76..fab2cc6a 100644 --- a/aws_quickstart/CHANGELOG.md +++ b/aws_quickstart/CHANGELOG.md @@ -1,3 +1,7 @@ +# 4.14.0 (June 2, 2026) + +- Add `datadog_agentless_delegate_role_saas.yaml` for SaaS-mode Agentless Scanning. The template provisions only the `DatadogAgentlessScannerDelegateRole` and its three managed policies (Orchestrator, Worker, DSPM) — no scanner EC2/VPC/ASG resources. The delegate role's trust policy is keyed on the local Datadog integration role (default `DatadogIntegrationRole`), so Datadog assumes the integration role and chains into the delegate role to perform agentless scans. `SecurityAudit` is unconditionally attached to the integration role. `DatadogIntegrationRoleName` is required (defaults to `DatadogIntegrationRole`). Released alongside an entry added to `release.sh` so the new template participates in the standard placeholder substitution and upload pipeline. + # 4.13.0 (May 29, 2026) - Add `uk1.datadoghq.com` site support. Affects `main_v2.yaml`, `main_workflow.yaml`, `main_extended.yaml`, and `main_extended_workflow.yaml`. diff --git a/aws_quickstart/datadog_agentless_delegate_role_saas.yaml b/aws_quickstart/datadog_agentless_delegate_role_saas.yaml new file mode 100644 index 00000000..f5e5a6b7 --- /dev/null +++ b/aws_quickstart/datadog_agentless_delegate_role_saas.yaml @@ -0,0 +1,377 @@ +# version: v +AWSTemplateFormatVersion: '2010-09-09' +Description: Creates a Datadog Agentless Scanning delegate role for SaaS-mode deployments (no scanner infrastructure; trusted by the local Datadog integration role). +Parameters: + AccountId: + Type: String + Description: The current AWS account ID. This parameter is for validation purposes only, and may be left empty. + AllowedPattern: "|[0-9]{12}" + Default: "" + + DatadogAPIKey: + Type: String + AllowedPattern: "[0-9a-f]{32}" + Description: API key for the Datadog account + NoEcho: true + + DatadogAPPKey: + Type: String + AllowedPattern: "([0-9a-f]{40})|(ddapp_[a-zA-Z0-9]{34})" + Description: Application key for the Datadog account + NoEcho: true + + DatadogSite: + Type: String + Description: >- + The Datadog site to use for the Datadog Agentless Scanner. + Allowed values: datadoghq.com, datadoghq.eu, us3.datadoghq.com, us5.datadoghq.com, + ap1.datadoghq.com, ap2.datadoghq.com. + Default: datadoghq.com + + AgentlessVulnerabilityScanning: + Type: String + AllowedValues: + - true + - false + Description: Enable Agentless Vulnerability Scanning (hosts, containers, and Lambda functions). + Default: false + + AgentlessSensitiveDataScanning: + Type: String + AllowedValues: + - true + - false + Description: Enable Agentless Scanning of datastores (S3 buckets). + Default: false + + AgentlessComplianceHostScanning: + Type: String + AllowedValues: + - true + - false + Description: Enable Agentless Compliance Scanning for hosts. + Default: false + + ScannerDelegateRoleName: + Type: String + Description: The name of the role assumed by the Datadog Agentless Scanner via the Datadog integration role. + Default: DatadogAgentlessScannerDelegateRole + + DatadogIntegrationRoleName: + Type: String + Description: >- + The name of the IAM role used by the Datadog AWS integration. In SaaS mode, Datadog assumes this + role and then chains into the delegate role to perform agentless scans. The SecurityAudit policy is + also attached to this role. + Default: DatadogIntegrationRole + AllowedPattern: '[\w+=,.@-]{1,64}' + +Rules: + MustMatchAccountId: + AssertDescription: 'Checking that AccountId matches the current AWS account ID' + Assertions: + - Assert: !Or [!Equals [!Ref AccountId, !Ref AWS::AccountId], !Equals [!Ref AccountId, ""]] + AssertDescription: >- + The current AWS account ID does not match the AWS account selected in Datadog. + Please log in to the AWS account where you want to set up Datadog Agentless Scanning and try again. + +Resources: + ScannerDelegateRoleOrchestratorPolicy: + Type: AWS::IAM::ManagedPolicy + Properties: + Description: Policy for the Datadog Agentless Scanner orchestrator allowing the creation and deletion of snapshots. + PolicyDocument: + Version: '2012-10-17' + Statement: + - Sid: DatadogAgentlessScannerResourceTagging + Action: 'ec2:CreateTags' + Effect: Allow + Resource: + - 'arn:aws:ec2:*:*:volume/*' + - 'arn:aws:ec2:*:*:snapshot/*' + - 'arn:aws:ec2:*:*:image/*' + Condition: + StringEquals: + 'ec2:CreateAction': + - CreateSnapshot + - CreateVolume + - CopySnapshot + - CopyImage + - Sid: DatadogAgentlessScannerVolumeSnapshotCreation + Action: 'ec2:CreateSnapshot' + Effect: Allow + Resource: 'arn:aws:ec2:*:*:volume/*' + Condition: + StringNotEquals: + 'aws:ResourceTag/DatadogAgentlessScanner': 'false' + - Sid: DatadogAgentlessScannerCopySnapshotSource + Action: 'ec2:CopySnapshot' + Effect: Allow + Resource: 'arn:aws:ec2:*:*:snapshot/snap-*' + - Sid: DatadogAgentlessScannerCopySnapshotDestination + Action: 'ec2:CopySnapshot' + Effect: Allow + Resource: 'arn:aws:ec2:*:*:snapshot/${*}' + Condition: + 'ForAllValues:StringLike': + 'aws:TagKeys': DatadogAgentlessScanner* + StringEquals: + 'aws:RequestTag/DatadogAgentlessScanner': 'true' + - Sid: DatadogAgentlessScannerSnapshotCreation + Action: 'ec2:CreateSnapshot' + Effect: Allow + Resource: 'arn:aws:ec2:*:*:snapshot/*' + Condition: + 'ForAllValues:StringLike': + 'aws:TagKeys': DatadogAgentlessScanner* + StringEquals: + 'aws:RequestTag/DatadogAgentlessScanner': 'true' + - Sid: DatadogAgentlessScannerSnapshotCleanup + Action: 'ec2:DeleteSnapshot' + Effect: Allow + Resource: 'arn:aws:ec2:*:*:snapshot/*' + Condition: + StringEquals: + 'aws:ResourceTag/DatadogAgentlessScanner': 'true' + - Sid: DatadogAgentlessScannerDescribeSnapshots + Action: 'ec2:DescribeSnapshots' + Effect: Allow + Resource: '*' + - Sid: DatadogAgentlessScannerEncryptedCopyGrant + Action: 'kms:CreateGrant' + Effect: Allow + Resource: 'arn:aws:kms:*:*:key/*' + Condition: + 'ForAnyValue:StringEquals': + 'kms:EncryptionContextKeys': 'aws:ebs:id' + StringLike: + 'kms:ViaService': 'ec2.*.amazonaws.com' + Bool: + 'kms:GrantIsForAWSResource': true + - Sid: DatadogAgentlessScannerEncryptedCopyDescribe + Action: 'kms:DescribeKey' + Effect: Allow + Resource: 'arn:aws:kms:*:*:key/*' + - Sid: DatadogAgentlessScannerImageCleanup + Action: 'ec2:DeregisterImage' + Effect: Allow + Resource: 'arn:aws:ec2:*:*:image/*' + Condition: + StringEquals: + 'aws:ResourceTag/DatadogAgentlessScanner': 'true' + + ScannerDelegateRoleWorkerPolicy: + Type: AWS::IAM::ManagedPolicy + Properties: + Description: Policy for the Datadog Agentless Scanner worker allowing the listing and reading of snapshots. + PolicyDocument: + Version: '2012-10-17' + Statement: + - Sid: DatadogAgentlessScannerSnapshotAccess + Action: + - 'ebs:ListSnapshotBlocks' + - 'ebs:ListChangedBlocks' + - 'ebs:GetSnapshotBlock' + Effect: Allow + Resource: 'arn:aws:ec2:*:*:snapshot/*' + Condition: + StringEquals: + 'aws:ResourceTag/DatadogAgentlessScanner': 'true' + - Sid: DatadogAgentlessScannerDescribeSnapshots + Action: 'ec2:DescribeSnapshots' + Effect: Allow + Resource: '*' + - Sid: DatadogAgentlessScannerDescribeVolumes + Action: 'ec2:DescribeVolumes' + Effect: Allow + Resource: '*' + - Sid: DatadogAgentlessScannerDecryptEncryptedSnapshots + Action: 'kms:Decrypt' + Effect: Allow + Resource: 'arn:aws:kms:*:*:key/*' + Condition: + 'ForAnyValue:StringEquals': + 'kms:EncryptionContextKeys': 'aws:ebs:id' + StringLike: + 'kms:ViaService': 'ec2.*.amazonaws.com' + - Sid: DatadogAgentlessScannerKMSDescribe + Action: 'kms:DescribeKey' + Effect: Allow + Resource: 'arn:aws:kms:*:*:key/*' + - Sid: DatadogAgentlessScannerGetLambdaDetails + Action: 'lambda:GetFunction' + Effect: Allow + Resource: 'arn:aws:lambda:*:*:function:*' + Condition: + StringNotEquals: + 'aws:ResourceTag/DatadogAgentlessScanner': 'false' + - Sid: DatadogAgentlessScannerGetLambdaLayerDetails + Action: 'lambda:GetLayerVersion' + Effect: Allow + Resource: 'arn:aws:lambda:*:*:layer:*:*' + Condition: + StringNotEquals: + 'aws:ResourceTag/DatadogAgentlessScanner': 'false' + - Sid: DatadogAgentlessScannerECRAuthorizationToken + Action: + - "ecr:GetAuthorizationToken" + Effect: Allow + Resource: "*" + - Sid: DatadogAgentlessScannerECRImages + Action: + - "ecr:GetDownloadUrlForLayer" + - "ecr:BatchGetImage" + Condition: + StringNotEquals: + "ecr:ResourceTag/DatadogAgentlessScanner": "false" + Effect: Allow + Resource: "arn:aws:ecr:*:*:repository/*" + + ScannerDelegateRoleWorkerDSPMPolicy: + Type: AWS::IAM::ManagedPolicy + Properties: + Description: Policy for the Datadog Agentless Scanner worker allowing the listing and reading of S3 buckets. + PolicyDocument: + Version: '2012-10-17' + Statement: + - Sid: DatadogAgentlessScannerAccessS3Objects + Action: 's3:GetObject' + Effect: Allow + Resource: 'arn:aws:s3:::*/*' + - Sid: DatadogAgentlessScannerListS3Buckets + Action: 's3:ListBucket' + Effect: Allow + Resource: 'arn:aws:s3:::*' + - Sid: DatadogAgentlessScannerDecryptS3Objects + Action: + - 'kms:Decrypt' + - 'kms:GenerateDataKey' + Effect: Allow + Resource: 'arn:aws:kms:*:*:key/*' + Condition: + StringLike: + 'kms:ViaService': 's3.*.amazonaws.com' + + ScannerDelegateRole: + Type: AWS::IAM::Role + Properties: + RoleName: !Ref 'ScannerDelegateRoleName' + AssumeRolePolicyDocument: + Version: '2012-10-17' + Statement: + - Sid: DatadogIntegrationRoleAssumeRole + Effect: Allow + Principal: + AWS: !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${DatadogIntegrationRoleName}" + Action: 'sts:AssumeRole' + MaxSessionDuration: 3600 + ManagedPolicyArns: + - !Ref 'ScannerDelegateRoleOrchestratorPolicy' + - !Ref 'ScannerDelegateRoleWorkerPolicy' + - !Ref 'ScannerDelegateRoleWorkerDSPMPolicy' + Description: Role assumed by the Datadog Agentless scanner (via the Datadog integration role) to perform scans + Tags: + - Key: DatadogAgentlessScanner + Value: 'true' + - Key: Datadog + Value: 'true' + + DatadogIntegrationRoleAssumeDelegatePolicy: + Type: AWS::IAM::RolePolicy + Properties: + RoleName: !Ref DatadogIntegrationRoleName + PolicyName: DatadogAgentlessAssumeDelegateRole + PolicyDocument: + Version: '2012-10-17' + Statement: + - Sid: AllowAssumeAgentlessDelegateRole + Effect: Allow + Action: 'sts:AssumeRole' + Resource: !GetAtt ScannerDelegateRole.Arn + + LambdaExecutionRoleDatadogAgentlessAPICall: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Principal: + Service: + - lambda.amazonaws.com + Action: + - sts:AssumeRole + Path: "/" + ManagedPolicyArns: + - !Sub "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + + SecurityAuditPolicyAttachmentPermissions: + Type: AWS::IAM::RolePolicy + Properties: + RoleName: !Ref LambdaExecutionRoleDatadogAgentlessAPICall + PolicyName: SecurityAuditPolicyAttachmentPermissions + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - iam:ListAttachedRolePolicies + Resource: !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${DatadogIntegrationRoleName}" + - Effect: Allow + Action: + - iam:AttachRolePolicy + Resource: !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${DatadogIntegrationRoleName}" + Condition: + ArnEquals: + 'iam:PolicyARN': + - !Sub "arn:${AWS::Partition}:iam::aws:policy/SecurityAudit" + + DatadogAgentlessAPICall: + Type: "Custom::DatadogAgentlessAPICall" + Properties: + ServiceToken: !GetAtt "DatadogAgentlessAPICallFunction.Arn" + TemplateVersion: "" + APIKey: !Ref "DatadogAPIKey" + APPKey: !Ref "DatadogAPPKey" + DatadogSite: !Ref "DatadogSite" + AccountId: !Ref "AWS::AccountId" + VulnerabilityScanning: !Ref "AgentlessVulnerabilityScanning" + SensitiveData: !Ref "AgentlessSensitiveDataScanning" + ComplianceHost: !Ref "AgentlessComplianceHostScanning" + IntegrationRoleName: !Ref "DatadogIntegrationRoleName" + Partition: !Ref "AWS::Partition" + # Optional parameters + DelegateRoleArn: !GetAtt "ScannerDelegateRole.Arn" + OrchestratorPolicyArn: !Ref "ScannerDelegateRoleOrchestratorPolicy" + WorkerPolicyArn: !Ref "ScannerDelegateRoleWorkerPolicy" + WorkerDSPMPolicyArn: !Ref "ScannerDelegateRoleWorkerDSPMPolicy" + + DatadogAgentlessAPICallFunction: + Type: "AWS::Lambda::Function" + Properties: + Description: A function to call the Datadog Agentless API. + Role: !GetAtt LambdaExecutionRoleDatadogAgentlessAPICall.Arn + Handler: "index.handler" + LoggingConfig: + ApplicationLogLevel: "INFO" + LogFormat: "JSON" + Runtime: "python3.13" + Timeout: 30 + Code: + ZipFile: | + + +Metadata: + AWS::CloudFormation::Interface: + ParameterGroups: + - Label: + default: "Required" + Parameters: + - ScannerDelegateRoleName + - DatadogIntegrationRoleName + - Label: + default: "Advanced" + Parameters: + - AgentlessSensitiveDataScanning + - AgentlessComplianceHostScanning + - AccountId diff --git a/aws_quickstart/release.sh b/aws_quickstart/release.sh index 3b8728f2..2835b6d4 100755 --- a/aws_quickstart/release.sh +++ b/aws_quickstart/release.sh @@ -122,7 +122,7 @@ for template in main_workflow.yaml main_extended_workflow.yaml main_v2.yaml main done # Process Agentless Scanning templates -for template in datadog_agentless_delegate_role.yaml datadog_agentless_scanning.yaml datadog_agentless_delegate_role_snapshot.yaml datadog_integration_autoscaling_policy.yaml datadog_integration_sds_policy.yaml datadog_agentless_delegate_role_stackset.yaml; do +for template in datadog_agentless_delegate_role.yaml datadog_agentless_scanning.yaml datadog_agentless_delegate_role_snapshot.yaml datadog_integration_autoscaling_policy.yaml datadog_integration_sds_policy.yaml datadog_agentless_delegate_role_stackset.yaml datadog_agentless_delegate_role_saas.yaml; do # Note: unlike above, here we remove the 'v' prefix from the version perl -pi -e "s//${VERSION#v}/g" "$template" From 55e46e9b1f04d7e47fa73624fa85cc9e2bb5091e Mon Sep 17 00:00:00 2001 From: Moez Ezzeddine Date: Tue, 2 Jun 2026 18:28:38 +0200 Subject: [PATCH 2/6] refactor(aws_quickstart): attach SaaS scanning permissions as managed policy on integration role Replace the chained delegate-role approach with a single DatadogAgentlessSaaSScanningPolicy attached directly to the Datadog integration role. Co-Authored-By: Claude Sonnet 4.6 --- aws_quickstart/CHANGELOG.md | 2 +- .../datadog_agentless_delegate_role_saas.yaml | 75 ++----------------- 2 files changed, 8 insertions(+), 69 deletions(-) diff --git a/aws_quickstart/CHANGELOG.md b/aws_quickstart/CHANGELOG.md index fab2cc6a..cd20f791 100644 --- a/aws_quickstart/CHANGELOG.md +++ b/aws_quickstart/CHANGELOG.md @@ -1,6 +1,6 @@ # 4.14.0 (June 2, 2026) -- Add `datadog_agentless_delegate_role_saas.yaml` for SaaS-mode Agentless Scanning. The template provisions only the `DatadogAgentlessScannerDelegateRole` and its three managed policies (Orchestrator, Worker, DSPM) — no scanner EC2/VPC/ASG resources. The delegate role's trust policy is keyed on the local Datadog integration role (default `DatadogIntegrationRole`), so Datadog assumes the integration role and chains into the delegate role to perform agentless scans. `SecurityAudit` is unconditionally attached to the integration role. `DatadogIntegrationRoleName` is required (defaults to `DatadogIntegrationRole`). Released alongside an entry added to `release.sh` so the new template participates in the standard placeholder substitution and upload pipeline. +- Add `datadog_agentless_delegate_role_saas.yaml` for SaaS-mode Agentless Scanning. The template provisions a single managed policy with the SaaS scanner permissions and attaches it to the local Datadog integration role (default `DatadogIntegrationRole`) — no scanner EC2/VPC/ASG resources and no delegate-role chaining. `SecurityAudit` is unconditionally attached to the integration role. `DatadogIntegrationRoleName` is required (defaults to `DatadogIntegrationRole`). Released alongside an entry added to `release.sh` so the new template participates in the standard placeholder substitution and upload pipeline. # 4.13.0 (May 29, 2026) diff --git a/aws_quickstart/datadog_agentless_delegate_role_saas.yaml b/aws_quickstart/datadog_agentless_delegate_role_saas.yaml index f5e5a6b7..51ef732c 100644 --- a/aws_quickstart/datadog_agentless_delegate_role_saas.yaml +++ b/aws_quickstart/datadog_agentless_delegate_role_saas.yaml @@ -1,6 +1,6 @@ # version: v AWSTemplateFormatVersion: '2010-09-09' -Description: Creates a Datadog Agentless Scanning delegate role for SaaS-mode deployments (no scanner infrastructure; trusted by the local Datadog integration role). +Description: Attaches Datadog Agentless Scanning permissions for SaaS-mode deployments to the Datadog integration role. Parameters: AccountId: Type: String @@ -52,17 +52,11 @@ Parameters: Description: Enable Agentless Compliance Scanning for hosts. Default: false - ScannerDelegateRoleName: - Type: String - Description: The name of the role assumed by the Datadog Agentless Scanner via the Datadog integration role. - Default: DatadogAgentlessScannerDelegateRole - DatadogIntegrationRoleName: Type: String Description: >- The name of the IAM role used by the Datadog AWS integration. In SaaS mode, Datadog assumes this - role and then chains into the delegate role to perform agentless scans. The SecurityAudit policy is - also attached to this role. + role directly to perform agentless scans. The SecurityAudit policy is also attached to this role. Default: DatadogIntegrationRole AllowedPattern: '[\w+=,.@-]{1,64}' @@ -76,10 +70,12 @@ Rules: Please log in to the AWS account where you want to set up Datadog Agentless Scanning and try again. Resources: - ScannerDelegateRoleOrchestratorPolicy: + DatadogAgentlessSaaSScanningPolicy: Type: AWS::IAM::ManagedPolicy Properties: - Description: Policy for the Datadog Agentless Scanner orchestrator allowing the creation and deletion of snapshots. + Description: Policy for Datadog Agentless Scanning in SaaS mode. + Roles: + - !Ref DatadogIntegrationRoleName PolicyDocument: Version: '2012-10-17' Statement: @@ -159,14 +155,6 @@ Resources: Condition: StringEquals: 'aws:ResourceTag/DatadogAgentlessScanner': 'true' - - ScannerDelegateRoleWorkerPolicy: - Type: AWS::IAM::ManagedPolicy - Properties: - Description: Policy for the Datadog Agentless Scanner worker allowing the listing and reading of snapshots. - PolicyDocument: - Version: '2012-10-17' - Statement: - Sid: DatadogAgentlessScannerSnapshotAccess Action: - 'ebs:ListSnapshotBlocks' @@ -226,14 +214,6 @@ Resources: "ecr:ResourceTag/DatadogAgentlessScanner": "false" Effect: Allow Resource: "arn:aws:ecr:*:*:repository/*" - - ScannerDelegateRoleWorkerDSPMPolicy: - Type: AWS::IAM::ManagedPolicy - Properties: - Description: Policy for the Datadog Agentless Scanner worker allowing the listing and reading of S3 buckets. - PolicyDocument: - Version: '2012-10-17' - Statement: - Sid: DatadogAgentlessScannerAccessS3Objects Action: 's3:GetObject' Effect: Allow @@ -252,43 +232,6 @@ Resources: StringLike: 'kms:ViaService': 's3.*.amazonaws.com' - ScannerDelegateRole: - Type: AWS::IAM::Role - Properties: - RoleName: !Ref 'ScannerDelegateRoleName' - AssumeRolePolicyDocument: - Version: '2012-10-17' - Statement: - - Sid: DatadogIntegrationRoleAssumeRole - Effect: Allow - Principal: - AWS: !Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${DatadogIntegrationRoleName}" - Action: 'sts:AssumeRole' - MaxSessionDuration: 3600 - ManagedPolicyArns: - - !Ref 'ScannerDelegateRoleOrchestratorPolicy' - - !Ref 'ScannerDelegateRoleWorkerPolicy' - - !Ref 'ScannerDelegateRoleWorkerDSPMPolicy' - Description: Role assumed by the Datadog Agentless scanner (via the Datadog integration role) to perform scans - Tags: - - Key: DatadogAgentlessScanner - Value: 'true' - - Key: Datadog - Value: 'true' - - DatadogIntegrationRoleAssumeDelegatePolicy: - Type: AWS::IAM::RolePolicy - Properties: - RoleName: !Ref DatadogIntegrationRoleName - PolicyName: DatadogAgentlessAssumeDelegateRole - PolicyDocument: - Version: '2012-10-17' - Statement: - - Sid: AllowAssumeAgentlessDelegateRole - Effect: Allow - Action: 'sts:AssumeRole' - Resource: !GetAtt ScannerDelegateRole.Arn - LambdaExecutionRoleDatadogAgentlessAPICall: Type: AWS::IAM::Role Properties: @@ -341,10 +284,7 @@ Resources: IntegrationRoleName: !Ref "DatadogIntegrationRoleName" Partition: !Ref "AWS::Partition" # Optional parameters - DelegateRoleArn: !GetAtt "ScannerDelegateRole.Arn" - OrchestratorPolicyArn: !Ref "ScannerDelegateRoleOrchestratorPolicy" - WorkerPolicyArn: !Ref "ScannerDelegateRoleWorkerPolicy" - WorkerDSPMPolicyArn: !Ref "ScannerDelegateRoleWorkerDSPMPolicy" + SaaSScanningPolicyArn: !Ref "DatadogAgentlessSaaSScanningPolicy" DatadogAgentlessAPICallFunction: Type: "AWS::Lambda::Function" @@ -367,7 +307,6 @@ Metadata: - Label: default: "Required" Parameters: - - ScannerDelegateRoleName - DatadogIntegrationRoleName - Label: default: "Advanced" From 270a3693d1a0df36b4d1a873509926d1bcd54864 Mon Sep 17 00:00:00 2001 From: Moez Ezzeddine Date: Tue, 2 Jun 2026 18:30:56 +0200 Subject: [PATCH 3/6] rename datadog_agentless_delegate_role_saas.yaml to datadog_agentless_saas.yaml Co-Authored-By: Claude Sonnet 4.6 --- aws_quickstart/CHANGELOG.md | 2 +- ...less_delegate_role_saas.yaml => datadog_agentless_saas.yaml} | 0 aws_quickstart/release.sh | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename aws_quickstart/{datadog_agentless_delegate_role_saas.yaml => datadog_agentless_saas.yaml} (100%) diff --git a/aws_quickstart/CHANGELOG.md b/aws_quickstart/CHANGELOG.md index cd20f791..3340b0f3 100644 --- a/aws_quickstart/CHANGELOG.md +++ b/aws_quickstart/CHANGELOG.md @@ -1,6 +1,6 @@ # 4.14.0 (June 2, 2026) -- Add `datadog_agentless_delegate_role_saas.yaml` for SaaS-mode Agentless Scanning. The template provisions a single managed policy with the SaaS scanner permissions and attaches it to the local Datadog integration role (default `DatadogIntegrationRole`) — no scanner EC2/VPC/ASG resources and no delegate-role chaining. `SecurityAudit` is unconditionally attached to the integration role. `DatadogIntegrationRoleName` is required (defaults to `DatadogIntegrationRole`). Released alongside an entry added to `release.sh` so the new template participates in the standard placeholder substitution and upload pipeline. +- Add `datadog_agentless_saas.yaml` for SaaS-mode Agentless Scanning. The template provisions a single managed policy with the SaaS scanner permissions and attaches it to the local Datadog integration role (default `DatadogIntegrationRole`) — no scanner EC2/VPC/ASG resources and no delegate-role chaining. `SecurityAudit` is unconditionally attached to the integration role. `DatadogIntegrationRoleName` is required (defaults to `DatadogIntegrationRole`). Released alongside an entry added to `release.sh` so the new template participates in the standard placeholder substitution and upload pipeline. # 4.13.0 (May 29, 2026) diff --git a/aws_quickstart/datadog_agentless_delegate_role_saas.yaml b/aws_quickstart/datadog_agentless_saas.yaml similarity index 100% rename from aws_quickstart/datadog_agentless_delegate_role_saas.yaml rename to aws_quickstart/datadog_agentless_saas.yaml diff --git a/aws_quickstart/release.sh b/aws_quickstart/release.sh index 2835b6d4..737f47fe 100755 --- a/aws_quickstart/release.sh +++ b/aws_quickstart/release.sh @@ -122,7 +122,7 @@ for template in main_workflow.yaml main_extended_workflow.yaml main_v2.yaml main done # Process Agentless Scanning templates -for template in datadog_agentless_delegate_role.yaml datadog_agentless_scanning.yaml datadog_agentless_delegate_role_snapshot.yaml datadog_integration_autoscaling_policy.yaml datadog_integration_sds_policy.yaml datadog_agentless_delegate_role_stackset.yaml datadog_agentless_delegate_role_saas.yaml; do +for template in datadog_agentless_delegate_role.yaml datadog_agentless_scanning.yaml datadog_agentless_delegate_role_snapshot.yaml datadog_integration_autoscaling_policy.yaml datadog_integration_sds_policy.yaml datadog_agentless_delegate_role_stackset.yaml datadog_agentless_saas.yaml; do # Note: unlike above, here we remove the 'v' prefix from the version perl -pi -e "s//${VERSION#v}/g" "$template" From badd7446e73d1358364ee4135c04895b981f8618 Mon Sep 17 00:00:00 2001 From: Moez Ezzeddine Date: Wed, 3 Jun 2026 13:53:17 +0200 Subject: [PATCH 4/6] feat(aws_quickstart): forward saas_scanning_policy_arn in agentless API call and drop Sid fields Co-Authored-By: Claude Sonnet 4.6 --- aws_quickstart/datadog_agentless_api_call.py | 2 + .../datadog_agentless_api_call_test.py | 7 ++ aws_quickstart/datadog_agentless_saas.yaml | 66 +++++++------------ 3 files changed, 31 insertions(+), 44 deletions(-) diff --git a/aws_quickstart/datadog_agentless_api_call.py b/aws_quickstart/datadog_agentless_api_call.py index 98295f68..63a1494b 100644 --- a/aws_quickstart/datadog_agentless_api_call.py +++ b/aws_quickstart/datadog_agentless_api_call.py @@ -25,6 +25,7 @@ def call_datadog_agentless_api(context, event, method): instance_role_arn = event["ResourceProperties"].get("InstanceRoleArn") instance_profile_arn = event["ResourceProperties"].get("InstanceProfileArn") scanner_policy_arn = event["ResourceProperties"].get("ScannerPolicyArn") + saas_scanning_policy_arn = event["ResourceProperties"].get("SaaSScanningPolicyArn") orchestrator_policy_arn = event["ResourceProperties"].get("OrchestratorPolicyArn") worker_policy_arn = event["ResourceProperties"].get("WorkerPolicyArn") worker_dspm_policy_arn = event["ResourceProperties"].get("WorkerDSPMPolicyArn") @@ -65,6 +66,7 @@ def call_datadog_agentless_api(context, event, method): "instance_role_arn": instance_role_arn, "instance_profile_arn": instance_profile_arn, "scanner_policy_arn": scanner_policy_arn, + "saas_scanning_policy_arn": saas_scanning_policy_arn, "orchestrator_policy_arn": orchestrator_policy_arn, "worker_policy_arn": worker_policy_arn, "worker_dspm_policy_arn": worker_dspm_policy_arn, diff --git a/aws_quickstart/datadog_agentless_api_call_test.py b/aws_quickstart/datadog_agentless_api_call_test.py index 8c19ce33..2eb44c21 100644 --- a/aws_quickstart/datadog_agentless_api_call_test.py +++ b/aws_quickstart/datadog_agentless_api_call_test.py @@ -195,6 +195,9 @@ def test_post_request_payload_structure(self, mock_is_enabled, mock_urlopen): mock_is_enabled.return_value = False mock_response = self.create_mock_response(200) mock_urlopen.return_value = mock_response + self.base_event["ResourceProperties"]["SaaSScanningPolicyArn"] = ( + "arn:aws:iam::123456789012:policy/datadog-agentless-saas-scanning" + ) call_datadog_agentless_api(self.context, self.base_event, "POST") @@ -207,6 +210,10 @@ def test_post_request_payload_structure(self, mock_is_enabled, mock_urlopen): self.assertIn("data", payload) self.assertIn("type", payload["data"]) self.assertEqual(payload["data"]["type"], "aws_scan_options") + self.assertEqual( + payload["meta"]["resources"]["saas_scanning_policy_arn"], + "arn:aws:iam::123456789012:policy/datadog-agentless-saas-scanning", + ) class TestIsAgentlessScanningEnabled(unittest.TestCase): diff --git a/aws_quickstart/datadog_agentless_saas.yaml b/aws_quickstart/datadog_agentless_saas.yaml index 51ef732c..55b9e2ea 100644 --- a/aws_quickstart/datadog_agentless_saas.yaml +++ b/aws_quickstart/datadog_agentless_saas.yaml @@ -79,8 +79,7 @@ Resources: PolicyDocument: Version: '2012-10-17' Statement: - - Sid: DatadogAgentlessScannerResourceTagging - Action: 'ec2:CreateTags' + - Action: 'ec2:CreateTags' Effect: Allow Resource: - 'arn:aws:ec2:*:*:volume/*' @@ -93,19 +92,16 @@ Resources: - CreateVolume - CopySnapshot - CopyImage - - Sid: DatadogAgentlessScannerVolumeSnapshotCreation - Action: 'ec2:CreateSnapshot' + - Action: 'ec2:CreateSnapshot' Effect: Allow Resource: 'arn:aws:ec2:*:*:volume/*' Condition: StringNotEquals: 'aws:ResourceTag/DatadogAgentlessScanner': 'false' - - Sid: DatadogAgentlessScannerCopySnapshotSource - Action: 'ec2:CopySnapshot' + - Action: 'ec2:CopySnapshot' Effect: Allow Resource: 'arn:aws:ec2:*:*:snapshot/snap-*' - - Sid: DatadogAgentlessScannerCopySnapshotDestination - Action: 'ec2:CopySnapshot' + - Action: 'ec2:CopySnapshot' Effect: Allow Resource: 'arn:aws:ec2:*:*:snapshot/${*}' Condition: @@ -113,8 +109,7 @@ Resources: 'aws:TagKeys': DatadogAgentlessScanner* StringEquals: 'aws:RequestTag/DatadogAgentlessScanner': 'true' - - Sid: DatadogAgentlessScannerSnapshotCreation - Action: 'ec2:CreateSnapshot' + - Action: 'ec2:CreateSnapshot' Effect: Allow Resource: 'arn:aws:ec2:*:*:snapshot/*' Condition: @@ -122,19 +117,16 @@ Resources: 'aws:TagKeys': DatadogAgentlessScanner* StringEquals: 'aws:RequestTag/DatadogAgentlessScanner': 'true' - - Sid: DatadogAgentlessScannerSnapshotCleanup - Action: 'ec2:DeleteSnapshot' + - Action: 'ec2:DeleteSnapshot' Effect: Allow Resource: 'arn:aws:ec2:*:*:snapshot/*' Condition: StringEquals: 'aws:ResourceTag/DatadogAgentlessScanner': 'true' - - Sid: DatadogAgentlessScannerDescribeSnapshots - Action: 'ec2:DescribeSnapshots' + - Action: 'ec2:DescribeSnapshots' Effect: Allow Resource: '*' - - Sid: DatadogAgentlessScannerEncryptedCopyGrant - Action: 'kms:CreateGrant' + - Action: 'kms:CreateGrant' Effect: Allow Resource: 'arn:aws:kms:*:*:key/*' Condition: @@ -144,19 +136,16 @@ Resources: 'kms:ViaService': 'ec2.*.amazonaws.com' Bool: 'kms:GrantIsForAWSResource': true - - Sid: DatadogAgentlessScannerEncryptedCopyDescribe - Action: 'kms:DescribeKey' + - Action: 'kms:DescribeKey' Effect: Allow Resource: 'arn:aws:kms:*:*:key/*' - - Sid: DatadogAgentlessScannerImageCleanup - Action: 'ec2:DeregisterImage' + - Action: 'ec2:DeregisterImage' Effect: Allow Resource: 'arn:aws:ec2:*:*:image/*' Condition: StringEquals: 'aws:ResourceTag/DatadogAgentlessScanner': 'true' - - Sid: DatadogAgentlessScannerSnapshotAccess - Action: + - Action: - 'ebs:ListSnapshotBlocks' - 'ebs:ListChangedBlocks' - 'ebs:GetSnapshotBlock' @@ -165,16 +154,13 @@ Resources: Condition: StringEquals: 'aws:ResourceTag/DatadogAgentlessScanner': 'true' - - Sid: DatadogAgentlessScannerDescribeSnapshots - Action: 'ec2:DescribeSnapshots' + - Action: 'ec2:DescribeSnapshots' Effect: Allow Resource: '*' - - Sid: DatadogAgentlessScannerDescribeVolumes - Action: 'ec2:DescribeVolumes' + - Action: 'ec2:DescribeVolumes' Effect: Allow Resource: '*' - - Sid: DatadogAgentlessScannerDecryptEncryptedSnapshots - Action: 'kms:Decrypt' + - Action: 'kms:Decrypt' Effect: Allow Resource: 'arn:aws:kms:*:*:key/*' Condition: @@ -182,31 +168,26 @@ Resources: 'kms:EncryptionContextKeys': 'aws:ebs:id' StringLike: 'kms:ViaService': 'ec2.*.amazonaws.com' - - Sid: DatadogAgentlessScannerKMSDescribe - Action: 'kms:DescribeKey' + - Action: 'kms:DescribeKey' Effect: Allow Resource: 'arn:aws:kms:*:*:key/*' - - Sid: DatadogAgentlessScannerGetLambdaDetails - Action: 'lambda:GetFunction' + - Action: 'lambda:GetFunction' Effect: Allow Resource: 'arn:aws:lambda:*:*:function:*' Condition: StringNotEquals: 'aws:ResourceTag/DatadogAgentlessScanner': 'false' - - Sid: DatadogAgentlessScannerGetLambdaLayerDetails - Action: 'lambda:GetLayerVersion' + - Action: 'lambda:GetLayerVersion' Effect: Allow Resource: 'arn:aws:lambda:*:*:layer:*:*' Condition: StringNotEquals: 'aws:ResourceTag/DatadogAgentlessScanner': 'false' - - Sid: DatadogAgentlessScannerECRAuthorizationToken - Action: + - Action: - "ecr:GetAuthorizationToken" Effect: Allow Resource: "*" - - Sid: DatadogAgentlessScannerECRImages - Action: + - Action: - "ecr:GetDownloadUrlForLayer" - "ecr:BatchGetImage" Condition: @@ -214,16 +195,13 @@ Resources: "ecr:ResourceTag/DatadogAgentlessScanner": "false" Effect: Allow Resource: "arn:aws:ecr:*:*:repository/*" - - Sid: DatadogAgentlessScannerAccessS3Objects - Action: 's3:GetObject' + - Action: 's3:GetObject' Effect: Allow Resource: 'arn:aws:s3:::*/*' - - Sid: DatadogAgentlessScannerListS3Buckets - Action: 's3:ListBucket' + - Action: 's3:ListBucket' Effect: Allow Resource: 'arn:aws:s3:::*' - - Sid: DatadogAgentlessScannerDecryptS3Objects - Action: + - Action: - 'kms:Decrypt' - 'kms:GenerateDataKey' Effect: Allow From 326a2f450de6f18fb73297731d915b89b6c10f8e Mon Sep 17 00:00:00 2001 From: Moez Ezzeddine Date: Thu, 4 Jun 2026 11:22:11 +0200 Subject: [PATCH 5/6] chore(aws_quickstart): bump version to v4.14.0 Co-Authored-By: Claude Sonnet 4.6 --- aws_quickstart/version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aws_quickstart/version.txt b/aws_quickstart/version.txt index c4475d31..cabad0ce 100644 --- a/aws_quickstart/version.txt +++ b/aws_quickstart/version.txt @@ -1 +1 @@ -v4.13.0 +v4.14.0 From 01e90de10045c1e197eb1048ece8383223c64cb4 Mon Sep 17 00:00:00 2001 From: Moez Ezzeddine Date: Thu, 4 Jun 2026 11:28:14 +0200 Subject: [PATCH 6/6] feat(aws_quickstart): make DatadogIntegrationRoleName required in datadog_agentless_saas.yaml Co-Authored-By: Claude Sonnet 4.6 --- aws_quickstart/CHANGELOG.md | 2 +- aws_quickstart/datadog_agentless_saas.yaml | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/aws_quickstart/CHANGELOG.md b/aws_quickstart/CHANGELOG.md index 3340b0f3..348ae531 100644 --- a/aws_quickstart/CHANGELOG.md +++ b/aws_quickstart/CHANGELOG.md @@ -1,6 +1,6 @@ # 4.14.0 (June 2, 2026) -- Add `datadog_agentless_saas.yaml` for SaaS-mode Agentless Scanning. The template provisions a single managed policy with the SaaS scanner permissions and attaches it to the local Datadog integration role (default `DatadogIntegrationRole`) — no scanner EC2/VPC/ASG resources and no delegate-role chaining. `SecurityAudit` is unconditionally attached to the integration role. `DatadogIntegrationRoleName` is required (defaults to `DatadogIntegrationRole`). Released alongside an entry added to `release.sh` so the new template participates in the standard placeholder substitution and upload pipeline. +- Add `datadog_agentless_saas.yaml` for SaaS-mode Agentless Scanning. The template provisions a single managed policy with the SaaS scanner permissions and attaches it to the local Datadog integration role — no scanner EC2/VPC/ASG resources and no delegate-role chaining. `SecurityAudit` is unconditionally attached to the integration role. `DatadogIntegrationRoleName` is required. Released alongside an entry added to `release.sh` so the new template participates in the standard placeholder substitution and upload pipeline. # 4.13.0 (May 29, 2026) diff --git a/aws_quickstart/datadog_agentless_saas.yaml b/aws_quickstart/datadog_agentless_saas.yaml index 55b9e2ea..1513adcd 100644 --- a/aws_quickstart/datadog_agentless_saas.yaml +++ b/aws_quickstart/datadog_agentless_saas.yaml @@ -57,7 +57,6 @@ Parameters: Description: >- The name of the IAM role used by the Datadog AWS integration. In SaaS mode, Datadog assumes this role directly to perform agentless scans. The SecurityAudit policy is also attached to this role. - Default: DatadogIntegrationRole AllowedPattern: '[\w+=,.@-]{1,64}' Rules: