/
setup-principal-account.sh
executable file
·220 lines (204 loc) · 8.81 KB
/
setup-principal-account.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
#!/bin/bash
# exit when any command fails
set -e
helpFunction()
{
echo "Enrolls a Principal (end user or service account) in a project with the provided roles attached."
echo ""
echo "Arguments:"
echo " -g [Required] Google Account of an end user. Mutually exclusive with -s."
echo " -s [Required] Service Account name or email. Mutually exclusive with -g."
echo " -p [Required] Short project name (ID) to which the principal will be enrolled."
echo " -r Roles (basic or predefined) to be attached to the principal in the project, splitted by comma."
echo " -f Path to a file containing the roles (basic or predefined) to be attached to the principal in the project."
echo " -c Path to a YAML file containing the custom role to be attached to the principal in the project. Requires -i."
echo " -i ID to be set to the custom role provided in -c."
echo " -k Path to the file where the service account key will be stored. Default: ./key.json."
exit
}
while getopts g:s:p:r:f:c:i:k:h flag
do
case "${flag}" in
g) google_account=${OPTARG};;
s) service_account=${OPTARG};;
p) project_id=${OPTARG};;
r) roles=${OPTARG};;
f) roles_file=${OPTARG};;
c) custom_role_file=${OPTARG};;
i) custom_role_id=${OPTARG};;
k) key_path=${OPTARG};;
h) helpFunction ;;
? ) helpFunction ;; # Print helpFunction in case parameter is non-existent.
esac
done
white='\e[1;37m'
green='\e[1;32m'
red='\e[0;31m'
#Argument check
#Missing arguments
if [ -z "$google_account" ] && [ -z "$service_account" ] || [ -z "$project_id" ];
then
echo -e "${red}Error: Missing parameters, -g or -s (mutually exclusive) and -p flags are mandatory." >&2
echo -e "${red}Use -h flag to display help." >&2
echo -ne "${white}"
exit 2
fi
#Only google_account or service_account allowed
if [ -n "$google_account" ] && [ -n "$service_account" ];
then
echo -e "${red}Error: Parameters -g or -s are mutually exclusive." >&2
echo -e "${red}Use -h flag to display help." >&2
echo -ne "${white}"
exit 2
fi
if { [ "$custom_role_file" ] && [ -z "$custom_role_id" ]; } || { [ -z "$custom_role_file" ] && [ "$custom_role_id" ]; };
then
echo -e "${red}Error: -c and -i parameters must be used together." >&2
echo -e "${red}Use -h flag to display help." >&2
echo -ne "${white}"
exit 2
fi
#Check if GCP CLI is installed
if ! [ -x "$(command -v gcloud)" ];
then
echo -e "${red}Error: GCP CLI is not installed." >&2
echo -ne "${white}"
exit 127
fi
#Check if the provided project_id exists and in that case set it as working project
echo -e "${white}Checking provided project $project_id..."
if ! gcloud projects describe "$project_id" &> /dev/null;
then
echo -e "${red}Error: The provided project ID does not exist. Please, create it first." >&2
echo -ne "${white}"
exit 2
else
echo -e "${white}Setting current project to $project_id..."
if ! gcloud config set project "$project_id" &> /dev/null;
then
echo -e "${red}Error: Could not set current project to $project_id." >&2
echo -ne "${white}"
exit 2
else
echo -e "${green}Current project set to $project_id." >&2
echo -ne "${white}"
fi
fi
if [ -n "$service_account" ];
then
#Retrieve the list of service accounts available for the current project
service_accounts=$(gcloud projects get-iam-policy "$project_id" --format='flattened' | grep members | grep serviceAccount: | cut -d ':' -f 3-)
service_accounts_array=($service_accounts)
#Check the type of the service account (user-managed service account or other)
if [[ "$service_account" =~ .*"@".* ]]; #Non user-managed service account
then
echo -e "${white}Checking if service account $service_account already exists..."
if [[ ! " ${service_accounts_array[*]} " =~ " ${service_account} " ]]; # Searches right literal in left array. More info: https://stackoverflow.com/a/15394738
then
echo -e "${red}Error: Service account $service_account. does not exist" >&2
echo -ne "${white}"
exit 2
fi
else #User-managed service account
service_account_email="$service_account@$project_id.iam.gserviceaccount.com"
echo -e "${white}Checking if service account $service_account already exists..."
if [[ ! " ${service_accounts_array[*]} " =~ " $service_account_email " ]]; # Searches right literal in left array. More info: https://stackoverflow.com/a/15394738
then
echo -e "${white}Creating new service account: $service_account_email..."
if ! gcloud iam service-accounts create "$service_account" --display-name="$service_account" &> /dev/null;
then
echo -e "${red}Error: Cannot create service account with display name $service_account." >&2
echo -ne "${white}"
exit 2
else
echo -e "${green}Service account $service_account created successfully."
echo -ne "${white}"
fi
else
echo -e "${white}The service account $service_account exists already. Proceeding to use it."
fi
echo -e "${white}Creating service-account keys for service account $service_account..."
key_path="${key_path:-./key.json}"
if ! gcloud iam service-accounts keys create "${key_path}" --iam-account="$service_account_email" &> /dev/null;
then
echo -e "${white}Error: Service account key could not be created." >&2
echo -ne "${white}"
exit 2
else
echo -e "${green}Service account key creation ended successfully."
echo -ne "${white}"
fi
fi
fi
#Set member value depending on the use of a google account of a service account
if [ -n "$google_account" ]
then
memberValue="user:$google_account"
elif [ -n "$service_account" ]
then
if [ -n "$service_account_email" ];
then
memberValue="serviceAccount:$service_account_email"
else
memberValue="serviceAccount:$service_account"
fi
fi
#Attach roles to principal in project (From command line)
if [ -n "$roles" ];
then
echo -e "${white}Attaching provided roles to principal in project $project_id..."
IFS=',' read -ra roles_array <<< "$roles"
for role_to_check in "${roles_array[@]}"; do
if ! gcloud projects add-iam-policy-binding "$project_id" --member="$memberValue" --role="$role_to_check" &> /dev/null;
then
echo -e "${red}Error: Attaching role $role_to_check to $memberValue for project $project_id." >&2
echo -ne "${white}"
exit 2
else
echo -e "${green}Attached role $role_to_check to $memberValue in project $project_id."
echo -ne "${white}"
fi
done
fi
#Attach roles to principal in project (From file)
if [ -n "$roles_file" ];
then
echo "Attaching provided roles in file $roles_file to principal in project $project_id..."
IFS=$'\r\n' GLOBIGNORE='*' command eval 'roles_file_array=($(cat ${roles_file}))'
for role_to_check in "${roles_file_array[@]}"
do
if ! gcloud projects add-iam-policy-binding "$project_id" --member="$memberValue" --role="$role_to_check" &> /dev/null;
then
echo -e "${red}Error: Attaching role $role_to_check to $memberValue in project $project_id." >&2
echo -ne "${white}"
exit 2
else
echo -e "${green}Attached role $role_to_check to $memberValue in project $project_id."
echo -ne "${white}"
fi
done
fi
#Create and attach custom role to principal in project (From YAML file)
if [ -n "$custom_role_file" ];
then
echo -e "${white}Creating role $custom_role_id defined in $custom_role_file for project $project_id..."
if ! gcloud iam roles create "$custom_role_id" --project="$project_id" --file="$custom_role_file" &> /dev/null;
then
echo -e "${red}Error: Creating custom role $custom_role_id for project $project_id." >&2
echo -ne "${white}"
exit 2
else
echo -e "${green}Created custom role $custom_role_id for project $project_id successfully."
echo -ne "${white}"
fi
echo -e "${white}Binding role $custom_role_id to principal $memberValue in project $project_id..."
if ! gcloud projects add-iam-policy-binding "$project_id" --member="$memberValue" --role=projects/"$project_id"/roles/"$custom_role_id" &> /dev/null;
then
echo -e "${red}Error: Attaching custom role $custom_role_id to $memberValue in project $project_id." >&2
echo -ne "${white}"
exit 2
else
echo -e "${green}Attached custom role $custom_role_id to $memberValue in project $project_id successfully."
echo -ne "${white}"
fi
fi