diff --git a/modules/response_actions.cft.yaml b/modules/response_actions.cft.yaml new file mode 100644 index 0000000..f77bbe1 --- /dev/null +++ b/modules/response_actions.cft.yaml @@ -0,0 +1,1520 @@ +AWSTemplateFormatVersion: "2010-09-09" +Description: Sysdig Response Actions for AWS - Automated security responses to detected threats + +Metadata: + AWS::CloudFormation::Interface: + ParameterGroups: + - Label: + default: "" + Parameters: + - EnabledResponseActions + - Regions + - Label: + default: "Sysdig Settings (Do not change)" + Parameters: + - NameSuffix + - ExternalID + - TrustedIdentity + - ApiBaseUrl + - LambdaPackagesBaseUrl + - ResponseActionsVersion + - IsOrganizational + - Partition + - RootOUID + - IncludeOUIDs + - IncludeAccounts + - ExcludeAccounts + ParameterLabels: + NameSuffix: + default: Name Suffix + ExternalID: + default: External ID + TrustedIdentity: + default: Trusted Identity + ApiBaseUrl: + default: API Base URL + LambdaPackagesBaseUrl: + default: Lambda Packages Base URL + ResponseActionsVersion: + default: Response Actions Version + EnabledResponseActions: + default: Enabled Response Actions + Regions: + default: Deployment Regions + IsOrganizational: + default: Is Organizational + Partition: + default: AWS Partition + RootOUID: + default: Root Organization Unit ID + IncludeOUIDs: + default: Include Organizational Unit IDs + IncludeAccounts: + default: Include AWS accounts + ExcludeAccounts: + default: Exclude AWS accounts + +Parameters: + NameSuffix: + Type: String + Description: Suffix to append to the resource name identifiers + AllowedPattern: '[0-9a-z-]+' + MaxLength: 8 + MinLength: 4 + ExternalID: + Type: String + Description: External ID for secure cross-account role assumption + Default: "cloud-actions-lambda-invoke-access" + TrustedIdentity: + Type: String + Description: The Role in Sysdig's AWS Account with permissions to your account + ApiBaseUrl: + Type: String + Description: API base URL for Lambda functions + LambdaPackagesBaseUrl: + Type: String + Description: Base URL for downloading Lambda deployment packages (e.g., https://example.com/packages) + ResponseActionsVersion: + Type: String + Description: Response Actions version + Default: "0.0.15" + EnabledResponseActions: + Type: CommaDelimitedList + Description: List of response actions to enable (make_private, fetch_cloud_logs, create_volume_snapshot, quarantine_user) + Default: "make_private,fetch_cloud_logs,create_volume_snapshot,quarantine_user" + Regions: + Type: CommaDelimitedList + Description: Comma separated list of regions to deploy Response Actions Lambda functions + IsOrganizational: + Type: String + Description: Install into an organization + Default: 'false' + AllowedValues: + - 'true' + - 'false' + Partition: + Type: String + Description: AWS Partition of your account or organization to create resources in + Default: 'aws' + RootOUID: + Type: CommaDelimitedList + Description: Root Organizational Unit ID of your AWS organization + IncludeOUIDs: + Type: CommaDelimitedList + Description: Comma separated list of organizational unit IDs to be included for deployment + IncludeAccounts: + Type: CommaDelimitedList + Description: Comma separated list of AWS accounts in your organization to be included for deployment + ExcludeAccounts: + Type: CommaDelimitedList + Description: Comma separated list of AWS accounts in your organization to be excluded for deployment + +Conditions: + IsOrganizational: + Fn::Equals: + - Ref: IsOrganizational + - 'true' + + # Check for Inclusion and Exclusion params + # INCLUSIONS + OUInclusionsConfigured: + !And + - !Condition IsOrganizational + - !Not + - !Equals + - !Join ["", !Ref IncludeOUIDs] + - '' + AccountInclusionsConfigured: + !And + - !Condition IsOrganizational + - !Not + - !Equals + - !Join ["", !Ref IncludeAccounts] + - '' + AllowedInclusions: + !And + - !Condition OUInclusionsConfigured + - !Not + - !Condition AccountInclusionsConfigured + + # EXCLUSIONS + AccountExclusionsConfigured: + !And + - !Condition IsOrganizational + - !Equals + - !Join ["", !Ref IncludeAccounts] + - '' + - !Not + - !Equals + - !Join ["", !Ref ExcludeAccounts] + - '' + + +Resources: + # StackSet Administration and Execution Roles + LambdaStackSetAdministrationRole: + Type: AWS::IAM::Role + Properties: + RoleName: !Sub sysdig-secure-ra-${NameSuffix}-stackset-admin + AssumeRolePolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Principal: + Service: cloudformation.amazonaws.com + Action: + - sts:AssumeRole + Policies: + - PolicyName: !Sub sysdig-secure-ra-${NameSuffix}-stackset-admin-policy + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: + - sts:AssumeRole + Resource: + - !Sub arn:${Partition}:iam::*:role/sysdig-secure-ra-${NameSuffix}-stackset-execution + + LambdaStackSetExecutionRole: + Type: AWS::IAM::Role + Properties: + RoleName: !Sub sysdig-secure-ra-${NameSuffix}-stackset-execution + AssumeRolePolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Principal: + AWS: + - !GetAtt LambdaStackSetAdministrationRole.Arn + Action: + - sts:AssumeRole + ManagedPolicyArns: + - !Sub arn:${Partition}:iam::aws:policy/AWSCloudFormationFullAccess + Policies: + - PolicyName: !Sub sysdig-secure-ra-${NameSuffix}-stackset-execution-policy + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: + - lambda:* + - iam:CreateRole + - iam:DeleteRole + - iam:GetRole + - iam:PassRole + - iam:PutRolePolicy + - iam:DeleteRolePolicy + - iam:AttachRolePolicy + - iam:DetachRolePolicy + - iam:GetRolePolicy + - iam:TagRole + - iam:UntagRole + - iam:ListRoleTags + - logs:CreateLogGroup + - logs:DeleteLogGroup + - logs:PutRetentionPolicy + - logs:TagResource + - logs:UntagResource + - logs:TagLogGroup + - logs:ListTagsForResource + - s3:CreateBucket + - s3:DeleteBucket + - s3:GetBucketLocation + - s3:GetBucketVersioning + - s3:PutBucketVersioning + - s3:PutBucketPublicAccessBlock + - s3:GetBucketPublicAccessBlock + - s3:PutBucketTagging + - s3:GetBucketTagging + - s3:GetObject + - s3:PutObject + - s3:DeleteObject + - s3:ListBucket + Resource: "*" + + # Cross-Account Lambda Invoker Role + CrossAccountLambdaInvokerRole: + Type: AWS::IAM::Role + Properties: + RoleName: !Sub sysdig-secure-ra-${NameSuffix}-cross-account-invoker + AssumeRolePolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Principal: + AWS: !Ref TrustedIdentity + Action: sts:AssumeRole + Condition: + StringEquals: + sts:ExternalId: !Ref ExternalID + Policies: + - PolicyName: !Sub sysdig-secure-ra-${NameSuffix}-invoke-policy + PolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Action: + - tag:GetResources + Resource: "*" + - Effect: Allow + Action: + - lambda:InvokeFunction + - lambda:GetFunction + Resource: + - !Sub "arn:${Partition}:lambda:*:${AWS::AccountId}:function:sysdig-secure-ra-${NameSuffix}-*" + Tags: + - Key: Name + Value: !Sub sysdig-secure-ra-${NameSuffix}-cross-account-invoker + - Key: 'sysdig.com/response-actions/resource-name' + Value: 'cross-account-invoker' + + # Lambda Execution Roles + QuarantineUserRole: + Type: AWS::IAM::Role + Properties: + RoleName: !Sub sysdig-secure-ra-${NameSuffix}-${AWS::AccountId}-quarantine-user-role + AssumeRolePolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Principal: + Service: lambda.amazonaws.com + Action: sts:AssumeRole + ManagedPolicyArns: + - !Sub arn:${Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole + Policies: + - PolicyName: !Sub sysdig-secure-ra-${NameSuffix}-quarantine-user-policy + PolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Action: + - iam:AttachUserPolicy + - iam:DetachUserPolicy + - iam:PutUserPolicy + - iam:DeleteUserPolicy + - iam:ListUserPolicies + - iam:ListAttachedUserPolicies + - iam:GetUser + - iam:GetUserPolicy + - iam:TagUser + - iam:UntagUser + - iam:ListUserTags + - iam:AttachRolePolicy + - iam:DetachRolePolicy + - iam:GetRole + - iam:ListRolePolicies + - iam:ListAttachedRolePolicies + - iam:GetPolicy + - iam:CreatePolicy + - sts:GetCallerIdentity + Resource: "*" + - Effect: Allow + Action: sts:AssumeRole + Resource: !Sub "arn:${Partition}:iam::*:role/sysdig-secure-ra-${NameSuffix}-${AWS::AccountId}-quarantine-user-role" + Tags: + - Key: Name + Value: !Sub sysdig-secure-ra-${NameSuffix}-${AWS::AccountId}-quarantine-user-role + - Key: 'sysdig.com/response-actions/cloud-actions' + Value: 'true' + - Key: 'sysdig.com/response-actions/resource-name' + Value: 'quarantine-user-role' + + FetchCloudLogsRole: + Type: AWS::IAM::Role + Properties: + RoleName: !Sub sysdig-secure-ra-${NameSuffix}-${AWS::AccountId}-fetch-cloud-logs-role + AssumeRolePolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Principal: + Service: lambda.amazonaws.com + Action: sts:AssumeRole + ManagedPolicyArns: + - !Sub arn:${Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole + Policies: + - PolicyName: !Sub sysdig-secure-ra-${NameSuffix}-fetch-cloud-logs-policy + PolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Action: + - cloudtrail:LookupEvents + - sts:GetCallerIdentity + Resource: "*" + - Effect: Allow + Action: sts:AssumeRole + Resource: !Sub "arn:${Partition}:iam::*:role/sysdig-secure-ra-${NameSuffix}-${AWS::AccountId}-fetch-cloud-logs-role" + Tags: + - Key: Name + Value: !Sub sysdig-secure-ra-${NameSuffix}-${AWS::AccountId}-fetch-cloud-logs-role + - Key: 'sysdig.com/response-actions/cloud-actions' + Value: 'true' + - Key: 'sysdig.com/response-actions/resource-name' + Value: 'fetch-cloud-logs-role' + + RemovePolicyRole: + Type: AWS::IAM::Role + Properties: + RoleName: !Sub sysdig-secure-ra-${NameSuffix}-${AWS::AccountId}-remove-policy-role + AssumeRolePolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Principal: + Service: lambda.amazonaws.com + Action: sts:AssumeRole + ManagedPolicyArns: + - !Sub arn:${Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole + Policies: + - PolicyName: !Sub sysdig-secure-ra-${NameSuffix}-remove-policy-policy + PolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Action: + - iam:DetachUserPolicy + - iam:DetachRolePolicy + - iam:ListAttachedUserPolicies + - iam:ListAttachedRolePolicies + - iam:GetUser + - iam:GetRole + - sts:GetCallerIdentity + Resource: "*" + - Effect: Allow + Action: sts:AssumeRole + Resource: !Sub "arn:${Partition}:iam::*:role/sysdig-secure-ra-${NameSuffix}-${AWS::AccountId}-remove-policy-role" + Tags: + - Key: Name + Value: !Sub sysdig-secure-ra-${NameSuffix}-${AWS::AccountId}-remove-policy-role + - Key: 'sysdig.com/response-actions/cloud-actions' + Value: 'true' + - Key: 'sysdig.com/response-actions/resource-name' + Value: 'remove-policy-role' + + ConfigureResourceAccessRole: + Type: AWS::IAM::Role + Properties: + RoleName: !Sub sysdig-secure-ra-${NameSuffix}-${AWS::AccountId}-confi-res-access-role + AssumeRolePolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Principal: + Service: lambda.amazonaws.com + Action: sts:AssumeRole + ManagedPolicyArns: + - !Sub arn:${Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole + Policies: + - PolicyName: !Sub sysdig-secure-ra-${NameSuffix}-configure-resource-access-policy + PolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Action: + - s3:GetBucketLocation + - s3:GetBucketPublicAccessBlock + - s3:PutBucketPublicAccessBlock + - s3:ListAllMyBuckets + Resource: "*" + - Effect: Allow + Action: + - rds:DescribeDBInstances + - rds:ModifyDBInstance + - sts:GetCallerIdentity + Resource: "*" + - Effect: Allow + Action: sts:AssumeRole + Resource: !Sub "arn:${Partition}:iam::*:role/sysdig-secure-ra-${NameSuffix}-${AWS::AccountId}-confi-res-access-role" + Tags: + - Key: Name + Value: !Sub sysdig-secure-ra-${NameSuffix}-${AWS::AccountId}-confi-res-access-role + - Key: 'sysdig.com/response-actions/cloud-actions' + Value: 'true' + - Key: 'sysdig.com/response-actions/resource-name' + Value: 'configure-resource-access-role' + + CreateVolumeSnapshotsRole: + Type: AWS::IAM::Role + Properties: + RoleName: !Sub sysdig-secure-ra-${NameSuffix}-${AWS::AccountId}-create-vol-snap-role + AssumeRolePolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Principal: + Service: lambda.amazonaws.com + Action: sts:AssumeRole + ManagedPolicyArns: + - !Sub arn:${Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole + Policies: + - PolicyName: !Sub sysdig-secure-ra-${NameSuffix}-create-volume-snapshots-policy + PolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Action: + - logs:CreateLogGroup + - logs:CreateLogStream + - logs:PutLogEvents + Resource: "arn:aws:logs:*:*:*" + - Effect: Allow + Action: + - ec2:DescribeInstances + - ec2:DescribeVolumes + - ec2:DescribeSnapshots + - ec2:CreateSnapshot + - ec2:CreateTags + - sts:GetCallerIdentity + Resource: "*" + - Effect: Allow + Action: + - ec2:CreateTags + Resource: + - "arn:aws:ec2:*:*:snapshot/*" + - Effect: Allow + Action: sts:AssumeRole + Resource: !Sub "arn:${Partition}:iam::*:role/sysdig-secure-ra-${NameSuffix}-${AWS::AccountId}-create-vol-snap-role" + Tags: + - Key: Name + Value: !Sub sysdig-secure-ra-${NameSuffix}-${AWS::AccountId}-create-vol-snap-role + - Key: 'sysdig.com/response-actions/cloud-actions' + Value: 'true' + - Key: 'sysdig.com/response-actions/resource-name' + Value: 'create-volume-snapshots-role' + + DeleteVolumeSnapshotsRole: + Type: AWS::IAM::Role + Properties: + RoleName: !Sub sysdig-secure-ra-${NameSuffix}-${AWS::AccountId}-delete-vol-snap-role + AssumeRolePolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Principal: + Service: lambda.amazonaws.com + Action: sts:AssumeRole + ManagedPolicyArns: + - !Sub arn:${Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole + Policies: + - PolicyName: !Sub sysdig-secure-ra-${NameSuffix}-delete-volume-snapshots-policy + PolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Action: + - logs:CreateLogGroup + - logs:CreateLogStream + - logs:PutLogEvents + Resource: "arn:aws:logs:*:*:*" + - Effect: Allow + Action: + - ec2:DescribeSnapshots + - ec2:DeleteSnapshot + - sts:GetCallerIdentity + Resource: "*" + - Effect: Allow + Action: sts:AssumeRole + Resource: !Sub "arn:${Partition}:iam::*:role/sysdig-secure-ra-${NameSuffix}-${AWS::AccountId}-delete-vol-snap-role" + Tags: + - Key: Name + Value: !Sub sysdig-secure-ra-${NameSuffix}-${AWS::AccountId}-delete-vol-snap-role + - Key: 'sysdig.com/response-actions/cloud-actions' + Value: 'true' + - Key: 'sysdig.com/response-actions/resource-name' + Value: 'delete-volume-snapshots-role' + + # Lambda Functions StackSet + LambdaFunctionsStackSet: + Type: AWS::CloudFormation::StackSet + Properties: + StackSetName: !Sub sysdig-secure-ra-${NameSuffix}-lambda + AdministrationRoleARN: !GetAtt LambdaStackSetAdministrationRole.Arn + ExecutionRoleName: !Ref LambdaStackSetExecutionRole + Description: Sysdig Response Actions Lambda Functions - Multi-Region Deployment + PermissionModel: SELF_MANAGED + ManagedExecution: + Active: true + Capabilities: + - CAPABILITY_NAMED_IAM + OperationPreferences: + MaxConcurrentPercentage: 100 + FailureTolerancePercentage: 90 + ConcurrencyMode: SOFT_FAILURE_TOLERANCE + RegionConcurrencyType: PARALLEL + Parameters: + - ParameterKey: ResourceName + ParameterValue: !Sub sysdig-secure-ra-${NameSuffix}-${AWS::AccountId} + - ParameterKey: S3BucketName + ParameterValue: !Sub sysdig-secure-ra-${NameSuffix}-packages + - ParameterKey: ApiBaseUrl + ParameterValue: !Ref ApiBaseUrl + - ParameterKey: QuarantineUserRoleArn + ParameterValue: !GetAtt QuarantineUserRole.Arn + - ParameterKey: FetchCloudLogsRoleArn + ParameterValue: !GetAtt FetchCloudLogsRole.Arn + - ParameterKey: RemovePolicyRoleArn + ParameterValue: !GetAtt RemovePolicyRole.Arn + - ParameterKey: ConfigureResourceAccessRoleArn + ParameterValue: !GetAtt ConfigureResourceAccessRole.Arn + - ParameterKey: CreateVolumeSnapshotsRoleArn + ParameterValue: !GetAtt CreateVolumeSnapshotsRole.Arn + - ParameterKey: DeleteVolumeSnapshotsRoleArn + ParameterValue: !GetAtt DeleteVolumeSnapshotsRole.Arn + - ParameterKey: QuarantineUserRoleName + ParameterValue: !Select [1, !Split ["/", !GetAtt QuarantineUserRole.Arn]] + - ParameterKey: FetchCloudLogsRoleName + ParameterValue: !Select [1, !Split ["/", !GetAtt FetchCloudLogsRole.Arn]] + - ParameterKey: RemovePolicyRoleName + ParameterValue: !Select [1, !Split ["/", !GetAtt RemovePolicyRole.Arn]] + - ParameterKey: ConfigureResourceAccessRoleName + ParameterValue: !Select [1, !Split ["/", !GetAtt ConfigureResourceAccessRole.Arn]] + - ParameterKey: CreateVolumeSnapshotsRoleName + ParameterValue: !Select [1, !Split ["/", !GetAtt CreateVolumeSnapshotsRole.Arn]] + - ParameterKey: DeleteVolumeSnapshotsRoleName + ParameterValue: !Select [1, !Split ["/", !GetAtt DeleteVolumeSnapshotsRole.Arn]] + - ParameterKey: ResponseActionsVersion + ParameterValue: !Ref ResponseActionsVersion + - ParameterKey: LambdaPackagesBaseUrl + ParameterValue: !Ref LambdaPackagesBaseUrl + - ParameterKey: EnabledResponseActions + ParameterValue: !Join [",", !Ref EnabledResponseActions] + StackInstancesGroup: + - DeploymentTargets: + Accounts: + - !Ref AWS::AccountId + Regions: !Ref Regions + TemplateBody: | + AWSTemplateFormatVersion: '2010-09-09' + Description: 'Sysdig Response Actions Lambda Functions - Multi-Region Deployment' + + Parameters: + ResourceName: + Type: String + Description: Base name for all resources + TemplateVersion: + Type: String + Description: Template version hash to force updates + Default: "1" + S3BucketName: + Type: String + Description: Name for the regional S3 bucket containing Lambda deployment packages + ApiBaseUrl: + Type: String + Description: API base URL for Lambda functions + QuarantineUserRoleArn: + Type: String + Description: ARN of the IAM role for quarantine user function + FetchCloudLogsRoleArn: + Type: String + Description: ARN of the IAM role for fetch cloud logs function + RemovePolicyRoleArn: + Type: String + Description: ARN of the IAM role for remove policy function + ConfigureResourceAccessRoleArn: + Type: String + Description: ARN of the IAM role for configure resource access function + CreateVolumeSnapshotsRoleArn: + Type: String + Description: ARN of the IAM role for create volume snapshots function + DeleteVolumeSnapshotsRoleArn: + Type: String + Description: ARN of the IAM role for delete volume snapshots function + QuarantineUserRoleName: + Type: String + Description: Name of the IAM role for quarantine user function + FetchCloudLogsRoleName: + Type: String + Description: Name of the IAM role for fetch cloud logs function + RemovePolicyRoleName: + Type: String + Description: Name of the IAM role for remove policy function + ConfigureResourceAccessRoleName: + Type: String + Description: Name of the IAM role for configure resource access function + CreateVolumeSnapshotsRoleName: + Type: String + Description: Name of the IAM role for create volume snapshots function + DeleteVolumeSnapshotsRoleName: + Type: String + Description: Name of the IAM role for delete volume snapshots function + ResponseActionsVersion: + Type: String + Description: Version of response actions packages to download + LambdaPackagesBaseUrl: + Type: String + Description: Base URL for downloading Lambda deployment packages + EnabledResponseActions: + Type: String + Description: Comma-separated list of response actions to enable + Default: "make_private,fetch_cloud_logs,create_volume_snapshot,quarantine_user" + + Conditions: + CreateQuarantineUserResources: !Not [!Equals [!Select [0, !Split ["quarantine_user", !Ref EnabledResponseActions]], !Ref EnabledResponseActions]] + CreateFetchCloudLogsResources: !Not [!Equals [!Select [0, !Split ["fetch_cloud_logs", !Ref EnabledResponseActions]], !Ref EnabledResponseActions]] + CreateMakePrivateResources: !Not [!Equals [!Select [0, !Split ["make_private", !Ref EnabledResponseActions]], !Ref EnabledResponseActions]] + CreateVolumeSnapshotResources: !Not [!Equals [!Select [0, !Split ["create_volume_snapshot", !Ref EnabledResponseActions]], !Ref EnabledResponseActions]] + + Resources: + # S3 Bucket for Lambda packages (Regional) + LambdaPackagesBucket: + Type: AWS::S3::Bucket + Properties: + BucketName: !Sub '${S3BucketName}-${AWS::Region}' + PublicAccessBlockConfiguration: + BlockPublicAcls: true + BlockPublicPolicy: true + IgnorePublicAcls: true + RestrictPublicBuckets: true + VersioningConfiguration: + Status: Enabled + Tags: + - Key: 'sysdig.com/response-actions/resource-name' + Value: 'lambda-packages-bucket' + + # Package Downloader Lambda (per region) + PackageDownloaderRole: + Type: AWS::IAM::Role + Properties: + RoleName: !Sub '${ResourceName}-package-downloader-role' + AssumeRolePolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Principal: + Service: lambda.amazonaws.com + Action: sts:AssumeRole + ManagedPolicyArns: + - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole + Policies: + - PolicyName: package-downloader-policy + PolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Action: + - s3:PutObject + - s3:DeleteObject + - s3:GetObject + Resource: !Sub 'arn:aws:s3:::${S3BucketName}-*/*' + - Effect: Allow + Action: + - s3:ListBucket + Resource: !Sub 'arn:aws:s3:::${S3BucketName}-*' + Tags: + - Key: 'sysdig.com/response-actions/resource-name' + Value: 'package-downloader-role' + + PackageDownloaderLogGroup: + Type: AWS::Logs::LogGroup + DeletionPolicy: Retain + Properties: + LogGroupName: !Sub '/aws/lambda/${ResourceName}-package-downloader' + RetentionInDays: 7 + Tags: + - Key: 'sysdig.com/response-actions/resource-name' + Value: 'package-downloader-log-group' + + PackageDownloaderFunction: + Type: AWS::Lambda::Function + DependsOn: PackageDownloaderLogGroup + Properties: + FunctionName: !Sub '${ResourceName}-package-downloader' + Runtime: python3.12 + Handler: index.handler + Role: !GetAtt PackageDownloaderRole.Arn + Timeout: 300 + MemorySize: 256 + Code: + ZipFile: | + import json + import urllib.request + import boto3 + import cfnresponse + + def handler(event, context): + try: + print(f"Event: {json.dumps(event)}") + + if event['RequestType'] == 'Delete': + # Clean up S3 object on delete + bucket = event['ResourceProperties']['Bucket'] + key = event['ResourceProperties']['Key'] + s3 = boto3.client('s3') + try: + s3.delete_object(Bucket=bucket, Key=key) + print(f"Deleted s3://{bucket}/{key}") + except Exception as e: + print(f"Error deleting object (may not exist): {e}") + cfnresponse.send(event, context, cfnresponse.SUCCESS, {}) + return + + if event['RequestType'] in ['Create', 'Update']: + url = event['ResourceProperties']['Url'] + bucket = event['ResourceProperties']['Bucket'] + key = event['ResourceProperties']['Key'] + + print(f"Downloading from {url}") + print(f"Target: s3://{bucket}/{key}") + + # Download from URL + try: + req = urllib.request.Request(url) + with urllib.request.urlopen(req, timeout=60) as response: + content = response.read() + print(f"Downloaded {len(content)} bytes, status: {response.status}") + except urllib.error.HTTPError as e: + error_msg = f"HTTP {e.code} downloading {url}: {e.reason}" + print(error_msg) + cfnresponse.send(event, context, cfnresponse.FAILED, {'Error': error_msg}) + return + except urllib.error.URLError as e: + error_msg = f"URL error downloading {url}: {str(e.reason)}" + print(error_msg) + cfnresponse.send(event, context, cfnresponse.FAILED, {'Error': error_msg}) + return + + # Upload to S3 + try: + s3 = boto3.client('s3') + s3.put_object(Bucket=bucket, Key=key, Body=content) + print(f"Uploaded to s3://{bucket}/{key}") + except Exception as e: + error_msg = f"S3 upload error: {str(e)}" + print(error_msg) + cfnresponse.send(event, context, cfnresponse.FAILED, {'Error': error_msg}) + return + + cfnresponse.send(event, context, cfnresponse.SUCCESS, { + 'Bucket': bucket, + 'Key': key, + 'Size': len(content) + }) + else: + cfnresponse.send(event, context, cfnresponse.SUCCESS, {}) + + except Exception as e: + import traceback + error_msg = f"Unexpected error: {str(e)}\n{traceback.format_exc()}" + print(error_msg) + cfnresponse.send(event, context, cfnresponse.FAILED, { + 'Error': str(e) + }) + Tags: + - Key: 'sysdig.com/response-actions/resource-name' + Value: 'package-downloader-lambda' + + # Custom Resources to download Lambda packages + QuarantineUserPackage: + Type: Custom::LambdaPackage + Condition: CreateQuarantineUserResources + Properties: + ServiceToken: !GetAtt PackageDownloaderFunction.Arn + Url: !Sub '${LambdaPackagesBaseUrl}/v${ResponseActionsVersion}/quarantine_user.zip' + Bucket: !Ref LambdaPackagesBucket + Key: !Sub '${ResponseActionsVersion}/quarantine_user.zip' + + FetchCloudLogsPackage: + Type: Custom::LambdaPackage + Condition: CreateFetchCloudLogsResources + Properties: + ServiceToken: !GetAtt PackageDownloaderFunction.Arn + Url: !Sub '${LambdaPackagesBaseUrl}/v${ResponseActionsVersion}/fetch_cloud_logs.zip' + Bucket: !Ref LambdaPackagesBucket + Key: !Sub '${ResponseActionsVersion}/fetch_cloud_logs.zip' + + RemovePolicyPackage: + Type: Custom::LambdaPackage + Condition: CreateQuarantineUserResources + Properties: + ServiceToken: !GetAtt PackageDownloaderFunction.Arn + Url: !Sub '${LambdaPackagesBaseUrl}/v${ResponseActionsVersion}/remove_policy.zip' + Bucket: !Ref LambdaPackagesBucket + Key: !Sub '${ResponseActionsVersion}/remove_policy.zip' + + ConfigureResourceAccessPackage: + Type: Custom::LambdaPackage + Condition: CreateMakePrivateResources + Properties: + ServiceToken: !GetAtt PackageDownloaderFunction.Arn + Url: !Sub '${LambdaPackagesBaseUrl}/v${ResponseActionsVersion}/configure_resource_access.zip' + Bucket: !Ref LambdaPackagesBucket + Key: !Sub '${ResponseActionsVersion}/configure_resource_access.zip' + + CreateVolumeSnapshotsPackage: + Type: Custom::LambdaPackage + Condition: CreateVolumeSnapshotResources + Properties: + ServiceToken: !GetAtt PackageDownloaderFunction.Arn + Url: !Sub '${LambdaPackagesBaseUrl}/v${ResponseActionsVersion}/create_volume_snapshots.zip' + Bucket: !Ref LambdaPackagesBucket + Key: !Sub '${ResponseActionsVersion}/create_volume_snapshots.zip' + + DeleteVolumeSnapshotsPackage: + Type: Custom::LambdaPackage + Condition: CreateVolumeSnapshotResources + Properties: + ServiceToken: !GetAtt PackageDownloaderFunction.Arn + Url: !Sub '${LambdaPackagesBaseUrl}/v${ResponseActionsVersion}/delete_volume_snapshots.zip' + Bucket: !Ref LambdaPackagesBucket + Key: !Sub '${ResponseActionsVersion}/delete_volume_snapshots.zip' + + # CloudWatch Log Groups (Regional Resources) + QuarantineUserLogGroup: + Type: AWS::Logs::LogGroup + Condition: CreateQuarantineUserResources + Properties: + LogGroupName: !Sub '/aws/lambda/${ResourceName}-quarantine-user' + RetentionInDays: 7 + Tags: + - Key: 'sysdig.com/response-actions/resource-name' + Value: 'quarantine-user-log-group' + + FetchCloudLogsLogGroup: + Type: AWS::Logs::LogGroup + Condition: CreateFetchCloudLogsResources + Properties: + LogGroupName: !Sub '/aws/lambda/${ResourceName}-fetch-cloud-logs' + RetentionInDays: 7 + Tags: + - Key: 'sysdig.com/response-actions/resource-name' + Value: 'fetch-cloud-logs-log-group' + + RemovePolicyLogGroup: + Type: AWS::Logs::LogGroup + Condition: CreateQuarantineUserResources + Properties: + LogGroupName: !Sub '/aws/lambda/${ResourceName}-remove-policy' + RetentionInDays: 7 + Tags: + - Key: 'sysdig.com/response-actions/resource-name' + Value: 'remove-policy-log-group' + + ConfigureResourceAccessLogGroup: + Type: AWS::Logs::LogGroup + Condition: CreateMakePrivateResources + Properties: + LogGroupName: !Sub '/aws/lambda/${ResourceName}-configure-resource-access' + RetentionInDays: 7 + Tags: + - Key: 'sysdig.com/response-actions/resource-name' + Value: 'configure-resource-access-log-group' + + CreateVolumeSnapshotsLogGroup: + Type: AWS::Logs::LogGroup + Condition: CreateVolumeSnapshotResources + Properties: + LogGroupName: !Sub '/aws/lambda/${ResourceName}-create-volume-snapshots' + RetentionInDays: 7 + Tags: + - Key: 'sysdig.com/response-actions/resource-name' + Value: 'create-volume-snapshots-log-group' + + DeleteVolumeSnapshotsLogGroup: + Type: AWS::Logs::LogGroup + Condition: CreateVolumeSnapshotResources + Properties: + LogGroupName: !Sub '/aws/lambda/${ResourceName}-delete-volume-snapshots' + RetentionInDays: 7 + Tags: + - Key: 'sysdig.com/response-actions/resource-name' + Value: 'delete-volume-snapshots-log-group' + + # Lambda Functions (Regional Resources) + QuarantineUserFunction: + Type: AWS::Lambda::Function + Condition: CreateQuarantineUserResources + DependsOn: + - QuarantineUserLogGroup + - QuarantineUserPackage + Properties: + FunctionName: !Sub '${ResourceName}-quarantine-user' + Runtime: python3.12 + Handler: app.index.handler + Role: !Ref QuarantineUserRoleArn + Code: + S3Bucket: !Ref LambdaPackagesBucket + S3Key: !Sub '${ResponseActionsVersion}/quarantine_user.zip' + Timeout: 300 + MemorySize: 128 + Environment: + Variables: + API_BASE_URL: !Ref ApiBaseUrl + DELEGATE_ROLE_NAME: !Ref QuarantineUserRoleName + Tags: + - Key: Name + Value: !Sub '${ResourceName}-quarantine-user' + - Key: 'sysdig.com/response-actions/cloud-actions' + Value: 'true' + - Key: 'sysdig.com/response-actions/resource-name' + Value: 'quarantine-user-lambda' + + FetchCloudLogsFunction: + Type: AWS::Lambda::Function + Condition: CreateFetchCloudLogsResources + DependsOn: + - FetchCloudLogsLogGroup + - FetchCloudLogsPackage + Properties: + FunctionName: !Sub '${ResourceName}-fetch-cloud-logs' + Runtime: python3.12 + Handler: app.index.handler + Role: !Ref FetchCloudLogsRoleArn + Code: + S3Bucket: !Ref LambdaPackagesBucket + S3Key: !Sub '${ResponseActionsVersion}/fetch_cloud_logs.zip' + Timeout: 300 + MemorySize: 128 + Environment: + Variables: + API_BASE_URL: !Ref ApiBaseUrl + DELEGATE_ROLE_NAME: !Ref FetchCloudLogsRoleName + Tags: + - Key: Name + Value: !Sub '${ResourceName}-fetch-cloud-logs' + - Key: 'sysdig.com/response-actions/cloud-actions' + Value: 'true' + - Key: 'sysdig.com/response-actions/resource-name' + Value: 'fetch-cloud-logs-lambda' + + RemovePolicyFunction: + Type: AWS::Lambda::Function + Condition: CreateQuarantineUserResources + DependsOn: + - RemovePolicyLogGroup + - RemovePolicyPackage + Properties: + FunctionName: !Sub '${ResourceName}-remove-policy' + Runtime: python3.12 + Handler: app.index.handler + Role: !Ref RemovePolicyRoleArn + Code: + S3Bucket: !Ref LambdaPackagesBucket + S3Key: !Sub '${ResponseActionsVersion}/remove_policy.zip' + Timeout: 300 + MemorySize: 128 + Environment: + Variables: + API_BASE_URL: !Ref ApiBaseUrl + DELEGATE_ROLE_NAME: !Ref RemovePolicyRoleName + Tags: + - Key: Name + Value: !Sub '${ResourceName}-remove-policy' + - Key: 'sysdig.com/response-actions/cloud-actions' + Value: 'true' + - Key: 'sysdig.com/response-actions/resource-name' + Value: 'remove-policy-lambda' + + ConfigureResourceAccessFunction: + Type: AWS::Lambda::Function + Condition: CreateMakePrivateResources + DependsOn: + - ConfigureResourceAccessLogGroup + - ConfigureResourceAccessPackage + Properties: + FunctionName: !Sub '${ResourceName}-configure-resource-access' + Runtime: python3.12 + Handler: app.index.handler + Role: !Ref ConfigureResourceAccessRoleArn + Code: + S3Bucket: !Ref LambdaPackagesBucket + S3Key: !Sub '${ResponseActionsVersion}/configure_resource_access.zip' + Timeout: 300 + MemorySize: 128 + Environment: + Variables: + API_BASE_URL: !Ref ApiBaseUrl + DELEGATE_ROLE_NAME: !Ref ConfigureResourceAccessRoleName + Tags: + - Key: Name + Value: !Sub '${ResourceName}-configure-resource-access' + - Key: 'sysdig.com/response-actions/cloud-actions' + Value: 'true' + - Key: 'sysdig.com/response-actions/resource-name' + Value: 'configure-resource-access-lambda' + + CreateVolumeSnapshotsFunction: + Type: AWS::Lambda::Function + Condition: CreateVolumeSnapshotResources + DependsOn: + - CreateVolumeSnapshotsLogGroup + - CreateVolumeSnapshotsPackage + Properties: + FunctionName: !Sub '${ResourceName}-create-volume-snapshots' + Runtime: python3.12 + Handler: app.index.handler + Role: !Ref CreateVolumeSnapshotsRoleArn + Code: + S3Bucket: !Ref LambdaPackagesBucket + S3Key: !Sub '${ResponseActionsVersion}/create_volume_snapshots.zip' + Timeout: 300 + MemorySize: 128 + Environment: + Variables: + API_BASE_URL: !Ref ApiBaseUrl + DELEGATE_ROLE_NAME: !Ref CreateVolumeSnapshotsRoleName + Tags: + - Key: Name + Value: !Sub '${ResourceName}-create-volume-snapshots' + - Key: 'sysdig.com/response-actions/cloud-actions' + Value: 'true' + - Key: 'sysdig.com/response-actions/resource-name' + Value: 'create-volume-snapshots-lambda' + + DeleteVolumeSnapshotsFunction: + Type: AWS::Lambda::Function + Condition: CreateVolumeSnapshotResources + DependsOn: + - DeleteVolumeSnapshotsLogGroup + - DeleteVolumeSnapshotsPackage + Properties: + FunctionName: !Sub '${ResourceName}-delete-volume-snapshots' + Runtime: python3.12 + Handler: app.index.handler + Role: !Ref DeleteVolumeSnapshotsRoleArn + Code: + S3Bucket: !Ref LambdaPackagesBucket + S3Key: !Sub '${ResponseActionsVersion}/delete_volume_snapshots.zip' + Timeout: 300 + MemorySize: 128 + Environment: + Variables: + API_BASE_URL: !Ref ApiBaseUrl + DELEGATE_ROLE_NAME: !Ref DeleteVolumeSnapshotsRoleName + Tags: + - Key: Name + Value: !Sub '${ResourceName}-delete-volume-snapshots' + - Key: 'sysdig.com/response-actions/cloud-actions' + Value: 'true' + - Key: 'sysdig.com/response-actions/resource-name' + Value: 'delete-volume-snapshots-lambda' + + Outputs: + QuarantineUserFunctionArn: + Condition: CreateQuarantineUserResources + Value: !GetAtt QuarantineUserFunction.Arn + FetchCloudLogsFunctionArn: + Condition: CreateFetchCloudLogsResources + Value: !GetAtt FetchCloudLogsFunction.Arn + RemovePolicyFunctionArn: + Condition: CreateQuarantineUserResources + Value: !GetAtt RemovePolicyFunction.Arn + ConfigureResourceAccessFunctionArn: + Condition: CreateMakePrivateResources + Value: !GetAtt ConfigureResourceAccessFunction.Arn + CreateVolumeSnapshotsFunctionArn: + Condition: CreateVolumeSnapshotResources + Value: !GetAtt CreateVolumeSnapshotsFunction.Arn + DeleteVolumeSnapshotsFunctionArn: + Condition: CreateVolumeSnapshotResources + Value: !GetAtt DeleteVolumeSnapshotsFunction.Arn + + # Organizational Delegate Roles StackSet + OrganizationDelegateRolesStackSet: + Type: AWS::CloudFormation::StackSet + Condition: IsOrganizational + Properties: + StackSetName: !Sub sysdig-secure-ra-${NameSuffix}-delegate-roles + Description: Sysdig Response Actions Delegate Roles - Multi-Account Deployment + PermissionModel: SERVICE_MANAGED + Capabilities: + - "CAPABILITY_NAMED_IAM" + AutoDeployment: + Enabled: true + RetainStacksOnAccountRemoval: false + ManagedExecution: + Active: true + OperationPreferences: + MaxConcurrentPercentage: 100 + FailureTolerancePercentage: 90 + ConcurrencyMode: SOFT_FAILURE_TOLERANCE + Parameters: + - ParameterKey: QuarantineUserLambdaRoleArn + ParameterValue: !GetAtt QuarantineUserRole.Arn + - ParameterKey: QuarantineUserRoleName + ParameterValue: !Select [1, !Split ["/", !GetAtt QuarantineUserRole.Arn]] + - ParameterKey: FetchCloudLogsLambdaRoleArn + ParameterValue: !GetAtt FetchCloudLogsRole.Arn + - ParameterKey: FetchCloudLogsRoleName + ParameterValue: !Select [1, !Split ["/", !GetAtt FetchCloudLogsRole.Arn]] + - ParameterKey: RemovePolicyLambdaRoleArn + ParameterValue: !GetAtt RemovePolicyRole.Arn + - ParameterKey: RemovePolicyRoleName + ParameterValue: !Select [1, !Split ["/", !GetAtt RemovePolicyRole.Arn]] + - ParameterKey: ConfigureResourceAccessLambdaRoleArn + ParameterValue: !GetAtt ConfigureResourceAccessRole.Arn + - ParameterKey: ConfigureResourceAccessRoleName + ParameterValue: !Select [1, !Split ["/", !GetAtt ConfigureResourceAccessRole.Arn]] + - ParameterKey: CreateVolumeSnapshotsLambdaRoleArn + ParameterValue: !GetAtt CreateVolumeSnapshotsRole.Arn + - ParameterKey: CreateVolumeSnapshotsRoleName + ParameterValue: !Select [1, !Split ["/", !GetAtt CreateVolumeSnapshotsRole.Arn]] + - ParameterKey: DeleteVolumeSnapshotsLambdaRoleArn + ParameterValue: !GetAtt DeleteVolumeSnapshotsRole.Arn + - ParameterKey: DeleteVolumeSnapshotsRoleName + ParameterValue: !Select [1, !Split ["/", !GetAtt DeleteVolumeSnapshotsRole.Arn]] + - ParameterKey: EnabledResponseActions + ParameterValue: !Join [",", !Ref EnabledResponseActions] + StackInstancesGroup: + - DeploymentTargets: + OrganizationalUnitIds: + Fn::If: + - AllowedInclusions + - !Ref IncludeOUIDs + - !Ref RootOUID + AccountFilterType: + Fn::If: + - AccountExclusionsConfigured + - "DIFFERENCE" + - "NONE" + Accounts: + Fn::If: + - AccountExclusionsConfigured + - !Ref ExcludeAccounts + - !Ref 'AWS::NoValue' + Regions: [!Select [0, !Ref Regions]] + TemplateBody: | + AWSTemplateFormatVersion: '2010-09-09' + Description: 'Sysdig Response Actions Delegate Roles - Multi-Account Deployment' + + Parameters: + TemplateVersion: + Type: String + Description: Template version hash to force updates + Default: "1" + QuarantineUserLambdaRoleArn: + Type: String + Description: ARN of the Lambda execution role for quarantine user function + QuarantineUserRoleName: + Type: String + Description: Name for the quarantine user delegate role + FetchCloudLogsLambdaRoleArn: + Type: String + Description: ARN of the Lambda execution role for fetch cloud logs function + FetchCloudLogsRoleName: + Type: String + Description: Name for the fetch cloud logs delegate role + RemovePolicyLambdaRoleArn: + Type: String + Description: ARN of the Lambda execution role for remove policy function + RemovePolicyRoleName: + Type: String + Description: Name for the remove policy delegate role + ConfigureResourceAccessLambdaRoleArn: + Type: String + Description: ARN of the Lambda execution role for configure resource access function + ConfigureResourceAccessRoleName: + Type: String + Description: Name for the configure resource access delegate role + CreateVolumeSnapshotsLambdaRoleArn: + Type: String + Description: ARN of the Lambda execution role for create volume snapshots function + CreateVolumeSnapshotsRoleName: + Type: String + Description: Name for the create volume snapshots delegate role + DeleteVolumeSnapshotsLambdaRoleArn: + Type: String + Description: ARN of the Lambda execution role for delete volume snapshots function + DeleteVolumeSnapshotsRoleName: + Type: String + Description: Name for the delete volume snapshots delegate role + EnabledResponseActions: + Type: String + Description: Comma-separated list of response actions to enable + Default: "make_private,fetch_cloud_logs,create_volume_snapshot,quarantine_user" + + Conditions: + CreateQuarantineUserResources: !Not [!Equals [!Select [0, !Split ["quarantine_user", !Ref EnabledResponseActions]], !Ref EnabledResponseActions]] + CreateFetchCloudLogsResources: !Not [!Equals [!Select [0, !Split ["fetch_cloud_logs", !Ref EnabledResponseActions]], !Ref EnabledResponseActions]] + CreateMakePrivateResources: !Not [!Equals [!Select [0, !Split ["make_private", !Ref EnabledResponseActions]], !Ref EnabledResponseActions]] + CreateVolumeSnapshotResources: !Not [!Equals [!Select [0, !Split ["create_volume_snapshot", !Ref EnabledResponseActions]], !Ref EnabledResponseActions]] + + Resources: + # Delegate Role: Configure Resource Access + ConfigureAccessDelegateRole: + Type: AWS::IAM::Role + Condition: CreateMakePrivateResources + Properties: + RoleName: !Ref ConfigureResourceAccessRoleName + Description: Delegate role for configuring resource access + MaxSessionDuration: 3600 + AssumeRolePolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Principal: + AWS: !Ref ConfigureResourceAccessLambdaRoleArn + Action: 'sts:AssumeRole' + Policies: + - PolicyName: response-actions-configure-resource-access + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - 's3:GetBucketLocation' + - 's3:GetBucketPublicAccessBlock' + - 's3:PutBucketPublicAccessBlock' + - 's3:ListAllMyBuckets' + Resource: '*' + - Effect: Allow + Action: + - 'rds:DescribeDBInstances' + - 'rds:ModifyDBInstance' + - 'sts:GetCallerIdentity' + Resource: '*' + Tags: + - Key: ManagedBy + Value: CloudFormation + - Key: Purpose + Value: ResponseActions + - Key: 'sysdig.com/response-actions/resource-name' + Value: 'configure-resource-access-delegate-role' + + # Delegate Role: Create Volume Snapshot + CreateVolumeSnapshotDelegateRole: + Type: AWS::IAM::Role + Condition: CreateVolumeSnapshotResources + Properties: + RoleName: !Ref CreateVolumeSnapshotsRoleName + Description: Delegate role for creating volume snapshots + MaxSessionDuration: 3600 + AssumeRolePolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Principal: + AWS: !Ref CreateVolumeSnapshotsLambdaRoleArn + Action: 'sts:AssumeRole' + Policies: + - PolicyName: response-actions-create-volume-snapshot + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - 'logs:CreateLogGroup' + - 'logs:CreateLogStream' + - 'logs:PutLogEvents' + Resource: 'arn:aws:logs:*:*:*' + - Effect: Allow + Action: + - 'ec2:DescribeInstances' + - 'ec2:DescribeVolumes' + - 'ec2:DescribeSnapshots' + - 'ec2:CreateSnapshot' + - 'ec2:CreateTags' + - 'sts:GetCallerIdentity' + Resource: '*' + - Effect: Allow + Action: + - 'ec2:CreateTags' + Resource: + - 'arn:aws:ec2:*:*:snapshot/*' + Tags: + - Key: ManagedBy + Value: CloudFormation + - Key: Purpose + Value: ResponseActions + - Key: 'sysdig.com/response-actions/resource-name' + Value: 'create-volume-snapshot-delegate-role' + + # Delegate Role: Delete Volume Snapshot + DeleteVolumeSnapshotDelegateRole: + Type: AWS::IAM::Role + Condition: CreateVolumeSnapshotResources + Properties: + RoleName: !Ref DeleteVolumeSnapshotsRoleName + Description: Delegate role for deleting volume snapshots + MaxSessionDuration: 3600 + AssumeRolePolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Principal: + AWS: !Ref DeleteVolumeSnapshotsLambdaRoleArn + Action: 'sts:AssumeRole' + Policies: + - PolicyName: response-actions-delete-volume-snapshots + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - 'logs:CreateLogGroup' + - 'logs:CreateLogStream' + - 'logs:PutLogEvents' + Resource: 'arn:aws:logs:*:*:*' + - Effect: Allow + Action: + - 'ec2:DescribeSnapshots' + - 'ec2:DeleteSnapshot' + - 'sts:GetCallerIdentity' + Resource: '*' + Tags: + - Key: ManagedBy + Value: CloudFormation + - Key: Purpose + Value: ResponseActions + - Key: 'sysdig.com/response-actions/resource-name' + Value: 'delete-volume-snapshot-delegate-role' + + # Delegate Role: Fetch Cloud Logs + FetchCloudLogsDelegateRole: + Type: AWS::IAM::Role + Condition: CreateFetchCloudLogsResources + Properties: + RoleName: !Ref FetchCloudLogsRoleName + Description: Delegate role for fetching cloud logs + MaxSessionDuration: 3600 + AssumeRolePolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Principal: + AWS: !Ref FetchCloudLogsLambdaRoleArn + Action: 'sts:AssumeRole' + Policies: + - PolicyName: response-actions-fetch-cloud-logs + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - 'cloudtrail:LookupEvents' + - 'sts:GetCallerIdentity' + Resource: '*' + Tags: + - Key: ManagedBy + Value: CloudFormation + - Key: Purpose + Value: ResponseActions + - Key: 'sysdig.com/response-actions/resource-name' + Value: 'fetch-cloud-logs-delegate-role' + + # Delegate Role: Quarantine User + QuarantineUserRoleDelegateRole: + Type: AWS::IAM::Role + Condition: CreateQuarantineUserResources + Properties: + RoleName: !Ref QuarantineUserRoleName + Description: Delegate role for quarantining users + MaxSessionDuration: 3600 + AssumeRolePolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Principal: + AWS: !Ref QuarantineUserLambdaRoleArn + Action: 'sts:AssumeRole' + Policies: + - PolicyName: response-actions-quarantine-user + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - 'iam:AttachUserPolicy' + - 'iam:DetachUserPolicy' + - 'iam:PutUserPolicy' + - 'iam:DeleteUserPolicy' + - 'iam:ListUserPolicies' + - 'iam:ListAttachedUserPolicies' + - 'iam:GetUser' + - 'iam:GetUserPolicy' + - 'iam:TagUser' + - 'iam:UntagUser' + - 'iam:ListUserTags' + - 'iam:AttachRolePolicy' + - 'iam:DetachRolePolicy' + - 'iam:GetRole' + - 'iam:ListRolePolicies' + - 'iam:ListAttachedRolePolicies' + - 'iam:GetPolicy' + - 'iam:CreatePolicy' + - 'sts:GetCallerIdentity' + Resource: '*' + Tags: + - Key: ManagedBy + Value: CloudFormation + - Key: Purpose + Value: ResponseActions + - Key: 'sysdig.com/response-actions/resource-name' + Value: 'quarantine-user-delegate-role' + + # Delegate Role: Remove Policy + RemovePolicyDelegateRole: + Type: AWS::IAM::Role + Condition: CreateQuarantineUserResources + Properties: + RoleName: !Ref RemovePolicyRoleName + Description: Delegate role for removing policies + MaxSessionDuration: 3600 + AssumeRolePolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Principal: + AWS: !Ref RemovePolicyLambdaRoleArn + Action: 'sts:AssumeRole' + Policies: + - PolicyName: response-actions-remove-policy + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - 'iam:DetachUserPolicy' + - 'iam:DetachRolePolicy' + - 'iam:ListAttachedUserPolicies' + - 'iam:ListAttachedRolePolicies' + - 'iam:GetUser' + - 'iam:GetRole' + - 'sts:GetCallerIdentity' + Resource: '*' + Tags: + - Key: ManagedBy + Value: CloudFormation + - Key: Purpose + Value: ResponseActions + - Key: 'sysdig.com/response-actions/resource-name' + Value: 'remove-policy-delegate-role' + + Outputs: + ConfigureAccessDelegateRoleName: + Condition: CreateMakePrivateResources + Value: !Ref ConfigureAccessDelegateRole + Description: Name of the configure resource access delegate role + CreateVolumeSnapshotDelegateRoleName: + Condition: CreateVolumeSnapshotResources + Value: !Ref CreateVolumeSnapshotDelegateRole + Description: Name of the create volume snapshot delegate role + DeleteVolumeSnapshotDelegateRoleName: + Condition: CreateVolumeSnapshotResources + Value: !Ref DeleteVolumeSnapshotDelegateRole + Description: Name of the delete volume snapshot delegate role + FetchCloudLogsDelegateRoleName: + Condition: CreateFetchCloudLogsResources + Value: !Ref FetchCloudLogsDelegateRole + Description: Name of the fetch cloud logs delegate role + QuarantineUserRoleDelegateRoleName: + Condition: CreateQuarantineUserResources + Value: !Ref QuarantineUserRoleDelegateRole + Description: Name of the quarantine user delegate role + RemovePolicyDelegateRoleName: + Condition: CreateQuarantineUserResources + Value: !Ref RemovePolicyDelegateRole + Description: Name of the remove policy delegate role + +Outputs: + CrossAccountRoleARN: + Description: ARN of the cross-account role for Lambda invocation + Value: !GetAtt CrossAccountLambdaInvokerRole.Arn + LambdaStackSetName: + Description: Name of the CloudFormation StackSet deploying Lambda functions + Value: !Ref LambdaFunctionsStackSet + DelegateRolesStackSetName: + Description: Name of the CloudFormation StackSet deploying delegate roles + Condition: IsOrganizational + Value: !Ref OrganizationDelegateRolesStackSet diff --git a/modules/response_actions.components.json b/modules/response_actions.components.json new file mode 100644 index 0000000..9da7b2a --- /dev/null +++ b/modules/response_actions.components.json @@ -0,0 +1,34 @@ +[ + { + "type": "COMPONENT_CLOUD_RESPONDER", + "instance": "secure-runtime", + "cloudResponderMetadata": { + "aws": { + "crossAccountRoleName": "{{CrossAccountRoleName}}", + "regions": ["{{Regions}}"], + "lambdaNames": [ + "{{QuarantineUserLambdaName}}", + "{{FetchCloudLogsLambdaName}}", + "{{RemovePolicyLambdaName}}", + "{{ConfigureResourceAccessLambdaName}}", + "{{CreateVolumeSnapshotsLambdaName}}", + "{{DeleteVolumeSnapshotsLambdaName}}" + ] + } + } + }, + { + "type": "COMPONENT_CLOUD_RESPONDER_ROLES", + "instance": "secure-runtime", + "cloudResponderRolesMetadata": { + "aws": { + "quarantineUserRoleName": "{{QuarantineUserRoleName}}", + "fetchCloudLogsRoleName": "{{FetchCloudLogsRoleName}}", + "removePolicyRoleName": "{{RemovePolicyRoleName}}", + "configureResourceAccessRoleName": "{{ConfigureResourceAccessRoleName}}", + "createVolumeSnapshotsRoleName": "{{CreateVolumeSnapshotsRoleName}}", + "deleteVolumeSnapshotsRoleName": "{{DeleteVolumeSnapshotsRoleName}}" + } + } + } +]