diff --git a/.project_automation/functional_tests/entrypoint.sh b/.project_automation/functional_tests/entrypoint.sh index 091ecd7..aa35a7f 100755 --- a/.project_automation/functional_tests/entrypoint.sh +++ b/.project_automation/functional_tests/entrypoint.sh @@ -45,6 +45,8 @@ run_test "cw-test-ct" run_test "cw-test-ssm" +run_test "cw-test-smlambda" + run_test "cw-test-all" ## Executing ash tool diff --git a/.taskcat.yml b/.taskcat.yml index fb1c02c..b00c685 100644 --- a/.taskcat.yml +++ b/.taskcat.yml @@ -41,7 +41,19 @@ tests: EnableSSMDistributor: "true" regions: - us-east-1 - template: templates/crowdstrike_init_stack.yaml + template: templates/crowdstrike_init_stack.yaml + cw-test-smlambda: + parameters: + FalconClientID: $[taskcat_ssm_/crowdstrike/falcon_client_id] + FalconSecret: $[taskcat_ssm_/crowdstrike/falcon_secret] + SourceS3BucketName: $[taskcat_autobucket] + S3BucketRegion: $[taskcat_current_region] + ProvisionOU: $[taskcat_ssm_/crowdstrike/provision-ou] + ExcludeRegions: $[taskcat_ssm_/crowdstrike/exclude_regions] + APICredentialsStorageMode: "lambda" + regions: + - us-east-1 + template: templates/crowdstrike_init_stack.yaml cw-test-all: parameters: FalconClientID: $[taskcat_ssm_/crowdstrike/falcon_client_id] diff --git a/guide/content/deployment-steps.md b/guide/content/deployment-steps.md index 1852638..25be171 100644 --- a/guide/content/deployment-steps.md +++ b/guide/content/deployment-steps.md @@ -20,6 +20,7 @@ description: Deployment steps. * **Provision OUs**: _Comma Delimited List of OU(s) to provision resources. If you are provisioning the entire Organization, please enter the Root OU (r-****)_ * **Exclude Prohibited Regions**: `[, ,....]` _(Exclude regions from EventBridge Rules for IOA. Use this when SCPs cause stacksets to fail.)_ * **Enable Sensor Management**: Choose `true` or `false`. The default is `false` + * **API Credentials Storage Mode**: Choose `secret` or `lambda`. The default is `secret` * **EnableSSMDistributor**: Choose `true` or `false`. The default is `true` * **AutomationAssumeRole**: Define the name of the SSM Automation Execution Role. The default is `crowdstrike-distributor-deploy-role` * **ApplyOnlyAtCronInterval**: Choose `true` or `false`. The default is `false` diff --git a/templates/aws_cspm_cloudformation_v2.json b/templates/aws_cspm_cloudformation_v2.json index 4150d8e..68fc6e1 100644 --- a/templates/aws_cspm_cloudformation_v2.json +++ b/templates/aws_cspm_cloudformation_v2.json @@ -63,6 +63,12 @@ "Description": "Falcon Client Secret", "MinLength": "1", "NoEcho": "true" + }, + "APICredentialsStorageMode": { + "Type": "String", + "Description": "How Falcon API credentials are stored. 'lambda' stores them in the lambda environment variables, 'secret' in an AWS secret.", + "Default": "lambda", + "AllowedValues": ["lambda", "secret"] } }, "Conditions": { @@ -96,6 +102,24 @@ "Ref": "EnableSensorManagement" } ] + }, + "APICredentialsInSecretEnabled" : { + "Fn::Equals": [ + {"Ref": "APICredentialsStorageMode"}, + "secret" + ] + }, + "APICredentialsInLambdaEnabled" : { + "Fn::Equals": [ + {"Ref": "APICredentialsStorageMode"}, + "lambda" + ] + }, + "ShouldCreateSensorManagementCredentialsSecret": { + "Fn::And": [ + {"Condition": "ShouldCreateSensorManagementResources"}, + {"Condition": "APICredentialsInSecretEnabled"} + ] } }, "Resources": { @@ -242,7 +266,7 @@ } ] } - }, + }, "Properties": { "TrailName": "crowdstrike-cloudtrail", "S3BucketName": { @@ -384,6 +408,22 @@ ], "Effect": "Allow", "Sid": "Logging" + }, + { + "Fn::If": [ + "APICredentialsInSecretEnabled", + { + "Sid": "GetFalconCredentials", + "Action": [ + "secretsmanager:GetSecretValue" + ], + "Resource": [ + {"Fn::Sub": "arn:aws:secretsmanager:${AWS::Region}:${AWS::AccountId}:secret:/CrowdStrike/CSPM/SensorManagement/FalconAPICredentials-??????"} + ], + "Effect": "Allow" + }, + {"Ref" : "AWS::NoValue"} + ] } ] } @@ -409,6 +449,25 @@ "RetentionInDays": 1 } }, + "CrowdStrikeSensorManagementFalconCredentialsSecret": { + "Type": "AWS::SecretsManager::Secret", + "Condition": "ShouldCreateSensorManagementCredentialsSecret", + "Metadata": { + "checkov": { + "skip": [ + { + "id": "CKV_AWS_149", + "comment": "The default key aws/secretsmanager is sufficient to secure this resource" + } + ] + } + }, + "Properties": { + "Name": "/CrowdStrike/CSPM/SensorManagement/FalconAPICredentials", + "Description": "Falcon API credentials. Used by the 1-Click sensor management orchestrator.", + "SecretString": {"Fn::Sub": "{\"ClientId\":\"${ClientID}\",\"ClientSecret\":\"${ClientSecret}\"}"} + } + }, "CrowdStrikeSensorManagementLambda": { "Type": "AWS::Lambda::Function", "Condition": "ShouldCreateSensorManagementResources", @@ -421,7 +480,7 @@ }, { "id": "CKV_AWS_173", - "comment": "Future release will support this" + "comment": "This is supported by APICredentialsStorageMode parameter" }, { "id": "W89", @@ -449,10 +508,25 @@ "Variables": { "CS_ADDRESS": "", "CS_CLIENT_ID": { - "Ref": "ClientID" + "Fn::If": [ + "APICredentialsInLambdaEnabled", + {"Ref": "ClientID"}, + {"Ref": "AWS::NoValue"} + ] }, "CS_CLIENT_SECRET": { - "Ref": "ClientSecret" + "Fn::If": [ + "APICredentialsInLambdaEnabled", + {"Ref": "ClientSecret"}, + {"Ref": "AWS::NoValue"} + ] + }, + "CS_API_CREDENTIALS_AWS_SECRET": { + "Fn::If": [ + "APICredentialsInSecretEnabled", + "/CrowdStrike/CSPM/SensorManagement/FalconAPICredentials", + {"Ref": "AWS::NoValue"} + ] }, "CS_MODE": "force_auth", "CS_DEBUG_ENABLED": "true" @@ -475,4 +549,4 @@ "DependsOn": "CrowdStrikeSensorManagementLogGroup" } } -} +} \ No newline at end of file diff --git a/templates/crowdstrike_init_stack.yaml b/templates/crowdstrike_init_stack.yaml index 89bafcb..2202c9e 100644 --- a/templates/crowdstrike_init_stack.yaml +++ b/templates/crowdstrike_init_stack.yaml @@ -43,6 +43,7 @@ Metadata: default: Sensor Management Parameters: - EnableSensorManagement + - APICredentialsStorageMode - Label: default: AWS Organization ID - Lambda Function Properties Parameters: @@ -94,6 +95,8 @@ Metadata: default: Max Concurrency Allowed SecretsManagerSecretName: default: Secrets Manager Secret Name + APICredentialsStorageMode: + default: API Credentials Storage Mode Conditions: CreateIOAResources: !Equals [ !Ref 'EnableIOA', true ] @@ -218,6 +221,11 @@ Parameters: Description: The maximum number of targets allowed to run the association at the same time. You can specify a number, for example 10, or a percentage of the target set, for example 10%. The default value is 100%, which means all targets run the association at the same time. Type: String Default: '20%' + APICredentialsStorageMode: + Type: String + Description: How Falcon API credentials are stored for Sensor Management. 'lambda' stores them in the lambda environment variables, 'secret' in an AWS secret. + Default: 'secret' + AllowedValues: ['lambda', 'secret'] Mappings: CloudMap: @@ -330,6 +338,7 @@ Resources: CSAccountNumber: !GetAtt TriggerRegisterAccountLambda.cs_account_id EnableIOA: !Ref EnableIOA EnableSensorManagement: !Ref EnableSensorManagement + APICredentialsStorageMode: !Ref APICredentialsStorageMode ClientID: !Ref FalconClientID ClientSecret: !Ref FalconSecret TemplateURL: !Sub https://${SourceS3BucketName}.s3.${S3BucketRegion}.amazonaws.com/${SourceS3BucketNamePrefix}/templates/aws_cspm_cloudformation_v2.json @@ -355,6 +364,8 @@ Resources: ParameterValue: !Ref EnableIOA - ParameterKey: EnableSensorManagement ParameterValue: !Ref EnableSensorManagement + - ParameterKey: APICredentialsStorageMode + ParameterValue: !Ref APICredentialsStorageMode - ParameterKey: ClientID ParameterValue: !Ref FalconClientID - ParameterKey: ClientSecret