-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathstanford-sso.sh
executable file
·285 lines (260 loc) · 8.45 KB
/
stanford-sso.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
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
#!/bin/bash
# Copyright 2015
# The Board of Trustees of the Leland Stanford Junior University
set -e
shopt -s extglob # enables pattern lists like +(...|...)
# Default variables
init() {
# Script name
script=$(basename "${BASH_SOURCE[0]}" .sh)
# Script actions
actionsRegexp='+(create|delete|show)'
# Dryrun flag. Default not run-run.
dryrun=0
# Metadata URL
metadataUrl='https://idp.stanford.edu/metadata.xml'
}
# Create saml provider
create_saml_provider() {
samlMetadata=$(curl -s -k $metadataUrl | tee /tmp/samlMetadata.xml)
if ! [[ "$samlMetadata" =~ "entityID=\"https://" ]];
then
echo "$samlMetadata"
echo "Invalid metadata"
exit 1
else
idpId=${metadataUrl%/metadata.xml}
fi
echo "Creating saml provider $name."
cmd="aws --profile $profile iam create-saml-provider --name=$name --output=text --saml-metadata-document file:///tmp/samlMetadata.xml"
[ $dryrun -eq 0 ] && $cmd || echo $cmd
# If no account alias and not passed as a parameter
if [ -z "$accountAlias" ];
then
accountAlias=$(aws --profile $profile iam list-account-aliases | jq --raw-output '.AccountAliases[]')
userProvidedLabel=0
else
userProvidedLabel=1
fi
if [ -z "$accountAlias" ] || [ $userProvidedLabel -eq 1 ];
then
if [ $userProvidedLabel -eq 1 ];
then
echo "Creating account alias ${accountAlias}"
cmd="aws --profile $profile iam create-account-alias --account-alias ${accountAlias}"
[ $dryrun -eq 0 ] && $cmd || echo $cmd
else
echo "Creating account alias ${script}-${profile}"
cmd="aws --profile $profile iam create-account-alias --account-alias ${script}-${profile}"
[ $dryrun -eq 0 ] && $cmd || echo $cmd
fi
fi
}
# Show SAML provider
show_saml_provider() {
aws --profile $profile iam get-saml-provider --saml-provider-arn=$samlProviderArn
}
# Delete SAML provider
delete_saml_provider() {
echo "Deleting saml provider $name."
cmd="aws --profile $profile iam delete-saml-provider --saml-provider-arn=$samlProviderArn"
[ $dryrun -eq 0 ] && $cmd || echo $cmd
# Also remove alias we created
accountAlias=$(aws --profile $profile iam list-account-aliases | jq --raw-output '.AccountAliases[]')
if [ "$accountAlias" = "${script}-${profile}" ];
then
cmd="aws --profile $profile iam delete-account-alias --account-alias ${script}-${profile}"
[ $dryrun -eq 0 ] && $cmd || echo $cmd
fi
}
# Create role
create_role() {
cat > /tmp/trust-policy.json <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::$accountId:saml-provider/$name"
},
"Action": "sts:AssumeRoleWithSAML",
"Condition": {
"StringEquals": {
"SAML:aud": "https://signin.aws.amazon.com/saml"
}
}
}
]
}
EOF
# Create role and assume idp trust policy
echo "Creating role $roleName"
cmd1="aws --profile $profile iam create-role --role-name $roleName --assume-role-policy-document file:///tmp/trust-policy.json"
# Grant access
cmd2="aws --profile $profile iam attach-role-policy --role-name $roleName --policy-arn $policyArn"
[ $dryrun -eq 0 ] && $cmd1 && $cmd2 || echo $cmd1 && echo $cmd2
}
# Delete role - only delete role created with this script.
delete_role() {
echo "Deleting role $roleName"
cmd1="aws --profile $profile iam detach-role-policy --role-name $roleName --policy-arn=$policyArn"
cmd2="aws --profile $profile iam delete-role --role-name $roleName"
[ $dryrun -eq 0 ] && $cmd1 && $cmd2 || echo $cmd1 && echo $cmd2
}
# Output
print_info() {
if [ $action = 'create' ]; then
echo ""
echo "All done! Next step. Submit the following request to https://helpsu.stanford.edu/helpsu/3.0/auth/helpsu-form?pcat=shibboleth to create idp server setup."
echo ""
echo "When idp server setup is complete, you can login to AWS console SSO through this url:"
echo "$idpId/idp/profile/SAML2/Unsolicited/SSO?providerId=urn:amazon:webservices"
echo ""
elif [ $action = 'delete' ]; then
echo "All done! Next step. Submit the following request to https://helpsu.stanford.edu/helpsu/3.0/auth/helpsu-form?pcat=shibboleth to remove idp server setup."
fi
cat <<EOF
Account number: $accountId
Provider name: arn:aws:iam::$accountId:saml-provider/$name
Role-name: $roleName
Workgroup: $workgroup
EOF
}
# Valid managed policy name
validate_policy() {
policyArn=$(aws --profile $profile iam list-policies | jq --raw-output --arg p "$permission" '.Policies[] | select(.PolicyName == $p).Arn')
if [ -z "$policyArn" ];
then
aws --profile $profile iam list-policies | jq --arg p "$permission" --raw-output '.Policies[].PolicyName' | sort
echo "Valid policies are shown as above."
exit 1
else
if [ -z "$roleName" ];
then
roleName=${permission}-generatedby-${script}
fi
fi
}
# Docs
help(){
echo "stanford-sso -a <action> -c <config> -n <provider name> -p <permission> -w <workgroupname> [-u <metadata url>] [-d] [-h] [-l <account-label>] [-r <role-name>]"
echo ""
echo " -a <create|show|delete>: action. create, show or delete SSO setup by this tool."
echo " -c <aws config>: authenticate using profile defined by configuration."
echo " -n <provider-name>: the name of the idp provider, for example 'stanford-idp'."
echo " -p <ReadOnlyAccess|AdministratorAccess|list-policies>: ReadOnlyAccess, AdministratorAccess, or list other valid AWS managed polices."
echo " -u <url-for-metadata>: optional. metadata url for the idp provider. Default 'https://idp.stanford.edu/metadata.xml'."
echo " -w <workgroupname>: Stanford workgroup name to link into this saml provider setup. e.g. itlab:anchorage-admin"
echo " -l <account-label>: Account label (alias) This will be the name displayed to users when logging in e.g. its-main-account"
echo " -r <role-name>: This defines the name of the role that will be created e.g. ops-readonly"
echo " -a <create|show|delete>: action. create, show or delete SSO setup by this tool."
echo " -d : dryrun. print out the commands"
echo " -h : Help"
}
# Main
# Set default values
init
while getopts "a:c:p:n:u:w:hdl:r:" OPTION
do
case $OPTION in
a)
action=$OPTARG
case $action in
$actionsRegexp)
;;
*)
echo "Unsupported action $action."
exit 1
esac
;;
c)
profile=$OPTARG
;;
p)
permission=$OPTARG
;;
n)
name=$OPTARG
;;
u)
metadataUrl=$OPTARG
if ! [[ "$metadataUrl" =~ "https" ]];
then
echo "metadata url should contain https."
echo "e.g. https://idp.stanford.edu/metadata.xml"
exit 1
fi
;;
w)
workgroup=$OPTARG
;;
l)
accountAlias=$OPTARG
;;
r)
roleName=$OPTARG
;;
d)
dryrun=1
;;
[h?])
help
exit
;;
esac
done
if [[ -z $action || -z $profile || -z $name ]]; then
help
echo "-a, -c, and -n are required."
exit 1
elif [[ $action =~ ^(create|delete)$ && -z $permission && -z $workgroup ]]; then
echo "create or delete requires access permission and workgroup name."
exit 1
fi
echo "Getting AWS account number ..."
accountId=$(aws --profile $profile iam get-user | jq '.User.Arn' | grep -Eo '[[:digit:]]{12}')
if [ -z "$accountId" ]; then
echo "Cannot find AWS account number."
exit 1
fi
# Get saml provider arn
echo "$action $name"
samlProviderArn=$(aws --profile $profile iam list-saml-providers | jq --raw-output ".SAMLProviderList[] | select(.Arn == \"arn:aws:iam::$accountId:saml-provider/$name\") | .Arn")
# Call functions based on action
case $action in
'create')
if [ "$samlProviderArn" == "arn:aws:iam::$accountId:saml-provider/$name" ];
then
show_saml_provider
echo "SAML provider $name is already setup."
exit 0
else
validate_policy && create_saml_provider && create_role
fi
;;
'show')
if [ "$samlProviderArn" != "arn:aws:iam::$accountId:saml-provider/$name" ];
then
echo "SAML provider $name doesn't exist."
exit 1
else
show_saml_provider
fi
;;
'delete')
if [ "$samlProviderArn" != "arn:aws:iam::$accountId:saml-provider/$name" ];
then
echo "SAML provider $name doesn't exist."
exit 1
else
validate_policy && delete_saml_provider && delete_role
fi
;;
esac
[ $dryrun -eq 1 ] && echo "Dryrun mode. Nothing is changed." || print_info
# Cleanup
rm -rf /tmp/trust-policy.json
rm -rf /tmp/samlMetadata.xml
exit 0