diff --git a/modules/project_cleanup/README.md b/modules/project_cleanup/README.md index a557c03..223a479 100644 --- a/modules/project_cleanup/README.md +++ b/modules/project_cleanup/README.md @@ -16,15 +16,18 @@ The following services must be enabled on the project housing the cleanup functi - Cloud Scheduler (`cloudscheduler.googleapis.com`) - Cloud Resource Manager (`cloudresourcemanager.googleapis.com`) - Compute Engine API (`compute.googleapis.com`) +- Security Command Center API (`securitycenter.googleapis.com`) ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| +| clean\_up\_org\_level\_scc\_notifications | Clean up organization level Security Command Center notifications. | `bool` | `false` | no | | clean\_up\_org\_level\_tag\_keys | Clean up organization level Tag Keys. | `bool` | `false` | no | | function\_timeout\_s | The amount of time in seconds allotted for the execution of the function. | `number` | `500` | no | | job\_schedule | Cleaner function run frequency, in cron syntax | `string` | `"*/5 * * * *"` | no | +| list\_scc\_notifications\_page\_size | The maximum number of notification configs to return in the call to `ListNotificationConfigs` service. The minimun value is 1 and the maximum value is 1000. | `number` | `500` | no | | max\_project\_age\_in\_hours | The maximum number of hours that a GCP project, selected by `target_tag_name` and `target_tag_value`, can exist | `number` | `6` | no | | organization\_id | The organization ID whose projects to clean up | `string` | n/a | yes | | project\_id | The project ID to host the scheduled function in | `string` | n/a | yes | @@ -33,6 +36,7 @@ The following services must be enabled on the project housing the cleanup functi | target\_excluded\_tagkeys | List of organization Tag Key short names that won't be deleted. | `list(string)` | `[]` | no | | target\_folder\_id | Folder ID to delete all projects under. | `string` | `""` | no | | target\_included\_labels | Map of project lablels that will be deleted. | `map(string)` | `{}` | no | +| target\_included\_scc\_notifications | List of organization Security Command Center notifications names regex that will be deleted. Regex example: `.*/notificationConfigs/scc-notify-.*` | `list(string)` | `[]` | no | | target\_tag\_name | The name of a tag to filter GCP projects on for consideration by the cleanup utility (legacy, use `target_included_labels` map instead). | `string` | `""` | no | | target\_tag\_value | The value of a tag to filter GCP projects on for consideration by the cleanup utility (legacy, use `target_included_labels` map instead). | `string` | `""` | no | | topic\_name | Name of pubsub topic connecting the scheduled projects cleanup function | `string` | `"pubsub_scheduled_project_cleaner"` | no | diff --git a/modules/project_cleanup/function_source/README.md b/modules/project_cleanup/function_source/README.md index 01934e3..f51035c 100644 --- a/modules/project_cleanup/function_source/README.md +++ b/modules/project_cleanup/function_source/README.md @@ -22,4 +22,4 @@ The following environment variables may be specified to configure the cleanup ut ## Required Permissions -This Cloud Function must be run as a Service Account with the `Organization Administrator` role. +This Cloud Function must be run as a Service Account with the `Organization Administrator` (`roles/resourcemanager.organizationAdmin`) role. diff --git a/modules/project_cleanup/function_source/go.mod b/modules/project_cleanup/function_source/go.mod index 3881a90..3d03730 100644 --- a/modules/project_cleanup/function_source/go.mod +++ b/modules/project_cleanup/function_source/go.mod @@ -3,15 +3,19 @@ module github.com/terraform-google-modules/terraform-google-scheduled-function/m go 1.21 require ( + cloud.google.com/go/securitycenter v1.28.0 golang.org/x/net v0.24.0 golang.org/x/oauth2 v0.19.0 google.golang.org/api v0.177.0 ) require ( + cloud.google.com/go v0.112.2 // indirect cloud.google.com/go/auth v0.3.0 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect cloud.google.com/go/compute/metadata v0.3.0 // indirect + cloud.google.com/go/iam v1.1.6 // indirect + cloud.google.com/go/longrunning v0.5.5 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect @@ -22,13 +26,18 @@ require ( github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect github.com/googleapis/gax-go/v2 v2.12.3 // indirect go.opencensus.io v0.24.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect golang.org/x/crypto v0.22.0 // indirect + golang.org/x/sync v0.7.0 // indirect golang.org/x/sys v0.19.0 // indirect golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect + google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240314234333-6e1732d8331c // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240429193739-8cf5692501f6 // indirect google.golang.org/grpc v1.63.2 // indirect google.golang.org/protobuf v1.34.0 // indirect diff --git a/modules/project_cleanup/function_source/go.sum b/modules/project_cleanup/function_source/go.sum index 2748528..c79693c 100644 --- a/modules/project_cleanup/function_source/go.sum +++ b/modules/project_cleanup/function_source/go.sum @@ -1,10 +1,18 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.112.2 h1:ZaGT6LiG7dBzi6zNOvVZwacaXlmf3lRqnC4DQzqyRQw= +cloud.google.com/go v0.112.2/go.mod h1:iEqjp//KquGIJV/m+Pk3xecgKNhV+ry+vVTsy4TbDms= cloud.google.com/go/auth v0.3.0 h1:PRyzEpGfx/Z9e8+lHsbkoUVXD0gnu4MNmm7Gp8TQNIs= cloud.google.com/go/auth v0.3.0/go.mod h1:lBv6NKTWp8E3LPzmO1TbiiRKc4drLOfHsgmlH9ogv5w= cloud.google.com/go/auth/oauth2adapt v0.2.2 h1:+TTV8aXpjeChS9M+aTtN/TjdQnzJvmzKFt//oWu7HX4= cloud.google.com/go/auth/oauth2adapt v0.2.2/go.mod h1:wcYjgpZI9+Yu7LyYBg4pqSiaRkfEK3GQcpb7C/uyF1Q= cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +cloud.google.com/go/iam v1.1.6 h1:bEa06k05IO4f4uJonbB5iAgKTPpABy1ayxaIZV/GHVc= +cloud.google.com/go/iam v1.1.6/go.mod h1:O0zxdPeGBoFdWW3HWmBxJsk0pfvNM/p/qa82rWOGTwI= +cloud.google.com/go/longrunning v0.5.5 h1:GOE6pZFdSrTb4KAiKnXsJBtlE6mEyaW44oKyMILWnOg= +cloud.google.com/go/longrunning v0.5.5/go.mod h1:WV2LAxD8/rg5Z1cNW6FJ/ZpX4E4VnDnoTk0yawPBB7s= +cloud.google.com/go/securitycenter v1.28.0 h1:NpEJeFbm3ad3ibpbpIBKXJS7eQq1cZhtt9nrDTMO/QQ= +cloud.google.com/go/securitycenter v1.28.0/go.mod h1:kmS8vAIwPbCIg7dDuiVKF/OTizYfuWe5f0IIW6NihN8= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= @@ -69,6 +77,8 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 h1:4Pp6oUg3+e/6M4C0A/3kJ2VYa++dsWVTtGgLVj5xtHg= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= @@ -111,6 +121,8 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -125,8 +137,9 @@ google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoA google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= -google.golang.org/genproto/googleapis/api v0.0.0-20240311132316-a219d84964c2 h1:rIo7ocm2roD9DcFIX67Ym8icoGCKSARAiPljFhh5suQ= -google.golang.org/genproto/googleapis/api v0.0.0-20240311132316-a219d84964c2/go.mod h1:O1cOfN1Cy6QEYr7VxtjOyP5AdAuR0aJ/MYZaaof623Y= +google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= +google.golang.org/genproto/googleapis/api v0.0.0-20240314234333-6e1732d8331c h1:kaI7oewGK5YnVwj+Y+EJBO/YN1ht8iTL9XkFHtVZLsc= +google.golang.org/genproto/googleapis/api v0.0.0-20240314234333-6e1732d8331c/go.mod h1:VQW3tUculP/D4B+xVCo+VgSq8As6wA9ZjHl//pmk+6s= google.golang.org/genproto/googleapis/rpc v0.0.0-20240429193739-8cf5692501f6 h1:DujSIu+2tC9Ht0aPNA7jgj23Iq8Ewi5sgkQ++wdvonE= google.golang.org/genproto/googleapis/rpc v0.0.0-20240429193739-8cf5692501f6/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= diff --git a/modules/project_cleanup/function_source/main.go b/modules/project_cleanup/function_source/main.go index 52e9837..6d312d4 100644 --- a/modules/project_cleanup/function_source/main.go +++ b/modules/project_cleanup/function_source/main.go @@ -27,6 +27,8 @@ import ( "strings" "time" + securitycenter "cloud.google.com/go/securitycenter/apiv1" + "cloud.google.com/go/securitycenter/apiv1/securitycenterpb" "golang.org/x/net/context" "golang.org/x/oauth2/google" "google.golang.org/api/cloudresourcemanager/v1" @@ -34,6 +36,7 @@ import ( cloudresourcemanager3 "google.golang.org/api/cloudresourcemanager/v3" "google.golang.org/api/compute/v1" "google.golang.org/api/googleapi" + "google.golang.org/api/iterator" "google.golang.org/api/option" "google.golang.org/api/servicemanagement/v1" ) @@ -43,12 +46,15 @@ const ( TargetExcludedLabels = "TARGET_EXCLUDED_LABELS" TargetIncludedLabels = "TARGET_INCLUDED_LABELS" CleanUpTagKeys = "CLEAN_UP_TAG_KEYS" + CleanUpSCCNotfi = "CLEAN_UP_SCC_NOTIFICATIONS" TargetExcludedTagKeys = "TARGET_EXCLUDED_TAGKEYS" + TargetIncludedSCCNotfis = "TARGET_INCLUDED_SCC_NOTIFICATIONS" TargetFolderId = "TARGET_FOLDER_ID" TargetOrganizationId = "TARGET_ORGANIZATION_ID" MaxProjectAgeHours = "MAX_PROJECT_AGE_HOURS" targetFolderRegexp = `^[0-9]+$` targetOrganizationRegexp = `^[0-9]+$` + SCCNotificationsPageSize = "SCC_NOTIFICATIONS_PAGE_SIZE" ) var ( @@ -56,10 +62,13 @@ var ( excludedLabelsMap = getLabelsMapFromEnv(TargetExcludedLabels) includedLabelsMap = getLabelsMapFromEnv(TargetIncludedLabels) cleanUpTagKeys = getCleanUpTagKeysOrTerminateExecution() + cleanUpSCCNotfi = getCleanUpSCCNotfiOrTerminateExecution() excludedTagKeysList = getTagKeysListFromEnv(TargetExcludedTagKeys) + includedSCCNotfisList = getSCCNotfiListFromEnv(TargetIncludedSCCNotfis) resourceCreationCutoff = getOldTime(int64(getCorrectMaxAgeInHoursOrTerminateExecution()) * 60 * 60) rootFolderId = getCorrectFolderIdOrTerminateExecution() organizationId = getCorrectOrganizationIdOrTerminateExecution() + sccPageSize = getSCCNotificationPageSizeOrTerminateExecution() ) type PubSubMessage struct { @@ -163,6 +172,18 @@ func checkIfAtLeastOneLabelPresentIfAny(project *cloudresourcemanager.Project, l return result } +func checkIfSCCNotificationNameIncluded(notificationName string, includedSCCNotfis []*regexp.Regexp) bool { + if len(includedSCCNotfis) == 0 { + return false + } + for _, name := range includedSCCNotfis { + if name.MatchString(notificationName) { + return true + } + } + return false +} + func checkIfTagKeyShortNameExcluded(shortName string, excludedTagKeys []string) bool { if len(excludedTagKeys) == 0 { return false @@ -194,6 +215,36 @@ func getLabelsMapFromEnv(envVariableName string) map[string]string { return labels } +func getSCCNotfiListFromEnv(envVariableName string) []*regexp.Regexp { + var compiledRegEx []*regexp.Regexp + targetExcludedSCCNotfis := os.Getenv(envVariableName) + logger.Println("Try to get SCC Notifications list") + if targetExcludedSCCNotfis == "" { + logger.Printf("No SCC Notifications provided.") + return compiledRegEx + } + + var sccNotfis []string + err := json.Unmarshal([]byte(targetExcludedSCCNotfis), &sccNotfis) + if err != nil { + logger.Printf("Failed to get SCC Notifications list from [%s] env variable, error [%s]", envVariableName, err.Error()) + return compiledRegEx + } else { + logger.Printf("Got SCC Notifications list [%s] from [%s] env variable", sccNotfis, envVariableName) + } + + //build Regexes + for _, r := range sccNotfis { + result, err := regexp.Compile(r) + if err != nil { + logger.Printf("Invalid regular expression [%s] for SCC Notification", r) + } else { + compiledRegEx = append(compiledRegEx, result) + } + } + return compiledRegEx +} + func getTagKeysListFromEnv(envVariableName string) []string { targetExcludedTagKeys := os.Getenv(envVariableName) logger.Println("Try to get Tag Keys list") @@ -224,6 +275,27 @@ func getCleanUpTagKeysOrTerminateExecution() bool { return result } +func getCleanUpSCCNotfiOrTerminateExecution() bool { + cleanUpSCCNotfiVal, exists := os.LookupEnv(CleanUpSCCNotfi) + if !exists { + logger.Fatalf("Clean up SCC notifications environment variable [%s] not set, set the environment variable and try again.", CleanUpSCCNotfi) + } + result, err := strconv.ParseBool(cleanUpSCCNotfiVal) + if err != nil { + logger.Fatalf("Invalid Clean up SCC notifications value [%s], specify correct value for environment variable [%s] and try again.", cleanUpSCCNotfiVal, CleanUpSCCNotfi) + } + return result +} + +func getSCCNotificationPageSizeOrTerminateExecution() int32 { + pageSize := os.Getenv(SCCNotificationsPageSize) + size, err := strconv.ParseInt(pageSize, 10, 32) + if err != nil { + logger.Fatalf("Invalid page size [%s], specify correct value and try again.", pageSize) + } + return int32(size) +} + func getCorrectFolderIdOrTerminateExecution() string { targetFolderIdString := os.Getenv(TargetFolderId) matched, err := regexp.MatchString(targetFolderRegexp, targetFolderIdString) @@ -290,6 +362,16 @@ func getTagValuesServiceOrTerminateExecution(ctx context.Context, client *http.C return cloudResourceManagerService.TagValues } +func getSCCNotificationServiceOrTerminateExecution(ctx context.Context, client *http.Client) *securitycenter.Client { + logger.Println("Try to get SCC Notification Service") + securitycenterClient, err := securitycenter.NewClient(ctx) + if err != nil { + logger.Fatalf("Failed to get SCC Notification Service with error [%s], terminate execution", err.Error()) + } + logger.Println("Got SCC Notification Service") + return securitycenterClient +} + func getFirewallPoliciesServiceOrTerminateExecution(ctx context.Context, client *http.Client) *compute.FirewallPoliciesService { logger.Println("Try to get Firewall Policies Service") computeService, err := compute.NewService(ctx, option.WithHTTPClient(client)) @@ -315,6 +397,7 @@ func invoke(ctx context.Context) { cloudResourceManagerService := getResourceManagerServiceOrTerminateExecution(ctx, client) folderService := getFolderServiceOrTerminateExecution(ctx, client) tagKeyService := getTagKeysServiceOrTerminateExecution(ctx, client) + sccService := getSCCNotificationServiceOrTerminateExecution(ctx, client) tagValuesService := getTagValuesServiceOrTerminateExecution(ctx, client) firewallPoliciesService := getFirewallPoliciesServiceOrTerminateExecution(ctx, client) endpointService := getServiceManagementServiceOrTerminateExecution(ctx, client) @@ -338,6 +421,49 @@ func invoke(ctx context.Context) { return tagKeyCreatedAt.Before(resourceCreationCutoff) } + projectDeleteRequestedFilter := func(projectID string) bool { + p, err := cloudResourceManagerService.Projects.Get(projectID).Context(ctx).Do() + if err != nil { + logger.Printf("Failed to get project [%s], error [%s]", projectID, err.Error()) + return false + } + if p.LifecycleState == "DELETE_REQUESTED" { + return true + } + return false + } + + removeSCCNotifications := func(organization string) { + logger.Printf("Try to remove SCC Notifications from organization [%s]", organization) + req := &securitycenterpb.ListNotificationConfigsRequest{ + Parent: fmt.Sprintf("organizations/%s", organization), + PageSize: sccPageSize, + } + it := sccService.ListNotificationConfigs(ctx, req) + for { + resp, err := it.Next() + if err == iterator.Done { + break + } + if err != nil { + logger.Printf("failed to list SCC notifications, error [%s]", err.Error()) + break + } + projectID := strings.Split(resp.PubsubTopic, "/")[1] + if checkIfSCCNotificationNameIncluded(resp.Name, includedSCCNotfisList) && projectDeleteRequestedFilter(projectID) { + delReq := &securitycenterpb.DeleteNotificationConfigRequest{ + Name: resp.Name, + } + err = sccService.DeleteNotificationConfig(ctx, delReq) + if err != nil { + logger.Printf("failed to delete SCC notification [%s], error [%s]", resp.Name, err.Error()) + } else { + logger.Printf("SCC notification [%s] deleted", resp.Name) + } + } + } + } + removeTagValues := func(tagKey string) { logger.Printf("Try to remove Tag Values from TagKey [%s]", tagKey) tagValuesList, err := tagValuesService.List().Parent(tagKey).Context(ctx).Do() @@ -518,6 +644,11 @@ func invoke(ctx context.Context) { if cleanUpTagKeys { removeTagKeys(organizationId) } + + // only delete Security Command Center notifications from deleted projects + if cleanUpSCCNotfi { + removeSCCNotifications(organizationId) + } } func CleanUpProjects(ctx context.Context, m PubSubMessage) error { diff --git a/modules/project_cleanup/main.tf b/modules/project_cleanup/main.tf index fb188f3..654cdcb 100644 --- a/modules/project_cleanup/main.tf +++ b/modules/project_cleanup/main.tf @@ -33,7 +33,8 @@ resource "google_organization_iam_member" "main" { "roles/compute.orgSecurityResourceAdmin", "roles/compute.orgSecurityPolicyAdmin", "roles/resourcemanager.tagAdmin", - "roles/viewer" + "roles/viewer", + "roles/securitycenter.notificationConfigEditor" ]) member = "serviceAccount:${google_service_account.project_cleaner_function.email}" @@ -58,12 +59,15 @@ module "scheduled_project_cleaner" { function_timeout_s = var.function_timeout_s function_environment_variables = { - TARGET_ORGANIZATION_ID = var.organization_id - TARGET_FOLDER_ID = var.target_folder_id - TARGET_EXCLUDED_LABELS = jsonencode(var.target_excluded_labels) - TARGET_INCLUDED_LABELS = jsonencode(local.target_included_labels) - MAX_PROJECT_AGE_HOURS = var.max_project_age_in_hours - CLEAN_UP_TAG_KEYS = var.clean_up_org_level_tag_keys - TARGET_EXCLUDED_TAGKEYS = jsonencode(var.target_excluded_tagkeys) + TARGET_ORGANIZATION_ID = var.organization_id + TARGET_FOLDER_ID = var.target_folder_id + TARGET_EXCLUDED_LABELS = jsonencode(var.target_excluded_labels) + TARGET_INCLUDED_LABELS = jsonencode(local.target_included_labels) + MAX_PROJECT_AGE_HOURS = var.max_project_age_in_hours + CLEAN_UP_TAG_KEYS = var.clean_up_org_level_tag_keys + TARGET_EXCLUDED_TAGKEYS = jsonencode(var.target_excluded_tagkeys) + CLEAN_UP_SCC_NOTIFICATIONS = var.clean_up_org_level_scc_notifications + TARGET_INCLUDED_SCC_NOTIFICATIONS = jsonencode(var.target_included_scc_notifications) + SCC_NOTIFICATIONS_PAGE_SIZE = var.list_scc_notifications_page_size } } diff --git a/modules/project_cleanup/variables.tf b/modules/project_cleanup/variables.tf index 4b8efdd..34720c9 100644 --- a/modules/project_cleanup/variables.tf +++ b/modules/project_cleanup/variables.tf @@ -77,6 +77,24 @@ variable "target_included_labels" { default = {} } +variable "clean_up_org_level_scc_notifications" { + type = bool + description = "Clean up organization level Security Command Center notifications." + default = false +} + +variable "target_included_scc_notifications" { + type = list(string) + description = "List of organization Security Command Center notifications names regex that will be deleted. Regex example: `.*/notificationConfigs/scc-notify-.*` " + default = [] +} + +variable "list_scc_notifications_page_size" { + type = number + description = "The maximum number of notification configs to return in the call to `ListNotificationConfigs` service. The minimun value is 1 and the maximum value is 1000." + default = 500 +} + variable "clean_up_org_level_tag_keys" { type = bool description = "Clean up organization level Tag Keys."