diff --git a/aws_quickstart/CHANGELOG.md b/aws_quickstart/CHANGELOG.md index b21d7c2..ab5ae8c 100644 --- a/aws_quickstart/CHANGELOG.md +++ b/aws_quickstart/CHANGELOG.md @@ -1,3 +1,8 @@ +# 4.4.0 (February 9, 2026) + +- Remove all enumerated IAM permissions from the datadog_integration_role stack +- Add Lambda function to retrieve and attach the equivalent IAM permissions at stack creation/update time + # 4.3.0 (December 26, 2025) ### Features diff --git a/aws_quickstart/attach_integration_permissions.py b/aws_quickstart/attach_integration_permissions.py new file mode 100644 index 0000000..16bcc76 --- /dev/null +++ b/aws_quickstart/attach_integration_permissions.py @@ -0,0 +1,159 @@ +import json +import logging +from urllib.request import Request +import urllib.error +import urllib.request +import cfnresponse +import boto3 + +LOGGER = logging.getLogger() +LOGGER.setLevel(logging.INFO) +API_CALL_SOURCE_HEADER_VALUE = "cfn-quickstart" +POLICY_NAME_STANDARD = "DatadogAWSIntegrationPolicy" +BASE_POLICY_PREFIX_RESOURCE_COLLECTION = "datadog-aws-integration-resource-collection-permissions" +STANDARD_PERMISSIONS_API_URL = "https://api.datadoghq.com/api/v2/integration/aws/iam_permissions/standard" +RESOURCE_COLLECTION_PERMISSIONS_API_URL = "https://api.datadoghq.com/api/v2/integration/aws/iam_permissions/resource_collection?chunked=true" + +class DatadogAPIError(Exception): + pass + +def fetch_permissions_from_datadog(api_url): + """Fetch permissions from Datadog API""" + headers = { + "Dd-Aws-Api-Call-Source": API_CALL_SOURCE_HEADER_VALUE, + } + request = Request(api_url, headers=headers) + request.get_method = lambda: "GET" + + try: + response = urllib.request.urlopen(request) + except urllib.error.HTTPError as e: + error_body = json.loads(e.read()) + error_message = error_body.get('errors', ['Unknown error'])[0] + raise DatadogAPIError(f"Datadog API error: {error_message}") from e + + json_response = json.loads(response.read()) + return json_response["data"]["attributes"]["permissions"] + +def cleanup_existing_policies(iam_client, role_name, account_id, partition, max_policies=10): + # Remove resource collection permissions + for i in range(max_policies): + policy_name = f"{BASE_POLICY_PREFIX_RESOURCE_COLLECTION}-{i+1}" + policy_arn = f"arn:{partition}:iam::{account_id}:policy/{policy_name}" + try: + iam_client.detach_role_policy( + RoleName=role_name, + PolicyArn=policy_arn + ) + except iam_client.exceptions.NoSuchEntityException: + pass + except Exception as e: + LOGGER.error(f"Error detaching policy {policy_name}: {str(e)}") + + try: + iam_client.delete_policy( + PolicyArn=policy_arn + ) + except iam_client.exceptions.NoSuchEntityException: + pass + except iam_client.exceptions.DeleteConflictException: + LOGGER.warning(f"Policy {policy_name} still attached, skipping delete") + except Exception as e: + LOGGER.error(f"Error deleting policy {policy_name}: {str(e)}") + + # Remove standard permissions + try: + iam_client.delete_role_policy( + RoleName=role_name, + PolicyName=POLICY_NAME_STANDARD + ) + except iam_client.exceptions.NoSuchEntityException: + pass + except Exception as e: + LOGGER.error(f"Error deleting inline policy {POLICY_NAME_STANDARD}: {str(e)}") + +def attach_standard_permissions(iam_client, role_name): + permissions = fetch_permissions_from_datadog(STANDARD_PERMISSIONS_API_URL) + policy_document = { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": permissions, + "Resource": "*" + } + ] + } + + iam_client.put_role_policy( + RoleName=role_name, + PolicyName=POLICY_NAME_STANDARD, + PolicyDocument=json.dumps(policy_document, separators=(',', ':')) + ) + +def attach_resource_collection_permissions(iam_client, role_name): + permission_chunks = fetch_permissions_from_datadog(RESOURCE_COLLECTION_PERMISSIONS_API_URL) + + # Create and attach new policies + for i, chunk in enumerate(permission_chunks): + # Create policy + policy_name = f"{BASE_POLICY_PREFIX_RESOURCE_COLLECTION}-{i+1}" + policy_document = { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": chunk, + "Resource": "*" + } + ] + } + policy_json = json.dumps(policy_document, separators=(',', ':')) + policy_size = len(policy_json) + LOGGER.info(f"Creating policy {policy_name} with {len(chunk)} permissions ({policy_size} characters)") + policy = iam_client.create_policy( + PolicyName=policy_name, + PolicyDocument=policy_json + ) + + # Attach policy to role + iam_client.attach_role_policy( + RoleName=role_name, + PolicyArn=policy['Policy']['Arn'] + ) + +def handle_delete(event, context, role_name, account_id, partition): + """Handle stack deletion.""" + iam_client = boto3.client('iam') + try: + cleanup_existing_policies(iam_client, role_name, account_id, partition) + cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData={}) + except Exception as e: + LOGGER.error(f"Error deleting policy: {str(e)}") + cfnresponse.send(event, context, cfnresponse.FAILED, responseData={"Message": str(e)}) + +def handle_create_update(event, context, role_name, account_id, partition, should_install_security_audit_policy): + """Handle stack creation or update.""" + try: + iam_client = boto3.client('iam') + cleanup_existing_policies(iam_client, role_name, account_id, partition) + attach_standard_permissions(iam_client, role_name) + if should_install_security_audit_policy: + attach_resource_collection_permissions(iam_client, role_name) + cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData={}) + except Exception as e: + LOGGER.error(f"Error creating/attaching policy: {str(e)}") + cfnresponse.send(event, context, cfnresponse.FAILED, responseData={"Message": str(e)}) + +def handler(event, context): + LOGGER.info("Event received: %s", json.dumps(event)) + + role_name = event['ResourceProperties']['DatadogIntegrationRole'] + account_id = event['ResourceProperties']['AccountId'] + partition = event['ResourceProperties'].get('Partition', 'aws') + should_install_security_audit_policy = str(event['ResourceProperties']['ResourceCollectionPermissions']).lower() == 'true' + + if event['RequestType'] == 'Delete': + handle_delete(event, context, role_name, account_id, partition) + else: + handle_create_update(event, context, role_name, account_id, partition, should_install_security_audit_policy) diff --git a/aws_quickstart/datadog_integration_role.yaml b/aws_quickstart/datadog_integration_role.yaml index 943bd9f..17fb792 100644 --- a/aws_quickstart/datadog_integration_role.yaml +++ b/aws_quickstart/datadog_integration_role.yaml @@ -61,897 +61,219 @@ Resources: [!Sub "arn:${AWS::Partition}:iam::aws:policy/SecurityAudit"], !Ref AWS::NoValue, ] + DatadogAttachIntegrationPermissionsLambdaExecutionRole: + 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" Policies: - - PolicyName: DatadogAWSIntegrationPolicy + - PolicyName: !Sub "datadog-aws-integration-iam-permissions-${IAMRoleName}" PolicyDocument: - Version: 2012-10-17 + Version: "2012-10-17" Statement: - Effect: Allow - Resource: "*" Action: - - "account:GetAccountInformation" - - "airflow:GetEnvironment" - - "airflow:ListEnvironments" - - "apigateway:GET" - - "appsync:ListGraphqlApis" - - "autoscaling:Describe*" - - "backup:List*" - - "batch:DescribeJobDefinitions" - - "bcm-data-exports:GetExport" - - "bcm-data-exports:ListExports" - - "budgets:ViewBudget" - - "cloudfront:GetDistributionConfig" - - "cloudfront:ListDistributions" - - "cloudtrail:DescribeTrails" - - "cloudtrail:GetTrail" - - "cloudtrail:GetTrailStatus" - - "cloudtrail:ListTrails" - - "cloudtrail:LookupEvents" - - "cloudwatch:Describe*" - - "cloudwatch:Get*" - - "cloudwatch:List*" - - "codebuild:BatchGetProjects" - - "codebuild:ListProjects" - - "codedeploy:BatchGet*" - - "codedeploy:List*" - - "cur:DescribeReportDefinitions" - - "directconnect:Describe*" - - "dms:DescribeReplicationInstances" - - "dynamodb:Describe*" - - "dynamodb:List*" - - "ec2:Describe*" - - "ecs:Describe*" - - "ecs:List*" - - "eks:DescribeCluster" - - "eks:ListClusters" - - "elasticache:Describe*" - - "elasticache:List*" - - "elasticfilesystem:DescribeAccessPoints" - - "elasticfilesystem:DescribeFileSystems" - - "elasticfilesystem:DescribeTags" - - "elasticloadbalancing:Describe*" - - "elasticmapreduce:Describe*" - - "elasticmapreduce:List*" - - "es:DescribeElasticsearchDomains" - - "es:ListDomainNames" - - "es:ListTags" - - "events:CreateEventBus" - - "fsx:DescribeFileSystems" - - "fsx:ListTagsForResource" - - "health:DescribeAffectedEntities" - - "health:DescribeEventDetails" - - "health:DescribeEvents" - - "iam:ListAccountAliases" - - "kinesis:Describe*" - - "kinesis:List*" - - "lambda:List*" - - "logs:DeleteSubscriptionFilter" - - "logs:DescribeDeliveries" - - "logs:DescribeDeliverySources" - - "logs:DescribeLogGroups" - - "logs:DescribeLogStreams" - - "logs:DescribeSubscriptionFilters" - - "logs:FilterLogEvents" - - "logs:GetDeliveryDestination" - - "logs:PutSubscriptionFilter" - - "logs:TestMetricFilter" - - "network-firewall:DescribeLoggingConfiguration" - - "network-firewall:ListFirewalls" - - "oam:ListAttachedLinks" - - "oam:ListSinks" - - "organizations:Describe*" - - "organizations:List*" - - "rds:Describe*" - - "rds:List*" - - "redshift-serverless:ListNamespaces" - - "redshift:DescribeClusters" - - "redshift:DescribeLoggingStatus" - - "route53:List*" - - "route53resolver:ListResolverQueryLogConfigs" - - "s3:GetBucketLocation" - - "s3:GetBucketLogging" - - "s3:GetBucketNotification" - - "s3:GetBucketTagging" - - "s3:ListAllMyBuckets" - - "s3:PutBucketNotification" - - "ses:Get*" - - "ses:List*" - - "sns:GetSubscriptionAttributes" - - "sns:List*" - - "sns:Publish" - - "sqs:ListQueues" - - "ssm:GetServiceSetting" - - "ssm:ListCommands" - - "states:DescribeStateMachine" - - "states:ListStateMachines" - - "support:DescribeTrustedAdvisor*" - - "support:RefreshTrustedAdvisorCheck" - - "tag:GetResources" - - "tag:GetTagKeys" - - "tag:GetTagValues" - - "timestream:DescribeEndpoints" - - "wafv2:ListLoggingConfigurations" - - "xray:BatchGetTraces" - - "xray:GetTraceSummaries" - DatadogIntegrationRoleManagedPolicy1: - Type: "AWS::IAM::ManagedPolicy" - Condition: ShouldInstallSecurityAuditPolicy + - iam:CreatePolicy + - iam:DeletePolicy + - iam:DeleteRolePolicy + - iam:AttachRolePolicy + - iam:DetachRolePolicy + - iam:PutRolePolicy + Resource: + - !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${IAMRoleName} + - !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:policy/datadog-aws-integration-resource-collection-permissions-* + - !Sub "arn:${AWS::Partition}:iam::aws:policy/SecurityAudit" + DatadogAttachIntegrationPermissionsFunction: + Type: AWS::Lambda::Function Properties: - ManagedPolicyName: !Sub - - "${IAMRoleName}-ManagedPolicy-1" - - { IAMRoleName: !Ref IAMRoleName } - Roles: - - !Ref DatadogIntegrationRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Resource: "*" - Action: - - "account:GetContactInformation" - - "amplify:ListApps" - - "amplify:ListBackendEnvironments" - - "amplify:ListBranches" - - "amplify:ListDomainAssociations" - - "amplify:ListJobs" - - "amplify:ListWebhooks" - - "aoss:BatchGetCollection" - - "aoss:ListCollections" - - "app-integrations:GetApplication" - - "app-integrations:GetDataIntegration" - - "app-integrations:ListApplicationAssociations" - - "app-integrations:ListApplications" - - "app-integrations:ListDataIntegrationAssociations" - - "app-integrations:ListDataIntegrations" - - "app-integrations:ListEventIntegrationAssociations" - - "app-integrations:ListEventIntegrations" - - "appflow:DescribeConnector" - - "appflow:DescribeConnectorProfiles" - - "appflow:DescribeFlow" - - "appflow:ListConnectors" - - "application-signals:GetServiceLevelObjective" - - "application-signals:ListServiceLevelObjectives" - - "appstream:DescribeAppBlockBuilders" - - "appstream:DescribeAppBlocks" - - "appstream:DescribeApplications" - - "appstream:DescribeFleets" - - "appstream:DescribeImageBuilders" - - "appstream:DescribeImages" - - "appstream:DescribeStacks" - - "appsync:GetGraphqlApi" - - "aps:DescribeRuleGroupsNamespace" - - "aps:DescribeScraper" - - "aps:DescribeWorkspace" - - "aps:ListRuleGroupsNamespaces" - - "aps:ListScrapers" - - "aps:ListWorkspaces" - - "athena:BatchGetNamedQuery" - - "athena:BatchGetPreparedStatement" - - "auditmanager:GetAssessment" - - "auditmanager:GetAssessmentFramework" - - "auditmanager:GetControl" - - "b2bi:GetCapability" - - "b2bi:GetPartnership" - - "b2bi:GetProfile" - - "b2bi:GetTransformer" - - "b2bi:ListCapabilities" - - "b2bi:ListPartnerships" - - "b2bi:ListProfiles" - - "b2bi:ListTransformers" - - "backup-gateway:GetGateway" - - "backup-gateway:GetHypervisor" - - "backup-gateway:GetVirtualMachine" - - "backup-gateway:ListGateways" - - "backup-gateway:ListHypervisors" - - "backup-gateway:ListVirtualMachines" - - "backup:DescribeFramework" - - "backup:GetLegalHold" - - "backup:ListBackupPlans" - - "backup:ListFrameworks" - - "backup:ListLegalHolds" - - "backup:ListProtectedResources" - - "backup:ListRecoveryPointsByBackupVault" - - "batch:DescribeJobQueues" - - "batch:DescribeJobs" - - "batch:DescribeSchedulingPolicies" - - "batch:ListJobs" - - "batch:ListSchedulingPolicies" - - "bedrock:GetAgent" - - "bedrock:GetAgentActionGroup" - - "bedrock:GetAsyncInvoke" - - "bedrock:GetBlueprint" - - "bedrock:GetDataSource" - - "bedrock:GetEvaluationJob" - - "bedrock:GetFlow" - - "bedrock:GetFlowVersion" - - "bedrock:GetGuardrail" - - "bedrock:GetKnowledgeBase" - - "bedrock:GetModelInvocationJob" - - "bedrock:GetPrompt" - - "bedrock:ListAgentCollaborators" - - "bedrock:ListAsyncInvokes" - - "bedrock:ListBlueprints" - - "bedrock:ListKnowledgeBaseDocuments" - - "billingconductor:ListBillingGroups" - - "billingconductor:ListCustomLineItems" - - "billingconductor:ListPricingPlans" - - "billingconductor:ListPricingRules" - - "cassandra:Select" - - "ce:DescribeCostCategoryDefinition" - - "ce:GetAnomalyMonitors" - - "ce:GetAnomalySubscriptions" - - "ce:GetCostCategories" - - "cloudformation:DescribeGeneratedTemplate" - - "cloudformation:DescribeResourceScan" - - "cloudformation:ListGeneratedTemplates" - - "cloudformation:ListResourceScans" - - "cloudformation:ListTypes" - - "cloudhsm:DescribeBackups" - - "cloudhsm:DescribeClusters" - - "codeartifact:DescribeDomain" - - "codeartifact:DescribePackageGroup" - - "codeartifact:DescribeRepository" - - "codeartifact:ListDomains" - - "codeartifact:ListPackageGroups" - - "codeartifact:ListPackages" - - "codeguru-profiler:ListFindingsReports" - - "codeguru-profiler:ListProfilingGroups" - - "codeguru-reviewer:ListCodeReviews" - - "codeguru-reviewer:ListRepositoryAssociations" - - "codeguru-security:GetFindings" - - "codeguru-security:GetScan" - - "codeguru-security:ListScans" - - "codepipeline:GetActionType" - - "codepipeline:ListActionTypes" - - "codepipeline:ListWebhooks" - - "connect:DescribeAgentStatus" - - "connect:DescribeAuthenticationProfile" - - "connect:DescribeContactFlow" - - "connect:DescribeContactFlowModule" - - "connect:DescribeHoursOfOperation" - - "connect:DescribeInstance" - - "connect:DescribeQueue" - - "connect:DescribeQuickConnect" - - "connect:DescribeRoutingProfile" - - "connect:DescribeSecurityProfile" - - "connect:DescribeUser" - - "connect:ListAgentStatuses" - - "connect:ListAuthenticationProfiles" - - "connect:ListContactFlowModules" - - "connect:ListContactFlows" - - "connect:ListHoursOfOperations" - - "connect:ListQueues" - - "connect:ListQuickConnects" - - "connect:ListRoutingProfiles" - - "connect:ListSecurityProfiles" - - "connect:ListUsers" - - "controltower:GetLandingZone" - - "controltower:ListEnabledBaselines" - - "controltower:ListEnabledControls" - - "controltower:ListLandingZones" - - "databrew:ListDatasets" - - "databrew:ListRecipes" - - "databrew:ListRulesets" - - "databrew:ListSchedules" - - "datazone:GetDomain" - - "datazone:ListDomains" - - "deadline:GetBudget" - - "deadline:GetLicenseEndpoint" - - "deadline:GetQueue" - - "deadline:ListBudgets" - - "deadline:ListFarms" - - "deadline:ListFleets" - - "deadline:ListLicenseEndpoints" - - "deadline:ListMonitors" - - "deadline:ListQueues" - - "deadline:ListWorkers" - - "devicefarm:ListDeviceInstances" - - "devicefarm:ListDevicePools" - - "devicefarm:ListDevices" - - "devicefarm:ListInstanceProfiles" - - "devicefarm:ListNetworkProfiles" - - "devicefarm:ListRemoteAccessSessions" - - "devicefarm:ListTestGridProjects" - - "devicefarm:ListTestGridSessions" - - "devicefarm:ListUploads" - - "devicefarm:ListVPCEConfigurations" - - "dlm:GetLifecyclePolicies" - - "dlm:GetLifecyclePolicy" - - "docdb-elastic:GetCluster" - - "docdb-elastic:GetClusterSnapshot" - - "docdb-elastic:ListClusterSnapshots" - - "drs:DescribeJobs" - - "drs:DescribeLaunchConfigurationTemplates" - - "drs:DescribeRecoveryInstances" - - "drs:DescribeReplicationConfigurationTemplates" - - "drs:DescribeSourceNetworks" - - "drs:DescribeSourceServers" - - "dsql:GetCluster" - - "dsql:ListClusters" - - "dynamodb:DescribeBackup" - - "dynamodb:DescribeStream" - - "ec2:GetAllowedImagesSettings" - - "ec2:GetEbsDefaultKmsKeyId" - - "ec2:GetInstanceMetadataDefaults" - - "ec2:GetSerialConsoleAccessStatus" - - "ec2:GetSnapshotBlockPublicAccessState" - - "ec2:GetVerifiedAccessEndpointPolicy" - DatadogIntegrationRoleManagedPolicy2: - Type: "AWS::IAM::ManagedPolicy" - Condition: ShouldInstallSecurityAuditPolicy + Description: "A function to attach Datadog AWS integration permissions to an IAM role." + Role: !GetAtt DatadogAttachIntegrationPermissionsLambdaExecutionRole.Arn + Handler: "index.handler" + LoggingConfig: + ApplicationLogLevel: "INFO" + LogFormat: "JSON" + Runtime: "python3.13" + Timeout: 300 + Code: + ZipFile: | + import json + import logging + from urllib.request import Request + import urllib.error + import urllib.request + import cfnresponse + import boto3 + + LOGGER = logging.getLogger() + LOGGER.setLevel(logging.INFO) + API_CALL_SOURCE_HEADER_VALUE = "cfn-quickstart" + POLICY_NAME_STANDARD = "DatadogAWSIntegrationPolicy" + BASE_POLICY_PREFIX_RESOURCE_COLLECTION = "datadog-aws-integration-resource-collection-permissions" + STANDARD_PERMISSIONS_API_URL = "https://api.datadoghq.com/api/v2/integration/aws/iam_permissions/standard" + RESOURCE_COLLECTION_PERMISSIONS_API_URL = "https://api.datadoghq.com/api/v2/integration/aws/iam_permissions/resource_collection?chunked=true" + + class DatadogAPIError(Exception): + pass + + def fetch_permissions_from_datadog(api_url): + """Fetch permissions from Datadog API""" + headers = { + "Dd-Aws-Api-Call-Source": API_CALL_SOURCE_HEADER_VALUE, + } + request = Request(api_url, headers=headers) + request.get_method = lambda: "GET" + + try: + response = urllib.request.urlopen(request) + except urllib.error.HTTPError as e: + error_body = json.loads(e.read()) + error_message = error_body.get('errors', ['Unknown error'])[0] + raise DatadogAPIError(f"Datadog API error: {error_message}") from e + + json_response = json.loads(response.read()) + return json_response["data"]["attributes"]["permissions"] + + def cleanup_existing_policies(iam_client, role_name, account_id, partition, max_policies=10): + # Remove resource collection permissions + for i in range(max_policies): + policy_name = f"{BASE_POLICY_PREFIX_RESOURCE_COLLECTION}-{i+1}" + policy_arn = f"arn:{partition}:iam::{account_id}:policy/{policy_name}" + try: + iam_client.detach_role_policy( + RoleName=role_name, + PolicyArn=policy_arn + ) + except iam_client.exceptions.NoSuchEntityException: + pass + except Exception as e: + LOGGER.error(f"Error detaching policy {policy_name}: {str(e)}") + + try: + iam_client.delete_policy( + PolicyArn=policy_arn + ) + except iam_client.exceptions.NoSuchEntityException: + pass + except iam_client.exceptions.DeleteConflictException: + LOGGER.warning(f"Policy {policy_name} still attached, skipping delete") + except Exception as e: + LOGGER.error(f"Error deleting policy {policy_name}: {str(e)}") + + # Remove standard permissions + try: + iam_client.delete_role_policy( + RoleName=role_name, + PolicyName=POLICY_NAME_STANDARD + ) + except iam_client.exceptions.NoSuchEntityException: + pass + except Exception as e: + LOGGER.error(f"Error deleting inline policy {POLICY_NAME_STANDARD}: {str(e)}") + + def attach_standard_permissions(iam_client, role_name): + permissions = fetch_permissions_from_datadog(STANDARD_PERMISSIONS_API_URL) + policy_document = { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": permissions, + "Resource": "*" + } + ] + } + + iam_client.put_role_policy( + RoleName=role_name, + PolicyName=POLICY_NAME_STANDARD, + PolicyDocument=json.dumps(policy_document, separators=(',', ':')) + ) + + def attach_resource_collection_permissions(iam_client, role_name): + permission_chunks = fetch_permissions_from_datadog(RESOURCE_COLLECTION_PERMISSIONS_API_URL) + + # Create and attach new policies + for i, chunk in enumerate(permission_chunks): + # Create policy + policy_name = f"{BASE_POLICY_PREFIX_RESOURCE_COLLECTION}-{i+1}" + policy_document = { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": chunk, + "Resource": "*" + } + ] + } + policy_json = json.dumps(policy_document, separators=(',', ':')) + policy_size = len(policy_json) + LOGGER.info(f"Creating policy {policy_name} with {len(chunk)} permissions ({policy_size} characters)") + policy = iam_client.create_policy( + PolicyName=policy_name, + PolicyDocument=policy_json + ) + + # Attach policy to role + iam_client.attach_role_policy( + RoleName=role_name, + PolicyArn=policy['Policy']['Arn'] + ) + + def handle_delete(event, context, role_name, account_id, partition): + """Handle stack deletion.""" + iam_client = boto3.client('iam') + try: + cleanup_existing_policies(iam_client, role_name, account_id, partition) + cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData={}) + except Exception as e: + LOGGER.error(f"Error deleting policy: {str(e)}") + cfnresponse.send(event, context, cfnresponse.FAILED, responseData={"Message": str(e)}) + + def handle_create_update(event, context, role_name, account_id, partition, should_install_security_audit_policy): + """Handle stack creation or update.""" + try: + iam_client = boto3.client('iam') + cleanup_existing_policies(iam_client, role_name, account_id, partition) + attach_standard_permissions(iam_client, role_name) + if should_install_security_audit_policy: + attach_resource_collection_permissions(iam_client, role_name) + cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData={}) + except Exception as e: + LOGGER.error(f"Error creating/attaching policy: {str(e)}") + cfnresponse.send(event, context, cfnresponse.FAILED, responseData={"Message": str(e)}) + + def handler(event, context): + LOGGER.info("Event received: %s", json.dumps(event)) + + role_name = event['ResourceProperties']['DatadogIntegrationRole'] + account_id = event['ResourceProperties']['AccountId'] + partition = event['ResourceProperties'].get('Partition', 'aws') + should_install_security_audit_policy = str(event['ResourceProperties']['ResourceCollectionPermissions']).lower() == 'true' + + if event['RequestType'] == 'Delete': + handle_delete(event, context, role_name, account_id, partition) + else: + handle_create_update(event, context, role_name, account_id, partition, should_install_security_audit_policy) + DatadogAttachIntegrationPermissionsFunctionTrigger: + Type: Custom::DatadogAttachIntegrationPermissionsFunctionTrigger + DependsOn: DatadogIntegrationRole Properties: - ManagedPolicyName: !Sub - - "${IAMRoleName}-ManagedPolicy-2" - - { IAMRoleName: !Ref IAMRoleName } - Roles: - - !Ref DatadogIntegrationRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Resource: "*" - Action: - - "ec2:GetVerifiedAccessEndpointTargets" - - "ec2:GetVerifiedAccessGroupPolicy" - - "eks:DescribeAccessEntry" - - "eks:DescribeAddon" - - "eks:DescribeIdentityProviderConfig" - - "eks:DescribeInsight" - - "eks:DescribePodIdentityAssociation" - - "eks:DescribeUpdate" - - "eks:ListAccessEntries" - - "eks:ListAddons" - - "eks:ListAssociatedAccessPolicies" - - "eks:ListEksAnywhereSubscriptions" - - "eks:ListIdentityProviderConfigs" - - "eks:ListInsights" - - "eks:ListPodIdentityAssociations" - - "elasticmapreduce:ListInstanceFleets" - - "elasticmapreduce:ListInstanceGroups" - - "emr-containers:ListManagedEndpoints" - - "emr-containers:ListSecurityConfigurations" - - "emr-containers:ListVirtualClusters" - - "fis:GetAction" - - "fis:GetExperiment" - - "fis:GetExperimentTemplate" - - "fis:ListActions" - - "fis:ListExperimentTemplates" - - "fis:ListExperiments" - - "frauddetector:DescribeDetector" - - "frauddetector:DescribeModelVersions" - - "frauddetector:GetBatchImportJobs" - - "frauddetector:GetBatchPredictionJobs" - - "frauddetector:GetDetectorVersion" - - "frauddetector:GetEntityTypes" - - "frauddetector:GetEventTypes" - - "frauddetector:GetExternalModels" - - "frauddetector:GetLabels" - - "frauddetector:GetListsMetadata" - - "frauddetector:GetModels" - - "frauddetector:GetOutcomes" - - "frauddetector:GetRules" - - "frauddetector:GetVariables" - - "gamelift:DescribeGameSessionQueues" - - "gamelift:DescribeMatchmakingConfigurations" - - "gamelift:DescribeMatchmakingRuleSets" - - "gamelift:ListAliases" - - "gamelift:ListContainerFleets" - - "gamelift:ListContainerGroupDefinitions" - - "gamelift:ListGameServerGroups" - - "gamelift:ListLocations" - - "gamelift:ListScripts" - - "geo:DescribeGeofenceCollection" - - "geo:DescribeKey" - - "geo:DescribeMap" - - "geo:DescribePlaceIndex" - - "geo:DescribeRouteCalculator" - - "geo:DescribeTracker" - - "geo:ListGeofenceCollections" - - "geo:ListKeys" - - "geo:ListPlaceIndexes" - - "geo:ListRouteCalculators" - - "geo:ListTrackers" - - "glacier:GetVaultNotifications" - - "glue:ListRegistries" - - "grafana:DescribeWorkspace" - - "greengrass:GetBulkDeploymentStatus" - - "greengrass:GetComponent" - - "greengrass:GetConnectivityInfo" - - "greengrass:GetCoreDevice" - - "greengrass:GetDeployment" - - "greengrass:GetGroup" - - "imagebuilder:GetContainerRecipe" - - "imagebuilder:GetDistributionConfiguration" - - "imagebuilder:GetImageRecipe" - - "imagebuilder:GetInfrastructureConfiguration" - - "imagebuilder:GetLifecyclePolicy" - - "imagebuilder:GetWorkflow" - - "imagebuilder:ListComponents" - - "imagebuilder:ListContainerRecipes" - - "imagebuilder:ListDistributionConfigurations" - - "imagebuilder:ListImagePipelines" - - "imagebuilder:ListImageRecipes" - - "imagebuilder:ListImages" - - "imagebuilder:ListInfrastructureConfigurations" - - "imagebuilder:ListLifecyclePolicies" - - "imagebuilder:ListWorkflows" - - "iotfleetwise:GetCampaign" - - "iotfleetwise:GetSignalCatalog" - - "iotfleetwise:GetStateTemplate" - - "iotfleetwise:GetVehicle" - - "iotfleetwise:ListCampaigns" - - "iotfleetwise:ListDecoderManifests" - - "iotfleetwise:ListFleets" - - "iotfleetwise:ListSignalCatalogs" - - "iotfleetwise:ListStateTemplates" - - "iotfleetwise:ListVehicles" - - "iotsitewise:DescribeAsset" - - "iotsitewise:DescribeAssetModel" - - "iotsitewise:DescribeDashboard" - - "iotsitewise:DescribeDataset" - - "iotsitewise:DescribePortal" - - "iotsitewise:DescribeProject" - - "iotsitewise:ListAssets" - - "iotsitewise:ListDashboards" - - "iotsitewise:ListDatasets" - - "iotsitewise:ListPortals" - - "iotsitewise:ListProjects" - - "iotsitewise:ListTimeSeries" - - "iottwinmaker:GetComponentType" - - "iottwinmaker:GetEntity" - - "iottwinmaker:GetScene" - - "iottwinmaker:GetWorkspace" - - "iottwinmaker:ListComponentTypes" - - "iottwinmaker:ListEntities" - - "iottwinmaker:ListScenes" - - "iotwireless:GetDeviceProfile" - - "iotwireless:GetMulticastGroup" - - "iotwireless:GetNetworkAnalyzerConfiguration" - - "iotwireless:GetServiceProfile" - - "iotwireless:GetWirelessDevice" - - "iotwireless:GetWirelessGateway" - - "iotwireless:ListDestinations" - - "iotwireless:ListDeviceProfiles" - - "iotwireless:ListMulticastGroups" - - "iotwireless:ListNetworkAnalyzerConfigurations" - - "iotwireless:ListServiceProfiles" - - "iotwireless:ListWirelessDevices" - - "iotwireless:ListWirelessGateways" - - "ivs:GetChannel" - - "ivs:GetComposition" - - "ivs:GetEncoderConfiguration" - - "ivs:GetIngestConfiguration" - - "ivs:GetPublicKey" - - "ivs:GetRecordingConfiguration" - - "ivs:GetStage" - - "ivs:ListChannels" - - "ivs:ListCompositions" - - "ivs:ListEncoderConfigurations" - - "ivs:ListIngestConfigurations" - - "ivs:ListPlaybackKeyPairs" - - "ivs:ListPlaybackRestrictionPolicies" - - "ivs:ListPublicKeys" - - "ivs:ListRecordingConfigurations" - - "ivs:ListStages" - - "ivs:ListStorageConfigurations" - - "ivs:ListStreamKeys" - - "ivschat:GetLoggingConfiguration" - - "ivschat:GetRoom" - - "ivschat:ListLoggingConfigurations" - - "ivschat:ListRooms" - - "kendra:DescribeAccessControlConfiguration" - - "kendra:DescribeDataSource" - - "kendra:DescribeExperience" - - "kendra:DescribeFaq" - - "kendra:DescribeFeaturedResultsSet" - - "kendra:DescribeQuerySuggestionsBlockList" - - "kendra:DescribeThesaurus" - - "kendra:ListAccessControlConfigurations" - - "kendra:ListExperiences" - - "kendra:ListFaqs" - - "kendra:ListFeaturedResultsSets" - - "kendra:ListQuerySuggestionsBlockLists" - - "kendra:ListThesauri" - - "lakeformation:GetDataLakeSettings" - - "lakeformation:ListPermissions" - - "lambda:GetFunction" - - "launchwizard:GetDeployment" - - "launchwizard:ListDeployments" - - "lightsail:GetAlarms" - - "lightsail:GetCertificates" - - "lightsail:GetDistributions" - - "lightsail:GetInstancePortStates" - - "lightsail:GetRelationalDatabaseParameters" - - "lightsail:GetRelationalDatabaseSnapshots" - - "lightsail:GetRelationalDatabases" - - "lightsail:GetStaticIps" - - "macie2:GetAllowList" - - "macie2:GetCustomDataIdentifier" - - "macie2:GetMacieSession" - - "macie2:ListAllowLists" - - "macie2:ListCustomDataIdentifiers" - - "macie2:ListMembers" - - "managedblockchain:GetAccessor" - - "managedblockchain:GetMember" - - "managedblockchain:GetNetwork" - - "managedblockchain:GetNode" - - "managedblockchain:GetProposal" - DatadogIntegrationRoleManagedPolicy3: - Type: "AWS::IAM::ManagedPolicy" - Condition: ShouldInstallSecurityAuditPolicy - Properties: - ManagedPolicyName: !Sub - - "${IAMRoleName}-ManagedPolicy-3" - - { IAMRoleName: !Ref IAMRoleName } - Roles: - - !Ref DatadogIntegrationRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Resource: "*" - Action: - - "managedblockchain:ListAccessors" - - "managedblockchain:ListInvitations" - - "managedblockchain:ListMembers" - - "managedblockchain:ListNodes" - - "managedblockchain:ListProposals" - - "mediaconvert:ListJobTemplates" - - "mediaconvert:ListPresets" - - "mediaconvert:ListQueues" - - "medialive:ListChannelPlacementGroups" - - "medialive:ListCloudWatchAlarmTemplateGroups" - - "medialive:ListCloudWatchAlarmTemplates" - - "medialive:ListClusters" - - "medialive:ListEventBridgeRuleTemplateGroups" - - "medialive:ListEventBridgeRuleTemplates" - - "medialive:ListInputDevices" - - "medialive:ListInputSecurityGroups" - - "medialive:ListInputs" - - "medialive:ListMultiplexes" - - "medialive:ListNetworks" - - "medialive:ListNodes" - - "medialive:ListReservations" - - "medialive:ListSdiSources" - - "medialive:ListSignalMaps" - - "mediapackage-vod:DescribeAsset" - - "mediapackage-vod:ListAssets" - - "mediapackage-vod:ListPackagingConfigurations" - - "mediapackage:ListChannels" - - "mediapackage:ListHarvestJobs" - - "mediapackagev2:GetChannel" - - "mediapackagev2:GetChannelGroup" - - "mediapackagev2:GetChannelPolicy" - - "mediapackagev2:GetOriginEndpoint" - - "mediapackagev2:GetOriginEndpointPolicy" - - "mediapackagev2:ListChannelGroups" - - "mediapackagev2:ListChannels" - - "mediapackagev2:ListHarvestJobs" - - "mediapackagev2:ListOriginEndpoints" - - "mediatailor:ListChannels" - - "mediatailor:ListLiveSources" - - "mediatailor:ListPlaybackConfigurations" - - "mediatailor:ListPrefetchSchedules" - - "mediatailor:ListSourceLocations" - - "mediatailor:ListVodSources" - - "memorydb:DescribeAcls" - - "memorydb:DescribeMultiRegionClusters" - - "memorydb:DescribeParameterGroups" - - "memorydb:DescribeReservedNodes" - - "memorydb:DescribeSnapshots" - - "memorydb:DescribeSubnetGroups" - - "memorydb:DescribeUsers" - - "mobiletargeting:GetApps" - - "mobiletargeting:GetCampaigns" - - "mobiletargeting:GetChannels" - - "mobiletargeting:GetEventStream" - - "mobiletargeting:GetSegments" - - "mobiletargeting:ListJourneys" - - "mobiletargeting:ListTemplates" - - "network-firewall:DescribeTLSInspectionConfiguration" - - "network-firewall:DescribeVpcEndpointAssociation" - - "network-firewall:ListTLSInspectionConfigurations" - - "network-firewall:ListVpcEndpointAssociations" - - "networkmanager:GetConnectPeer" - - "networkmanager:GetConnections" - - "networkmanager:GetCoreNetwork" - - "networkmanager:GetDevices" - - "networkmanager:GetLinks" - - "networkmanager:GetSites" - - "networkmanager:ListAttachments" - - "networkmanager:ListConnectPeers" - - "networkmanager:ListCoreNetworks" - - "networkmanager:ListPeerings" - - "omics:GetAnnotationStore" - - "omics:GetAnnotationStoreVersion" - - "omics:GetSequenceStore" - - "omics:GetVariantStore" - - "omics:GetWorkflow" - - "omics:GetWorkflowVersion" - - "omics:ListAnnotationStoreVersions" - - "omics:ListAnnotationStores" - - "omics:ListReadSets" - - "omics:ListReferenceStores" - - "omics:ListReferences" - - "omics:ListSequenceStores" - - "omics:ListVariantStores" - - "omics:ListWorkflowVersions" - - "omics:ListWorkflows" - - "osis:GetPipeline" - - "osis:GetPipelineBlueprint" - - "osis:ListPipelineBlueprints" - - "osis:ListPipelines" - - 'outposts:ListOutposts' - - 'outposts:ListSites' - - "payment-cryptography:GetKey" - - "payment-cryptography:ListAliases" - - "payment-cryptography:ListKeys" - - "pca-connector-ad:ListConnectors" - - "pca-connector-ad:ListDirectoryRegistrations" - - "pca-connector-ad:ListTemplates" - - "pca-connector-scep:ListConnectors" - - "personalize:DescribeAlgorithm" - - "personalize:DescribeBatchInferenceJob" - - "personalize:DescribeBatchSegmentJob" - - "personalize:DescribeCampaign" - - "personalize:DescribeDataDeletionJob" - - "personalize:DescribeDataset" - - "personalize:DescribeDatasetExportJob" - - "personalize:DescribeDatasetImportJob" - - "personalize:DescribeEventTracker" - - "personalize:DescribeFeatureTransformation" - - "personalize:DescribeFilter" - - "personalize:DescribeMetricAttribution" - - "personalize:DescribeRecipe" - - "personalize:DescribeRecommender" - - "personalize:DescribeSchema" - - "personalize:DescribeSolution" - - "personalize:ListBatchInferenceJobs" - - "personalize:ListBatchSegmentJobs" - - "personalize:ListCampaigns" - - "personalize:ListDataDeletionJobs" - - "personalize:ListDatasetExportJobs" - - "personalize:ListDatasetImportJobs" - - "personalize:ListDatasets" - - "personalize:ListEventTrackers" - - "personalize:ListFilters" - - "personalize:ListMetricAttributions" - - "personalize:ListRecipes" - - "personalize:ListRecommenders" - - "personalize:ListSchemas" - - "personalize:ListSolutions" - - "pipes:ListPipes" - - "proton:GetComponent" - - "proton:GetDeployment" - - "proton:GetEnvironment" - - "proton:GetEnvironmentAccountConnection" - - "proton:GetEnvironmentTemplate" - - "proton:GetEnvironmentTemplateVersion" - - "proton:GetRepository" - - "proton:GetService" - - "proton:GetServiceInstance" - - "proton:GetServiceTemplate" - - "proton:GetServiceTemplateVersion" - - "proton:ListComponents" - - "proton:ListDeployments" - - "proton:ListEnvironmentAccountConnections" - - "proton:ListEnvironmentTemplateVersions" - - "proton:ListEnvironmentTemplates" - - "proton:ListEnvironments" - - "proton:ListRepositories" - - "proton:ListServiceInstances" - - "proton:ListServiceTemplateVersions" - - "proton:ListServiceTemplates" - - "proton:ListServices" - - "qbusiness:GetApplication" - - "qbusiness:GetDataAccessor" - - "qbusiness:GetDataSource" - - "qbusiness:GetIndex" - - "qbusiness:GetPlugin" - - "qbusiness:GetRetriever" - - "qbusiness:GetWebExperience" - - "qbusiness:ListDataAccessors" - - "ram:GetResourceShareInvitations" - - "rbin:GetRule" - - "rbin:ListRules" - - "redshift-serverless:GetSnapshot" - - "redshift-serverless:ListEndpointAccess" - - "redshift-serverless:ListManagedWorkgroups" - - "redshift-serverless:ListNamespaces" - - "redshift-serverless:ListRecoveryPoints" - - "redshift-serverless:ListSnapshots" - - "refactor-spaces:ListApplications" - - "refactor-spaces:ListEnvironments" - - "refactor-spaces:ListRoutes" - - "refactor-spaces:ListServices" - DatadogIntegrationRoleManagedPolicy4: - Type: "AWS::IAM::ManagedPolicy" - Condition: ShouldInstallSecurityAuditPolicy - Properties: - ManagedPolicyName: !Sub - - "${IAMRoleName}-ManagedPolicy-4" - - { IAMRoleName: !Ref IAMRoleName } - Roles: - - !Ref DatadogIntegrationRole - PolicyDocument: - Version: 2012-10-17 - Statement: - - Effect: Allow - Resource: "*" - Action: - - "resiliencehub:DescribeApp" - - "resiliencehub:DescribeAppAssessment" - - "resiliencehub:ListAppAssessments" - - "resiliencehub:ListApps" - - "resiliencehub:ListResiliencyPolicies" - - "resource-explorer-2:GetIndex" - - "resource-explorer-2:GetManagedView" - - "resource-explorer-2:GetView" - - "resource-explorer-2:ListManagedViews" - - "resource-explorer-2:ListViews" - - "resource-groups:GetGroup" - - "resource-groups:ListGroups" - - "route53-recovery-readiness:ListCells" - - "route53-recovery-readiness:ListReadinessChecks" - - "route53-recovery-readiness:ListRecoveryGroups" - - "route53-recovery-readiness:ListResourceSets" - - "route53profiles:GetProfile" - - "route53profiles:ListProfileAssociations" - - "route53profiles:ListProfiles" - - "rum:GetAppMonitor" - - "rum:ListAppMonitors" - - "s3-outposts:ListRegionalBuckets" - - "scheduler:GetSchedule" - - "scheduler:ListScheduleGroups" - - "scheduler:ListSchedules" - - "securitylake:ListDataLakes" - - "securitylake:ListSubscribers" - - "serverlessrepo:GetApplication" - - "servicecatalog:DescribePortfolio" - - "servicecatalog:DescribeProduct" - - "servicecatalog:GetApplication" - - "servicecatalog:GetAttributeGroup" - - "servicecatalog:ListApplications" - - "servicecatalog:ListAttributeGroups" - - "servicecatalog:ListPortfolios" - - "servicecatalog:SearchProducts" - - "servicediscovery:GetNamespace" - - "servicediscovery:GetService" - - "servicediscovery:ListNamespaces" - - "servicediscovery:ListServices" - - "ses:GetArchive" - - "ses:GetContactList" - - "ses:GetCustomVerificationEmailTemplate" - - "ses:GetDedicatedIpPool" - - "ses:GetIdentityMailFromDomainAttributes" - - "ses:GetIngressPoint" - - "ses:GetMultiRegionEndpoint" - - "ses:GetRelay" - - "ses:GetRuleSet" - - "ses:GetTemplate" - - "ses:GetTrafficPolicy" - - "ses:ListAddonInstances" - - "ses:ListAddonSubscriptions" - - "ses:ListAddressLists" - - "ses:ListArchives" - - "ses:ListContactLists" - - "ses:ListCustomVerificationEmailTemplates" - - "ses:ListIngressPoints" - - "ses:ListMultiRegionEndpoints" - - "ses:ListRelays" - - "ses:ListRuleSets" - - "ses:ListTemplates" - - "ses:ListTrafficPolicies" - - "signer:GetSigningProfile" - - "signer:ListSigningProfiles" - - "sms-voice:DescribeConfigurationSets" - - "sms-voice:DescribeOptOutLists" - - "sms-voice:DescribePhoneNumbers" - - "sms-voice:DescribePools" - - "sms-voice:DescribeProtectConfigurations" - - "sms-voice:DescribeRegistrationAttachments" - - "sms-voice:DescribeRegistrations" - - "sms-voice:DescribeSenderIds" - - "sms-voice:DescribeVerifiedDestinationNumbers" - - "snowball:DescribeCluster" - - "snowball:DescribeJob" - - "sns:ListPlatformApplications" - - "social-messaging:GetLinkedWhatsAppBusinessAccount" - - "social-messaging:ListLinkedWhatsAppBusinessAccounts" - - "sqs:GetQueueUrl" - - "ssm-incidents:GetIncidentRecord" - - "ssm-incidents:GetReplicationSet" - - "ssm-incidents:GetResponsePlan" - - "ssm-incidents:ListIncidentRecords" - - "ssm-incidents:ListReplicationSets" - - "ssm-incidents:ListResponsePlans" - - "ssm:GetMaintenanceWindow" - - "ssm:GetPatchBaseline" - - "states:ListActivities" - - "states:ListExecutions" - - "states:ListStateMachineAliases" - - "storagegateway:DescribeFileSystemAssociations" - - "storagegateway:DescribeSMBFileShares" - - "textract:GetAdapter" - - "textract:GetAdapterVersion" - - "textract:ListAdapterVersions" - - "textract:ListAdapters" - - "timestream:ListScheduledQueries" - - "timestream:ListTables" - - "transcribe:GetCallAnalyticsJob" - - "transcribe:GetMedicalScribeJob" - - "transcribe:GetMedicalTranscriptionJob" - - "transcribe:GetTranscriptionJob" - - "transcribe:ListMedicalScribeJobs" - - "translate:GetParallelData" - - "translate:GetTerminology" - - "verifiedpermissions:GetPolicyStore" - - "verifiedpermissions:ListIdentitySources" - - "verifiedpermissions:ListPolicies" - - "verifiedpermissions:ListPolicyStores" - - "verifiedpermissions:ListPolicyTemplates" - - "vpc-lattice:GetListener" - - "vpc-lattice:GetResourceConfiguration" - - "vpc-lattice:GetResourceGateway" - - "vpc-lattice:GetRule" - - "vpc-lattice:GetService" - - "vpc-lattice:GetServiceNetwork" - - "vpc-lattice:GetTargetGroup" - - "vpc-lattice:ListAccessLogSubscriptions" - - "vpc-lattice:ListListeners" - - "vpc-lattice:ListResourceConfigurations" - - "vpc-lattice:ListResourceEndpointAssociations" - - "vpc-lattice:ListResourceGateways" - - "vpc-lattice:ListRules" - - "vpc-lattice:ListServiceNetworkResourceAssociations" - - "vpc-lattice:ListServiceNetworkServiceAssociations" - - "vpc-lattice:ListServiceNetworkVpcAssociations" - - "vpc-lattice:ListServiceNetworks" - - "vpc-lattice:ListServices" - - "vpc-lattice:ListTargetGroups" - - "waf-regional:GetRule" - - "waf-regional:GetRuleGroup" - - "waf-regional:ListRuleGroups" - - "waf-regional:ListRules" - - "waf:GetRule" - - "waf:GetRuleGroup" - - "waf:ListRuleGroups" - - "waf:ListRules" - - "wafv2:GetIPSet" - - "wafv2:GetRegexPatternSet" - - "wafv2:GetRuleGroup" - - "wellarchitected:GetLens" - - "wellarchitected:GetProfile" - - "wellarchitected:GetReviewTemplate" - - "wellarchitected:GetWorkload" - - "wellarchitected:ListLenses" - - "wellarchitected:ListProfiles" - - "wellarchitected:ListReviewTemplates" - - "wellarchitected:ListWorkloads" - - "wisdom:ListAssistantAssociations" - - "wisdom:ListAssistants" - - "wisdom:ListContents" - - "wisdom:ListKnowledgeBases" - - "wisdom:ListQuickResponses" - - "workmail:DescribeOrganization" - - "workmail:ListOrganizations" - - "workspaces-web:GetBrowserSettings" - - "workspaces-web:GetDataProtectionSettings" - - "workspaces-web:GetIdentityProvider" - - "workspaces-web:GetIpAccessSettings" - - "workspaces-web:GetNetworkSettings" - - "workspaces-web:GetTrustStore" - - "workspaces-web:GetUserAccessLoggingSettings" - - "workspaces-web:GetUserSettings" - - "workspaces-web:ListBrowserSettings" - - "workspaces-web:ListDataProtectionSettings" - - "workspaces-web:ListIdentityProviders" - - "workspaces-web:ListIpAccessSettings" - - "workspaces-web:ListNetworkSettings" - - "workspaces-web:ListPortals" - - "workspaces-web:ListTrustStores" - - "workspaces-web:ListUserAccessLoggingSettings" - - "workspaces-web:ListUserSettings" + ServiceToken: !GetAtt DatadogAttachIntegrationPermissionsFunction.Arn + DatadogIntegrationRole: !Ref IAMRoleName + AccountId: !Ref AWS::AccountId + Partition: !Sub "${AWS::Partition}" + ResourceCollectionPermissions: !Ref ResourceCollectionPermissions Metadata: AWS::CloudFormation::Interface: ParameterGroups: diff --git a/aws_quickstart/version.txt b/aws_quickstart/version.txt index 6062a5e..37c93be 100644 --- a/aws_quickstart/version.txt +++ b/aws_quickstart/version.txt @@ -1 +1 @@ -v4.3.1 +v4.4.0