From 2cad9602fe8cc1434c74eb6068c1b4ccc05854b0 Mon Sep 17 00:00:00 2001 From: lorenzo merici Date: Wed, 9 Apr 2025 16:08:45 +0200 Subject: [PATCH 01/12] add cross account support --- modules/log_ingestion.s3.cft.yaml | 280 ++++++++++++++++++++++++++++-- 1 file changed, 267 insertions(+), 13 deletions(-) diff --git a/modules/log_ingestion.s3.cft.yaml b/modules/log_ingestion.s3.cft.yaml index b88ad75..a4f6bfb 100644 --- a/modules/log_ingestion.s3.cft.yaml +++ b/modules/log_ingestion.s3.cft.yaml @@ -1,8 +1,8 @@ AWSTemplateFormatVersion: "2010-09-09" Description: > - CloudFormation organizational template for provisioning the necessary resources - for the `cloud-logs` component and the read-only role required to interact with - the target organizational environment. + CloudFormation template for provisioning the necessary resources + for the `cloud-logs` component, allowing Sysdig to access CloudTrail logs in S3 buckets. + Supports single-account, organizational same-account, and organizational cross-account deployments. Metadata: AWS::CloudFormation::Interface: @@ -14,9 +14,13 @@ Metadata: - ExternalID - TrustedIdentity - BucketARN + - KMSKeyARN + - BucketAccountId + - OrganizationalUnitIds - CreateTopic - TopicARN - Endpoint + - Partition ParameterLabels: NameSuffix: @@ -27,12 +31,20 @@ Metadata: default: Trusted Identity BucketARN: default: Bucket ARN + KMSKeyARN: + default: KMS Key ARN + BucketAccountId: + default: Bucket Account ID + OrganizationalUnitIds: + default: Organizational Unit IDs CreateTopic: default: Create SNS Topic TopicARN: default: SNS Topic ARN Endpoint: default: Sysdig Secure endpoint + Partition: + default: AWS Partition Parameters: NameSuffix: @@ -50,6 +62,19 @@ Parameters: BucketARN: Type: String Description: The ARN of your S3 bucket associated with your CloudTrail trail logs. + AllowedPattern: 'arn:(aws|aws-us-gov):s3:::.*' + KMSKeyARN: + Type: String + Description: The ARN of the KMS key used to encrypt the S3 bucket. + Default: "" + BucketAccountId: + Type: String + Description: The AWS Account ID that owns the S3 bucket, if different from the current account. + Default: "" + OrganizationalUnitIds: + Type: String + Description: Comma-separated list of AWS Organizations organizational unit (OU) IDs for cross-account deployments. + Default: "root" CreateTopic: Type: String AllowedValues: @@ -63,12 +88,32 @@ Parameters: Endpoint: Type: String Description: Sysdig Secure endpoint to receive CloudTrail notifications. + Partition: + Type: String + Description: AWS Partition of your account or organization to create resources in + Default: 'aws' + +Conditions: + CreateSNSTopic: !Equals [ !Ref CreateTopic, "true" ] + HasKMSKey: !Not [ !Equals [ !Ref KMSKeyARN, "" ] ] + # Matches Terraform's: is_cross_account = var.bucket_account_id != null && var.bucket_account_id != data.aws_caller_identity.current.account_id + IsCrossAccount: !And [ + !Not [ !Equals [ !Ref BucketAccountId, "" ] ], + !Not [ !Equals [ !Ref BucketAccountId, !Ref "AWS::AccountId" ] ] + ] + NotIsCrossAccount: !Not [IsCrossAccount] + HasKMSAndNotCrossAccount: !And [HasKMSKey, NotIsCrossAccount] + HasKMSAndIsCrossAccount: !And [HasKMSKey, IsCrossAccount] + IsTopicAccount: !Equals [ !Select [4, !Split [":", !Ref TopicARN]], !Ref "AWS::AccountId" ] + IsBucketAccount: !Equals [ !Ref BucketAccountId, !Ref "AWS::AccountId" ] Resources: + # Role and resources for same-account deployments CloudLogsRole: Type: "AWS::IAM::Role" + Condition: NotIsCrossAccount Properties: - RoleName: !Sub sysdig-secure-cloudlogs-${NameSuffix} + RoleName: !Sub sysdig-secure-cloudlogs-${NameSuffix} AssumeRolePolicyDocument: Version: "2012-10-17" Statement: @@ -85,20 +130,29 @@ Resources: PolicyDocument: Version: "2012-10-17" Statement: - - Sid: "CloudlogsS3AccessGet" + - Sid: "CloudlogsS3Access" Effect: "Allow" Action: - "s3:Get*" - Resource: - - !Sub '${BucketARN}' - - !Sub '${BucketARN}/*' - - Sid: "CloudlogsS3AccessList" - Effect: "Allow" - Action: - "s3:List*" Resource: - !Sub '${BucketARN}' - !Sub '${BucketARN}/*' + - !If + - HasKMSKey + - Sid: "CloudlogsKMSDecrypt" + Effect: "Allow" + Action: + - "kms:Decrypt" + Resource: !Ref KMSKeyARN + - !Ref "AWS::NoValue" + Tags: + - Key: "Name" + Value: "Sysdig Secure CloudTrail Logs Access Role" + - Key: "Purpose" + Value: "Allow Sysdig to access S3 bucket for CloudTrail logs" + - Key: "product" + Value: "sysdig-secure-for-cloud" CloudTrailNotificationsTopic: Condition: CreateSNSTopic @@ -129,10 +183,210 @@ Resources: Action: "SNS:Publish" Resource: !Ref CloudTrailNotificationsTopic -Conditions: - CreateSNSTopic: !Equals [ !Ref CreateTopic, "true" ] + # StackSet for cross-account bucket access + BucketAccessStackSet: + Type: AWS::CloudFormation::StackSet + Condition: IsCrossAccount + Properties: + StackSetName: !Sub sysdig-secure-cloudlogs-bucket-access-${NameSuffix} + Description: IAM Role for S3 bucket and KMS access for Sysdig Cloud Logs integration + PermissionModel: SERVICE_MANAGED + AutoDeployment: + Enabled: false + ManagedExecution: + Active: true + Capabilities: + - "CAPABILITY_NAMED_IAM" + OperationPreferences: + MaxConcurrentPercentage: 100 + FailureTolerancePercentage: 90 + ConcurrencyMode: SOFT_FAILURE_TOLERANCE + Parameters: + - ParameterKey: RoleName + ParameterValue: !Sub sysdig-secure-cloudlogs-${AWS::AccountId}-${NameSuffix} + - ParameterKey: TrustedIdentity + ParameterValue: !Ref TrustedIdentity + - ParameterKey: ExternalID + ParameterValue: !Ref ExternalID + - ParameterKey: BucketARN + ParameterValue: !Ref BucketARN + - ParameterKey: KMSKeyARN + ParameterValue: !Ref KMSKeyARN + - ParameterKey: BucketAccountId + ParameterValue: !Ref BucketAccountId + - ParameterKey: TopicARN + ParameterValue: !Ref TopicARN + - ParameterKey: Endpoint + ParameterValue: !Ref Endpoint + StackInstancesGroup: + - DeploymentTargets: + OrganizationalUnitIds: !Split [",", !Ref OrganizationalUnitIds] + Accounts: [!Ref BucketAccountId] + Regions: [!Ref "AWS::Region"] + - DeploymentTargets: + OrganizationalUnitIds: !Split [",", !Ref OrganizationalUnitIds] + Accounts: [!Select [4, !Split [":", !Ref TopicARN]]] # Extract account ID from topic ARN + Regions: [!Select [3, !Split [":", !Ref TopicARN]]] # Extract region from topic ARN + TemplateBody: | + AWSTemplateFormatVersion: "2010-09-09" + Description: IAM Role for S3 bucket and KMS access for Sysdig Cloud Logs integration + Parameters: + RoleName: + Type: String + Description: Name of the role to be created in the bucket account + TrustedIdentity: + Type: String + Description: ARN of the Sysdig service that needs to assume the role + ExternalID: + Type: String + Description: External ID for secure role assumption by Sysdig + BucketARN: + Type: String + Description: ARN of the S3 bucket containing CloudTrail logs + KMSKeyARN: + Type: String + Description: ARN of the KMS key used for encryption + Default: "" + BucketAccountId: + Type: String + Description: AWS Account ID that owns the S3 bucket + TopicARN: + Type: String + Description: ARN of the SNS topic + Endpoint: + Type: String + Description: Sysdig Secure endpoint to receive CloudTrail notifications + Conditions: + IsBucketAccount: !Equals [ !Ref BucketAccountId, !Ref "AWS::AccountId" ] + IsTopicAccount: !Equals [ !Ref TopicAccountId, !Ref "AWS::AccountId" ] + HasKMSKey: !Not [ !Equals [ !Ref KMSKeyARN, "" ] ] + Resources: + S3AccessRole: + Type: AWS::IAM::Role + Condition: IsBucketAccount + Properties: + RoleName: !Ref RoleName + AssumeRolePolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: "Allow" + Principal: + AWS: !Ref TrustedIdentity + Action: "sts:AssumeRole" + Condition: + StringEquals: + "sts:ExternalId": !Ref ExternalID + Policies: + - PolicyName: "cloudlogs_s3_access_policy" + PolicyDocument: + Version: "2012-10-17" + Statement: + - Sid: "S3BucketListAccess" + Effect: "Allow" + Action: + - "s3:ListBucket" + - "s3:GetBucketLocation" + Resource: + - !Ref BucketARN + - Sid: "S3ObjectAccess" + Effect: "Allow" + Action: + - "s3:GetObject" + Resource: + - !Sub "${BucketARN}/*" + - !If + - HasKMSKey + - Sid: "KMSDecryptAccess" + Effect: "Allow" + Action: "kms:Decrypt" + Resource: !Ref KMSKeyARN + - !Ref "AWS::NoValue" + Tags: + - Key: "Name" + Value: "Sysdig Secure CloudTrail Logs Access Role" + - Key: "Purpose" + Value: "Allow Sysdig to access S3 bucket for CloudTrail logs" + - Key: "product" + Value: "sysdig-secure-for-cloud" + + CloudTrailSNSSubscription: + Type: AWS::SNS::Subscription + Condition: IsTopicAccount + Properties: + TopicArn: !Ref TopicARN + Protocol: "https" + Endpoint: !Ref Endpoint + Outputs: + S3AccessRoleArn: + Description: ARN of the IAM role created in the bucket account for S3 access + Value: !GetAtt S3AccessRole.Arn + KMSPolicyInstructions: + Description: Instructions for updating KMS key policy when KMS encryption is enabled + Condition: HasKMSKey + Value: !Sub | + IMPORTANT: MANUAL ACTION REQUIRED + + Please add the following statement to your KMS key policy to allow Sysdig to decrypt logs. + This is necessary when KMS encryption is enabled for your S3 bucket. + Without this policy addition, Sysdig may not be able to read your encrypted logs. + + { + "Sid": "Sysdig-Decrypt", + "Effect": "Allow", + "Principal": { + "AWS": "${S3AccessRole.Arn}" + }, + "Action": "kms:Decrypt", + "Resource": "*" + } Outputs: TopicARN: Description: "The ARN of the SNS Topic created for CloudTrail notifications." Value: !If [ CreateSNSTopic, !Ref CloudTrailNotificationsTopic, !Ref TopicARN ] + RoleARN: + Description: "The ARN of the IAM Role created for CloudTrail logs access." + Condition: NotIsCrossAccount + Value: !GetAtt CloudLogsRole.Arn + CrossAccountRoleARN: + Description: "ARN of the Cross-Account IAM Role for accessing the S3 bucket." + Condition: IsCrossAccount + Value: !Sub "arn:${Partition}:iam::${BucketAccountId}:role/sysdig-secure-cloudlogs-${AWS::AccountId}-${NameSuffix}" + KMSPolicyInstructionsSameAccount: + Description: "Instructions for updating KMS key policy when KMS encryption is enabled" + Condition: HasKMSAndNotCrossAccount + Value: !Sub | + IMPORTANT: MANUAL ACTION REQUIRED + + Please add the following statement to your KMS key policy to allow Sysdig to decrypt logs. + This is necessary when KMS encryption is enabled for your S3 bucket. + Without this policy addition, Sysdig may not be able to read your encrypted logs. + + { + "Sid": "Sysdig-Decrypt", + "Effect": "Allow", + "Principal": { + "AWS": "${CloudLogsRole.Arn}" + }, + "Action": "kms:Decrypt", + "Resource": "*" + } + KMSPolicyInstructionsCrossAccount: + Description: "Instructions for updating KMS key policy when KMS encryption is enabled (Cross-Account)" + Condition: HasKMSAndIsCrossAccount + Value: !Sub | + IMPORTANT: MANUAL ACTION REQUIRED + + Please add the following statement to your KMS key policy to allow Sysdig to decrypt logs. + This is necessary when KMS encryption is enabled for your S3 bucket. + Without this policy addition, Sysdig may not be able to read your encrypted logs. + + { + "Sid": "Sysdig-Decrypt", + "Effect": "Allow", + "Principal": { + "AWS": "arn:${Partition}:iam::${BucketAccountId}:role/sysdig-secure-cloudlogs-${AWS::AccountId}-${NameSuffix}" + }, + "Action": "kms:Decrypt", + "Resource": "*" + } From 1717770c50c58bb58ffae2798af2bdc5c2dc9424 Mon Sep 17 00:00:00 2001 From: lorenzo merici Date: Wed, 9 Apr 2025 18:03:59 +0200 Subject: [PATCH 02/12] update conditions naming --- modules/log_ingestion.s3.cft.yaml | 47 +++++++++++-------------------- 1 file changed, 16 insertions(+), 31 deletions(-) diff --git a/modules/log_ingestion.s3.cft.yaml b/modules/log_ingestion.s3.cft.yaml index a4f6bfb..47a6297 100644 --- a/modules/log_ingestion.s3.cft.yaml +++ b/modules/log_ingestion.s3.cft.yaml @@ -96,14 +96,18 @@ Parameters: Conditions: CreateSNSTopic: !Equals [ !Ref CreateTopic, "true" ] HasKMSKey: !Not [ !Equals [ !Ref KMSKeyARN, "" ] ] - # Matches Terraform's: is_cross_account = var.bucket_account_id != null && var.bucket_account_id != data.aws_caller_identity.current.account_id - IsCrossAccount: !And [ + BucketCrossAccount: !And [ !Not [ !Equals [ !Ref BucketAccountId, "" ] ], !Not [ !Equals [ !Ref BucketAccountId, !Ref "AWS::AccountId" ] ] ] - NotIsCrossAccount: !Not [IsCrossAccount] - HasKMSAndNotCrossAccount: !And [HasKMSKey, NotIsCrossAccount] - HasKMSAndIsCrossAccount: !And [HasKMSKey, IsCrossAccount] + BucketInTargetAccount: !Not [BucketCrossAccount] + # Extract KMS account ID from KMS key ARN + KMSAccountId: !Select [4, !Split [":", !Ref KMSKeyARN]] + # Check if KMS key is in a different account from bucket + NeedKMSPolicy: !And [ + HasKMSKey, + !Equals [ !Ref KMSAccountId, !Ref BucketAccountId ] + ] IsTopicAccount: !Equals [ !Select [4, !Split [":", !Ref TopicARN]], !Ref "AWS::AccountId" ] IsBucketAccount: !Equals [ !Ref BucketAccountId, !Ref "AWS::AccountId" ] @@ -111,7 +115,7 @@ Resources: # Role and resources for same-account deployments CloudLogsRole: Type: "AWS::IAM::Role" - Condition: NotIsCrossAccount + Condition: BucketInTargetAccount Properties: RoleName: !Sub sysdig-secure-cloudlogs-${NameSuffix} AssumeRolePolicyDocument: @@ -186,7 +190,7 @@ Resources: # StackSet for cross-account bucket access BucketAccessStackSet: Type: AWS::CloudFormation::StackSet - Condition: IsCrossAccount + Condition: BucketCrossAccount Properties: StackSetName: !Sub sysdig-secure-cloudlogs-bucket-access-${NameSuffix} Description: IAM Role for S3 bucket and KMS access for Sysdig Cloud Logs integration @@ -346,20 +350,20 @@ Outputs: Value: !If [ CreateSNSTopic, !Ref CloudTrailNotificationsTopic, !Ref TopicARN ] RoleARN: Description: "The ARN of the IAM Role created for CloudTrail logs access." - Condition: NotIsCrossAccount + Condition: BucketInTargetAccount Value: !GetAtt CloudLogsRole.Arn CrossAccountRoleARN: Description: "ARN of the Cross-Account IAM Role for accessing the S3 bucket." - Condition: IsCrossAccount + Condition: BucketCrossAccount Value: !Sub "arn:${Partition}:iam::${BucketAccountId}:role/sysdig-secure-cloudlogs-${AWS::AccountId}-${NameSuffix}" - KMSPolicyInstructionsSameAccount: + KMSPolicyInstructions: Description: "Instructions for updating KMS key policy when KMS encryption is enabled" - Condition: HasKMSAndNotCrossAccount + Condition: NeedKMSPolicy Value: !Sub | IMPORTANT: MANUAL ACTION REQUIRED Please add the following statement to your KMS key policy to allow Sysdig to decrypt logs. - This is necessary when KMS encryption is enabled for your S3 bucket. + This is necessary when KMS encryption is enabled for your S3 bucket and the KMS key is in a different account. Without this policy addition, Sysdig may not be able to read your encrypted logs. { @@ -371,22 +375,3 @@ Outputs: "Action": "kms:Decrypt", "Resource": "*" } - KMSPolicyInstructionsCrossAccount: - Description: "Instructions for updating KMS key policy when KMS encryption is enabled (Cross-Account)" - Condition: HasKMSAndIsCrossAccount - Value: !Sub | - IMPORTANT: MANUAL ACTION REQUIRED - - Please add the following statement to your KMS key policy to allow Sysdig to decrypt logs. - This is necessary when KMS encryption is enabled for your S3 bucket. - Without this policy addition, Sysdig may not be able to read your encrypted logs. - - { - "Sid": "Sysdig-Decrypt", - "Effect": "Allow", - "Principal": { - "AWS": "arn:${Partition}:iam::${BucketAccountId}:role/sysdig-secure-cloudlogs-${AWS::AccountId}-${NameSuffix}" - }, - "Action": "kms:Decrypt", - "Resource": "*" - } From eb5a0f6c72422d2cab9aea654f75b7e1960298b8 Mon Sep 17 00:00:00 2001 From: lorenzo merici Date: Thu, 10 Apr 2025 11:41:09 +0200 Subject: [PATCH 03/12] fix cross account --- modules/log_ingestion.s3.cft.yaml | 89 ++++++++++++++++++------------- 1 file changed, 51 insertions(+), 38 deletions(-) diff --git a/modules/log_ingestion.s3.cft.yaml b/modules/log_ingestion.s3.cft.yaml index 47a6297..9621b4f 100644 --- a/modules/log_ingestion.s3.cft.yaml +++ b/modules/log_ingestion.s3.cft.yaml @@ -15,12 +15,15 @@ Metadata: - TrustedIdentity - BucketARN - KMSKeyARN + - KMSAccountId - BucketAccountId + - TopicAccountId - OrganizationalUnitIds - CreateTopic - TopicARN - Endpoint - Partition + - TopicRegion ParameterLabels: NameSuffix: @@ -33,8 +36,12 @@ Metadata: default: Bucket ARN KMSKeyARN: default: KMS Key ARN + KMSAccountId: + default: KMS Account ID BucketAccountId: default: Bucket Account ID + TopicAccountId: + default: SNS Topic Account ID OrganizationalUnitIds: default: Organizational Unit IDs CreateTopic: @@ -45,6 +52,8 @@ Metadata: default: Sysdig Secure endpoint Partition: default: AWS Partition + TopicRegion: + default: The AWS region where the SNS topic is located Parameters: NameSuffix: @@ -67,10 +76,18 @@ Parameters: Type: String Description: The ARN of the KMS key used to encrypt the S3 bucket. Default: "" + KMSAccountId: + Type: String + Description: The AWS Account ID that owns the KMS key. + Default: "" BucketAccountId: Type: String Description: The AWS Account ID that owns the S3 bucket, if different from the current account. Default: "" + TopicAccountId: + Type: String + Description: The AWS Account ID that owns the SNS topic. + Default: "" OrganizationalUnitIds: Type: String Description: Comma-separated list of AWS Organizations organizational unit (OU) IDs for cross-account deployments. @@ -92,6 +109,10 @@ Parameters: Type: String Description: AWS Partition of your account or organization to create resources in Default: 'aws' + TopicRegion: + Type: String + Description: The AWS region where the SNS topic is located + AllowedPattern: '^[a-zA-Z0-9-]{1,128}$' Conditions: CreateSNSTopic: !Equals [ !Ref CreateTopic, "true" ] @@ -100,16 +121,18 @@ Conditions: !Not [ !Equals [ !Ref BucketAccountId, "" ] ], !Not [ !Equals [ !Ref BucketAccountId, !Ref "AWS::AccountId" ] ] ] - BucketInTargetAccount: !Not [BucketCrossAccount] - # Extract KMS account ID from KMS key ARN - KMSAccountId: !Select [4, !Split [":", !Ref KMSKeyARN]] + BucketInTargetAccount: !Equals [ !Ref BucketAccountId, !Ref "AWS::AccountId" ] # Check if KMS key is in a different account from bucket NeedKMSPolicy: !And [ - HasKMSKey, - !Equals [ !Ref KMSAccountId, !Ref BucketAccountId ] + !Not [ !Equals [ !Ref KMSKeyARN, "" ] ], + !Not [ !Equals [ !Ref KMSAccountId, !Ref BucketAccountId ] ] ] - IsTopicAccount: !Equals [ !Select [4, !Split [":", !Ref TopicARN]], !Ref "AWS::AccountId" ] + IsTopicAccount: !Equals [ !Ref TopicAccountId, !Ref "AWS::AccountId" ] IsBucketAccount: !Equals [ !Ref BucketAccountId, !Ref "AWS::AccountId" ] + NeedKMSPolicyInTargetAccount: + Fn::And: + - !Condition NeedKMSPolicy + - !Condition BucketInTargetAccount Resources: # Role and resources for same-account deployments @@ -165,6 +188,7 @@ Resources: TopicName: !Select [ 5, !Split [ ":", !Ref TopicARN ] ] CloudTrailNotificationsSubscription: + Condition: IsTopicAccount Type: "AWS::SNS::Subscription" Properties: TopicArn: !If [ CreateSNSTopic, !Ref CloudTrailNotificationsTopic, !Ref TopicARN ] @@ -206,6 +230,8 @@ Resources: FailureTolerancePercentage: 90 ConcurrencyMode: SOFT_FAILURE_TOLERANCE Parameters: + - ParameterKey: NameSuffix + ParameterValue: !Ref NameSuffix - ParameterKey: RoleName ParameterValue: !Sub sysdig-secure-cloudlogs-${AWS::AccountId}-${NameSuffix} - ParameterKey: TrustedIdentity @@ -220,21 +246,30 @@ Resources: ParameterValue: !Ref BucketAccountId - ParameterKey: TopicARN ParameterValue: !Ref TopicARN + - ParameterKey: TopicAccountId + ParameterValue: !Ref TopicAccountId - ParameterKey: Endpoint ParameterValue: !Ref Endpoint + - ParameterKey: TopicRegion + ParameterValue: !Ref TopicRegion StackInstancesGroup: - DeploymentTargets: OrganizationalUnitIds: !Split [",", !Ref OrganizationalUnitIds] Accounts: [!Ref BucketAccountId] + AccountFilterType: INTERSECTION Regions: [!Ref "AWS::Region"] - DeploymentTargets: OrganizationalUnitIds: !Split [",", !Ref OrganizationalUnitIds] - Accounts: [!Select [4, !Split [":", !Ref TopicARN]]] # Extract account ID from topic ARN - Regions: [!Select [3, !Split [":", !Ref TopicARN]]] # Extract region from topic ARN + Accounts: [!Ref TopicAccountId] + AccountFilterType: INTERSECTION + Regions: [!Ref TopicRegion] TemplateBody: | AWSTemplateFormatVersion: "2010-09-09" Description: IAM Role for S3 bucket and KMS access for Sysdig Cloud Logs integration Parameters: + NameSuffix: + Type: String + Description: Suffix to append to the resource name identifiers RoleName: Type: String Description: Name of the role to be created in the bucket account @@ -257,9 +292,15 @@ Resources: TopicARN: Type: String Description: ARN of the SNS topic + TopicAccountId: + Type: String + Description: AWS Account ID that owns the SNS topic Endpoint: Type: String Description: Sysdig Secure endpoint to receive CloudTrail notifications + TopicRegion: + Type: String + Description: The AWS region where the SNS topic is located Conditions: IsBucketAccount: !Equals [ !Ref BucketAccountId, !Ref "AWS::AccountId" ] IsTopicAccount: !Equals [ !Ref TopicAccountId, !Ref "AWS::AccountId" ] @@ -281,7 +322,7 @@ Resources: StringEquals: "sts:ExternalId": !Ref ExternalID Policies: - - PolicyName: "cloudlogs_s3_access_policy" + - PolicyName: !Sub "sysdig-secure-cloudlogs-policy-${AWS::AccountId}-${NameSuffix}" PolicyDocument: Version: "2012-10-17" Statement: @@ -320,45 +361,17 @@ Resources: TopicArn: !Ref TopicARN Protocol: "https" Endpoint: !Ref Endpoint - Outputs: - S3AccessRoleArn: - Description: ARN of the IAM role created in the bucket account for S3 access - Value: !GetAtt S3AccessRole.Arn - KMSPolicyInstructions: - Description: Instructions for updating KMS key policy when KMS encryption is enabled - Condition: HasKMSKey - Value: !Sub | - IMPORTANT: MANUAL ACTION REQUIRED - - Please add the following statement to your KMS key policy to allow Sysdig to decrypt logs. - This is necessary when KMS encryption is enabled for your S3 bucket. - Without this policy addition, Sysdig may not be able to read your encrypted logs. - - { - "Sid": "Sysdig-Decrypt", - "Effect": "Allow", - "Principal": { - "AWS": "${S3AccessRole.Arn}" - }, - "Action": "kms:Decrypt", - "Resource": "*" - } - Outputs: TopicARN: Description: "The ARN of the SNS Topic created for CloudTrail notifications." Value: !If [ CreateSNSTopic, !Ref CloudTrailNotificationsTopic, !Ref TopicARN ] - RoleARN: - Description: "The ARN of the IAM Role created for CloudTrail logs access." - Condition: BucketInTargetAccount - Value: !GetAtt CloudLogsRole.Arn CrossAccountRoleARN: Description: "ARN of the Cross-Account IAM Role for accessing the S3 bucket." Condition: BucketCrossAccount Value: !Sub "arn:${Partition}:iam::${BucketAccountId}:role/sysdig-secure-cloudlogs-${AWS::AccountId}-${NameSuffix}" KMSPolicyInstructions: Description: "Instructions for updating KMS key policy when KMS encryption is enabled" - Condition: NeedKMSPolicy + Condition: NeedKMSPolicyInTargetAccount Value: !Sub | IMPORTANT: MANUAL ACTION REQUIRED From 6da0dd0b03a82d68b9a02b9cf98b6acc04c72260 Mon Sep 17 00:00:00 2001 From: lorenzo merici Date: Thu, 10 Apr 2025 16:02:42 +0200 Subject: [PATCH 04/12] remove partition and rename role --- modules/log_ingestion.s3.cft.yaml | 26 ++++---------------------- 1 file changed, 4 insertions(+), 22 deletions(-) diff --git a/modules/log_ingestion.s3.cft.yaml b/modules/log_ingestion.s3.cft.yaml index 9621b4f..8e255a7 100644 --- a/modules/log_ingestion.s3.cft.yaml +++ b/modules/log_ingestion.s3.cft.yaml @@ -22,7 +22,6 @@ Metadata: - CreateTopic - TopicARN - Endpoint - - Partition - TopicRegion ParameterLabels: @@ -50,8 +49,6 @@ Metadata: default: SNS Topic ARN Endpoint: default: Sysdig Secure endpoint - Partition: - default: AWS Partition TopicRegion: default: The AWS region where the SNS topic is located @@ -105,10 +102,6 @@ Parameters: Endpoint: Type: String Description: Sysdig Secure endpoint to receive CloudTrail notifications. - Partition: - Type: String - Description: AWS Partition of your account or organization to create resources in - Default: 'aws' TopicRegion: Type: String Description: The AWS region where the SNS topic is located @@ -129,10 +122,6 @@ Conditions: ] IsTopicAccount: !Equals [ !Ref TopicAccountId, !Ref "AWS::AccountId" ] IsBucketAccount: !Equals [ !Ref BucketAccountId, !Ref "AWS::AccountId" ] - NeedKMSPolicyInTargetAccount: - Fn::And: - - !Condition NeedKMSPolicy - - !Condition BucketInTargetAccount Resources: # Role and resources for same-account deployments @@ -217,7 +206,7 @@ Resources: Condition: BucketCrossAccount Properties: StackSetName: !Sub sysdig-secure-cloudlogs-bucket-access-${NameSuffix} - Description: IAM Role for S3 bucket and KMS access for Sysdig Cloud Logs integration + Description: StackSet to configure S3 bucket and KMS permissions for Sysdig Cloud Logs integration PermissionModel: SERVICE_MANAGED AutoDeployment: Enabled: false @@ -233,7 +222,7 @@ Resources: - ParameterKey: NameSuffix ParameterValue: !Ref NameSuffix - ParameterKey: RoleName - ParameterValue: !Sub sysdig-secure-cloudlogs-${AWS::AccountId}-${NameSuffix} + ParameterValue: !Sub sysdig-secure-cloudlogs-${NameSuffix} - ParameterKey: TrustedIdentity ParameterValue: !Ref TrustedIdentity - ParameterKey: ExternalID @@ -362,16 +351,9 @@ Resources: Protocol: "https" Endpoint: !Ref Endpoint Outputs: - TopicARN: - Description: "The ARN of the SNS Topic created for CloudTrail notifications." - Value: !If [ CreateSNSTopic, !Ref CloudTrailNotificationsTopic, !Ref TopicARN ] - CrossAccountRoleARN: - Description: "ARN of the Cross-Account IAM Role for accessing the S3 bucket." - Condition: BucketCrossAccount - Value: !Sub "arn:${Partition}:iam::${BucketAccountId}:role/sysdig-secure-cloudlogs-${AWS::AccountId}-${NameSuffix}" KMSPolicyInstructions: Description: "Instructions for updating KMS key policy when KMS encryption is enabled" - Condition: NeedKMSPolicyInTargetAccount + Condition: NeedKMSPolicy Value: !Sub | IMPORTANT: MANUAL ACTION REQUIRED @@ -383,7 +365,7 @@ Outputs: "Sid": "Sysdig-Decrypt", "Effect": "Allow", "Principal": { - "AWS": "${CloudLogsRole.Arn}" + "AWS": "sysdig-secure-cloudlogs-${NameSuffix}" }, "Action": "kms:Decrypt", "Resource": "*" From 3b605bf34773132fb3026355dbbf10fd6e35fd0c Mon Sep 17 00:00:00 2001 From: lorenzo merici Date: Thu, 10 Apr 2025 16:04:54 +0200 Subject: [PATCH 05/12] remove IsBucketAccount variable --- modules/log_ingestion.s3.cft.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/log_ingestion.s3.cft.yaml b/modules/log_ingestion.s3.cft.yaml index 8e255a7..ad3cbd3 100644 --- a/modules/log_ingestion.s3.cft.yaml +++ b/modules/log_ingestion.s3.cft.yaml @@ -121,7 +121,6 @@ Conditions: !Not [ !Equals [ !Ref KMSAccountId, !Ref BucketAccountId ] ] ] IsTopicAccount: !Equals [ !Ref TopicAccountId, !Ref "AWS::AccountId" ] - IsBucketAccount: !Equals [ !Ref BucketAccountId, !Ref "AWS::AccountId" ] Resources: # Role and resources for same-account deployments From e5d074dbf31f80c1398ff51851f5ce39618b434e Mon Sep 17 00:00:00 2001 From: lorenzo merici Date: Thu, 10 Apr 2025 16:06:47 +0200 Subject: [PATCH 06/12] add checks --- modules/log_ingestion.s3.cft.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/log_ingestion.s3.cft.yaml b/modules/log_ingestion.s3.cft.yaml index ad3cbd3..c4b5d7d 100644 --- a/modules/log_ingestion.s3.cft.yaml +++ b/modules/log_ingestion.s3.cft.yaml @@ -85,10 +85,12 @@ Parameters: Type: String Description: The AWS Account ID that owns the SNS topic. Default: "" + AllowedPattern: '^[0-9]{12}$' OrganizationalUnitIds: Type: String Description: Comma-separated list of AWS Organizations organizational unit (OU) IDs for cross-account deployments. - Default: "root" + Default: "r-root" + AllowedPattern: '^(ou-[a-z0-9]{4,32}-[a-z0-9]{8,32}|r-[a-z0-9]{4,32})(,\s*(ou-[a-z0-9]{4,32}-[a-z0-9]{8,32}|r-[a-z0-9]{4,32}))*$' CreateTopic: Type: String AllowedValues: From b537a2218922f94f76aa7d0ff197438e51de39a0 Mon Sep 17 00:00:00 2001 From: lorenzo merici Date: Thu, 10 Apr 2025 16:09:05 +0200 Subject: [PATCH 07/12] remove default --- modules/log_ingestion.s3.cft.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/log_ingestion.s3.cft.yaml b/modules/log_ingestion.s3.cft.yaml index c4b5d7d..64ff9c7 100644 --- a/modules/log_ingestion.s3.cft.yaml +++ b/modules/log_ingestion.s3.cft.yaml @@ -84,7 +84,6 @@ Parameters: TopicAccountId: Type: String Description: The AWS Account ID that owns the SNS topic. - Default: "" AllowedPattern: '^[0-9]{12}$' OrganizationalUnitIds: Type: String From 2a4b3a0b27d886eb477e60b3b672f2abe0f9cbc3 Mon Sep 17 00:00:00 2001 From: lorenzo merici Date: Thu, 10 Apr 2025 16:21:47 +0200 Subject: [PATCH 08/12] add DeployStackSet condition --- modules/log_ingestion.s3.cft.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/log_ingestion.s3.cft.yaml b/modules/log_ingestion.s3.cft.yaml index 64ff9c7..92135e8 100644 --- a/modules/log_ingestion.s3.cft.yaml +++ b/modules/log_ingestion.s3.cft.yaml @@ -111,12 +111,12 @@ Parameters: Conditions: CreateSNSTopic: !Equals [ !Ref CreateTopic, "true" ] HasKMSKey: !Not [ !Equals [ !Ref KMSKeyARN, "" ] ] - BucketCrossAccount: !And [ - !Not [ !Equals [ !Ref BucketAccountId, "" ] ], - !Not [ !Equals [ !Ref BucketAccountId, !Ref "AWS::AccountId" ] ] + DeployStackSet: !Or [ + !Not [ !Equals [ !Ref BucketAccountId, !Ref "AWS::AccountId" ] ], + !Not [ !Equals [ !Ref TopicAccountId, !Ref "AWS::AccountId" ] ] ] BucketInTargetAccount: !Equals [ !Ref BucketAccountId, !Ref "AWS::AccountId" ] - # Check if KMS key is in a different account from bucket + NeedKMSPolicy: !And [ !Not [ !Equals [ !Ref KMSKeyARN, "" ] ], !Not [ !Equals [ !Ref KMSAccountId, !Ref BucketAccountId ] ] @@ -203,7 +203,7 @@ Resources: # StackSet for cross-account bucket access BucketAccessStackSet: Type: AWS::CloudFormation::StackSet - Condition: BucketCrossAccount + Condition: DeployStackSet Properties: StackSetName: !Sub sysdig-secure-cloudlogs-bucket-access-${NameSuffix} Description: StackSet to configure S3 bucket and KMS permissions for Sysdig Cloud Logs integration From 77bc5c76b9ac028ac4a4e2329b59764ec07074dd Mon Sep 17 00:00:00 2001 From: lorenzo merici Date: Thu, 10 Apr 2025 16:23:53 +0200 Subject: [PATCH 09/12] AllowedPattern for bucketID --- modules/log_ingestion.s3.cft.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/log_ingestion.s3.cft.yaml b/modules/log_ingestion.s3.cft.yaml index 92135e8..e89dc1f 100644 --- a/modules/log_ingestion.s3.cft.yaml +++ b/modules/log_ingestion.s3.cft.yaml @@ -80,7 +80,7 @@ Parameters: BucketAccountId: Type: String Description: The AWS Account ID that owns the S3 bucket, if different from the current account. - Default: "" + AllowedPattern: '^[0-9]{12}$' TopicAccountId: Type: String Description: The AWS Account ID that owns the SNS topic. From 954010040a37721fa1344bc99cb12abd9ded1fd7 Mon Sep 17 00:00:00 2001 From: lorenzo merici Date: Thu, 10 Apr 2025 16:35:04 +0200 Subject: [PATCH 10/12] Update description --- modules/log_ingestion.s3.cft.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/log_ingestion.s3.cft.yaml b/modules/log_ingestion.s3.cft.yaml index e89dc1f..60393c2 100644 --- a/modules/log_ingestion.s3.cft.yaml +++ b/modules/log_ingestion.s3.cft.yaml @@ -2,7 +2,6 @@ AWSTemplateFormatVersion: "2010-09-09" Description: > CloudFormation template for provisioning the necessary resources for the `cloud-logs` component, allowing Sysdig to access CloudTrail logs in S3 buckets. - Supports single-account, organizational same-account, and organizational cross-account deployments. Metadata: AWS::CloudFormation::Interface: From f8db529bf5bb31042e0e97f8c7a5d95c3a6f856f Mon Sep 17 00:00:00 2001 From: lorenzo merici Date: Thu, 10 Apr 2025 18:28:56 +0200 Subject: [PATCH 11/12] Fix condition for deploying the role directly --- modules/log_ingestion.s3.cft.yaml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/modules/log_ingestion.s3.cft.yaml b/modules/log_ingestion.s3.cft.yaml index 60393c2..cdf6ddc 100644 --- a/modules/log_ingestion.s3.cft.yaml +++ b/modules/log_ingestion.s3.cft.yaml @@ -114,7 +114,11 @@ Conditions: !Not [ !Equals [ !Ref BucketAccountId, !Ref "AWS::AccountId" ] ], !Not [ !Equals [ !Ref TopicAccountId, !Ref "AWS::AccountId" ] ] ] - BucketInTargetAccount: !Equals [ !Ref BucketAccountId, !Ref "AWS::AccountId" ] + + DeployRole: !And [ + !Equals [ !Ref BucketAccountId, !Ref "AWS::AccountId" ] , + !Equals [ DeployStackSet, "false" ] + ] NeedKMSPolicy: !And [ !Not [ !Equals [ !Ref KMSKeyARN, "" ] ], @@ -126,7 +130,7 @@ Resources: # Role and resources for same-account deployments CloudLogsRole: Type: "AWS::IAM::Role" - Condition: BucketInTargetAccount + Condition: DeployRole Properties: RoleName: !Sub sysdig-secure-cloudlogs-${NameSuffix} AssumeRolePolicyDocument: From 21a67c3df3c3ca6e04518e89ef14002bb66e5a76 Mon Sep 17 00:00:00 2001 From: lorenzo merici Date: Thu, 10 Apr 2025 18:34:09 +0200 Subject: [PATCH 12/12] allowed pattern kms account id --- modules/log_ingestion.s3.cft.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/log_ingestion.s3.cft.yaml b/modules/log_ingestion.s3.cft.yaml index cdf6ddc..aea9660 100644 --- a/modules/log_ingestion.s3.cft.yaml +++ b/modules/log_ingestion.s3.cft.yaml @@ -75,7 +75,7 @@ Parameters: KMSAccountId: Type: String Description: The AWS Account ID that owns the KMS key. - Default: "" + AllowedPattern: '^[0-9]{12}$' BucketAccountId: Type: String Description: The AWS Account ID that owns the S3 bucket, if different from the current account.