Skip to content

Commit 24dce9b

Browse files
feat(modular): add TF snippets for enable GCP APIs (#38)
* feat(modular): add TF snippets for enable GCP APIs * feat(modular): add TF snippets for enable GCP APIs * feat(modular): add TF snippets for enable GCP APIs
1 parent 61d4ccf commit 24dce9b

File tree

7 files changed

+539
-0
lines changed

7 files changed

+539
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ override.tf.json
2929
.envrc
3030
**/.envrc
3131

32+
/test/examples/**/**/*.json
33+
3234
*.patch
3335

3436
# MacOS
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
/*
2+
This terraform file is intended to enable the GCP APIs needed for CDR/CIEM feature within a GCP organization onboarding.
3+
It will create a google_project_service resource per each service enabled within each GCP project.
4+
The APIs needed for the CDR/CIEM feature are listed below:
5+
- Cloud Pub/Sub API
6+
7+
* Note: This do not overwrite any other APIs config that your GCP project has, it will only enabled it if isn't yet.
8+
*/
9+
10+
# Set local variables for Organization ID and API services to enable
11+
locals {
12+
organizationID = "933620940614"
13+
services = [
14+
"pubsub.googleapis.com"
15+
]
16+
root_projects = [for project in data.google_projects.organization_projects.projects : project.project_id]
17+
folder_projects = jsondecode(data.local_file.projects_from_folder.content)
18+
all_projects = concat(local.root_projects, local.folder_projects)
19+
project_and_services = flatten([
20+
for project in local.all_projects : [
21+
for service in local.services : {
22+
project = project
23+
service = service
24+
}
25+
]
26+
])
27+
}
28+
29+
# GCP provider
30+
provider "google" {
31+
region = "us-west-1"
32+
}
33+
34+
# Get list of projects under the specified organization
35+
data "google_projects" "organization_projects" {
36+
filter = "parent.type:organization parent.id:${local.organizationID}"
37+
}
38+
39+
data "local_file" "projects_from_folder" {
40+
filename = "project_ids.json"
41+
depends_on = [null_resource.get_projects_from_folders]
42+
}
43+
44+
# Enable API services for GCP project
45+
resource "google_project_service" "enable_cdr_ciem_apis" {
46+
// create a unique key per project and service to enable each API
47+
for_each = { for item in local.project_and_services : "${item.project}-${item.service}" => item }
48+
49+
project = each.value.project
50+
service = each.value.service
51+
disable_on_destroy = false
52+
}
53+
54+
# Output the projects and APIs enabled
55+
output "enabled_projects" {
56+
value = distinct([for resource in google_project_service.enable_cdr_ciem_apis : resource.project])
57+
}
58+
59+
output "enabled_services" {
60+
value = distinct([for service in google_project_service.enable_cdr_ciem_apis : service.service])
61+
}
62+
63+
# Script to get projects from folders recursively and set to a file
64+
resource "null_resource" "get_projects_from_folders" {
65+
provisioner "local-exec" {
66+
command = <<EOF
67+
#!/bin/bash
68+
ORG_ID="933620940614"
69+
70+
# array to store project IDs
71+
declare -a FINAL_PROJECT_IDS
72+
73+
list_projects() {
74+
local folder_id=$1
75+
76+
# get projects from folder
77+
local projects_json=$(gcloud projects list --filter="parent.id=$folder_id AND parent.type=folder" --format=json)
78+
79+
# check valid array
80+
if ! echo "$projects_json" | jq empty >/dev/null 2>&1; then
81+
echo "Invalid JSON returned for projects list."
82+
return
83+
fi
84+
85+
# get project ids
86+
local project_ids=$(echo "$projects_json" | jq -r '.[] | .projectId')
87+
88+
# check project ids not empty and add to global variable
89+
if [ -n "$project_ids" ]; then
90+
for project_id in $project_ids; do
91+
FINAL_PROJECT_IDS+=("$project_id")
92+
done
93+
else
94+
echo "No projects found in folder $folder_id"
95+
fi
96+
}
97+
98+
list_folders_recursive() {
99+
local parent_id=$1
100+
local parent_type=$2
101+
102+
# list folders on org or other folders
103+
if [[ "$parent_type" == "organization" ]]; then
104+
folders=$(gcloud resource-manager folders list --organization=$parent_id --format=json)
105+
elif [[ "$parent_type" == "folder" ]]; then
106+
folders=$(gcloud resource-manager folders list --folder=$parent_id --format=json)
107+
fi
108+
109+
# check if there were folders returned
110+
if [ "$(echo "$folders" | jq length)" -eq 0 ]; then
111+
return
112+
fi
113+
114+
# iterate over folder and call functions recursively
115+
for folder in $(echo "$folders" | jq -c '.[]'); do
116+
folder_id=$(echo "$folder" | jq -r '.name' | awk -F'/' '{print $NF}')
117+
118+
list_projects "$folder_id"
119+
list_folders_recursive "$folder_id" "folder"
120+
done
121+
}
122+
123+
echo "Listing all projects in folders for organization: $ORG_ID"
124+
list_folders_recursive "$ORG_ID" "organization"
125+
printf "%s\n" "$${FINAL_PROJECT_IDS[@]}" | jq -R . | jq -s . > "project_ids.json"
126+
echo "Projects listed and saved to local file."
127+
EOF
128+
}
129+
}
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
/*
2+
This terraform file is intended to enable the GCP APIs needed for CSPM feature within a GCP organization onboarding.
3+
It will create a google_project_service resource per each service enabled within each GCP project.
4+
The APIs needed for the CSPM feature are listed below:
5+
- Security Token Service API
6+
- Cloud Asset API
7+
- Cloud Identity API
8+
- Admin SDK API
9+
In addition, since CSPM is needed for onboard any GCP project these other APIs are also enabled:
10+
- Identity and access management API
11+
- IAM Service Account Credentials API
12+
- Cloud Resource Manager API
13+
14+
* Note: This do not overwrite any other APIs config that your GCP project has, it will only enabled it if isn't yet.
15+
*/
16+
17+
# Set local variables for Organization ID and API services to enable
18+
locals {
19+
organizationID = "933620940614"
20+
services = [
21+
# CSPM specific APIs
22+
"sts.googleapis.com",
23+
"cloudasset.googleapis.com",
24+
"cloudidentity.googleapis.com",
25+
"admin.googleapis.com",
26+
27+
# additional APIs
28+
"iam.googleapis.com",
29+
"iamcredentials.googleapis.com",
30+
"cloudresourcemanager.googleapis.com"
31+
]
32+
root_projects = [for project in data.google_projects.organization_projects.projects : project.project_id]
33+
folder_projects = jsondecode(data.local_file.projects_from_folder.content)
34+
all_projects = concat(local.root_projects, local.folder_projects)
35+
project_and_services = flatten([
36+
for project in local.all_projects : [
37+
for service in local.services : {
38+
project = project
39+
service = service
40+
}
41+
]
42+
])
43+
}
44+
45+
# GCP provider
46+
provider "google" {
47+
region = "us-west-1"
48+
}
49+
50+
# Get list of projects under the specified organization
51+
data "google_projects" "organization_projects" {
52+
filter = "parent.type:organization parent.id:${local.organizationID}"
53+
}
54+
55+
data "local_file" "projects_from_folder" {
56+
filename = "project_ids.json"
57+
depends_on = [null_resource.get_projects_from_folders]
58+
}
59+
60+
# Enable API services for GCP project
61+
resource "google_project_service" "enable_cspm_apis" {
62+
// create a unique key per project and service to enable each API
63+
for_each = { for item in local.project_and_services : "${item.project}-${item.service}" => item }
64+
65+
project = each.value.project
66+
service = each.value.service
67+
disable_on_destroy = false
68+
}
69+
70+
# Output the projects and APIs enabled
71+
output "enabled_projects" {
72+
value = distinct([for resource in google_project_service.enable_cspm_apis : resource.project])
73+
}
74+
75+
output "enabled_services" {
76+
value = distinct([for service in google_project_service.enable_cspm_apis : service.service])
77+
}
78+
79+
# Script to get projects from folders recursively and set to a file
80+
resource "null_resource" "get_projects_from_folders" {
81+
provisioner "local-exec" {
82+
command = <<EOF
83+
#!/bin/bash
84+
ORG_ID="933620940614"
85+
86+
# array to store project IDs
87+
declare -a FINAL_PROJECT_IDS
88+
89+
list_projects() {
90+
local folder_id=$1
91+
92+
# get projects from folder
93+
local projects_json=$(gcloud projects list --filter="parent.id=$folder_id AND parent.type=folder" --format=json)
94+
95+
# check valid array
96+
if ! echo "$projects_json" | jq empty >/dev/null 2>&1; then
97+
echo "Invalid JSON returned for projects list."
98+
return
99+
fi
100+
101+
# get project ids
102+
local project_ids=$(echo "$projects_json" | jq -r '.[] | .projectId')
103+
104+
# check project ids not empty and add to global variable
105+
if [ -n "$project_ids" ]; then
106+
for project_id in $project_ids; do
107+
FINAL_PROJECT_IDS+=("$project_id")
108+
done
109+
else
110+
echo "No projects found in folder $folder_id"
111+
fi
112+
}
113+
114+
list_folders_recursive() {
115+
local parent_id=$1
116+
local parent_type=$2
117+
118+
# list folders on org or other folders
119+
if [[ "$parent_type" == "organization" ]]; then
120+
folders=$(gcloud resource-manager folders list --organization=$parent_id --format=json)
121+
elif [[ "$parent_type" == "folder" ]]; then
122+
folders=$(gcloud resource-manager folders list --folder=$parent_id --format=json)
123+
fi
124+
125+
# check if there were folders returned
126+
if [ "$(echo "$folders" | jq length)" -eq 0 ]; then
127+
return
128+
fi
129+
130+
# iterate over folder and call functions recursively
131+
for folder in $(echo "$folders" | jq -c '.[]'); do
132+
folder_id=$(echo "$folder" | jq -r '.name' | awk -F'/' '{print $NF}')
133+
134+
list_projects "$folder_id"
135+
list_folders_recursive "$folder_id" "folder"
136+
done
137+
}
138+
139+
echo "Listing all projects in folders for organization: $ORG_ID"
140+
list_folders_recursive "$ORG_ID" "organization"
141+
printf "%s\n" "$${FINAL_PROJECT_IDS[@]}" | jq -R . | jq -s . > "project_ids.json"
142+
echo "Projects listed and saved to local file."
143+
EOF
144+
}
145+
}

0 commit comments

Comments
 (0)