Created
May 9, 2023 12:43
-
-
Save aasanchez/af8f2e1cf4cb4c560f1009ed8b2aa647 to your computer and use it in GitHub Desktop.
OIDC Gitlab
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
export NORMAL='\033[0m' | |
export RED='\033[1;31m' | |
export GREEN='\033[1;32m' | |
export YELLOW='\033[1;33m' | |
export WHITE='\033[1;37m' | |
export BLUE='\033[1;34m' | |
DEBUG='true' | |
LOGFILE=/tmp/bash.log | |
logMessage() { | |
scriptname=$(basename "$0") | |
if [ ! -f "$LOGFILE" ]; then touch "$LOGFILE"; fi | |
echo "$(date +"%D %T") $scriptname : $*" >> $LOGFILE | |
} | |
message() { | |
message="$*" | |
echo -e "$message" >&2; | |
logMessage "$message" | |
} | |
info() { | |
message="$*" | |
if [ "$VERBOSE" == "true" ]; then | |
printf "$GREEN" | |
printf "%s\n" "$message" >&2; | |
tput sgr0 # Reset to normal. | |
echo -e `printf "$NORMAL"` | |
fi | |
logMessage $message | |
} | |
warning() { | |
message="$*" | |
if [ "$VERBOSE" == "true" ]; then | |
printf "$YELLOW" | |
printf "%s\n" "$message" >&2; | |
tput sgr0 # Reset to normal. | |
printf "$NORMAL" | |
fi | |
logMessage "WARN: $message" | |
} | |
debug() { | |
message="$*" | |
if [ "$DEBUG" == "true" ]; then | |
printf "$BLUE" | |
printf "%s\n" "$message" >&2; | |
tput sgr0 # Reset to normal. | |
printf "$NORMAL" | |
fi | |
logMessage "DEBUG: $message" | |
} | |
error() { | |
message="$*" | |
scriptname=$(basename $0) | |
printf "$RED" | |
printf "%s\n" "$scriptname $message" >&2; | |
tput sgr0 # Reset to normal. | |
printf "$NORMAL" | |
logMessage "ERROR: $message" | |
return 1 | |
} | |
debug_var(){ | |
if [ "$DEBUG" == "true" ]; then | |
echo -e "$BLUE $1: $YELLOW${!1} $NORMAL" | |
fi | |
logMessage "DEBUG: "$1: ${!1}"" | |
} | |
debug_json(){ | |
if [ "$DEBUG" == "true" ]; then | |
echo -e "$BLUE $1: $NORMAL" | |
echo ${!1} | jq . | |
fi | |
logMessage "DEBUG: $1: "${!1} | |
} | |
REVIEW_ACCOUNT=452115038936 # DEVELOPMENT AND MERGE REQUEST | |
INTEGRATION_ACCOUNT=452115038936 # INTEGRATION, ACCEPTANCE | |
STAGING_ACCOUNT=452115038936 # Demo, training, stagging | |
PRODUCTION_ACCOUNT=452115038936 | |
if ! IDENTITY=$(aws sts get-caller-identity 2>/dev/null); then | |
error "Error: There is no valid connection with AWS CLI" | |
exit 1 | |
fi | |
CURRENT_ACCOUNT=$(echo "$IDENTITY" | jq -r .Account) | |
debug_var "CURRENT_ACCOUNT" | |
info "Selecting the Envoriment Variables base on AWS Account" | |
if [ "$CURRENT_ACCOUNT" = "$REVIEW_ACCOUNT" ]; then | |
ENV="DEV" | |
REF_TYPE="branch:ref:*" | |
POLICY_ENV="POLICY_DOCUMENT_DEV" | |
elif [ "$CURRENT_ACCOUNT" = "$INTEGRATION_ACCOUNT" ]; then | |
ENV="INT" | |
REF_TYPE="branch:ref:*" | |
POLICY_ENV="POLICY_DOCUMENT_DEV" | |
elif [ "$CURRENT_ACCOUNT" = "$STAGING_ACCOUNT" ]; then | |
ENV="STG" | |
REF_TYPE="branch:ref:*" | |
POLICY_ENV="POLICY_DOCUMENT_DEV" | |
elif [ "$CURRENT_ACCOUNT" = "$PRODUCTION_ACCOUNT" ]; then | |
ENV="PRD" | |
REF_TYPE="branch:ref:*" | |
POLICY_ENV="POLICY_DOCUMENT_PRD" | |
else | |
exit 0 | |
fi | |
debug_var "ENV" | |
debug_var "REF_TYPE" | |
debug_var "POLICY_ENV" | |
IAM_IDENTITY_PROVIDER_GITLAB_ARN=$(aws iam list-open-id-connect-providers | jq -r '.OpenIDConnectProviderList[] | select(.Arn | contains("gitlab")) | .Arn') | |
debug_var "IAM_IDENTITY_PROVIDER_GITLAB_ARN" | |
if [ -z $IAM_IDENTITY_PROVIDER_GITLAB_ARN ]; then | |
error "Gitlab was not found as Identity Provider" | |
exit 0 | |
fi | |
PROJECT=$(git remote get-url origin | cut -c 16- | sed 's/\.git$//') | |
PROJECT_SLUG=$(echo $PROJECT | tr '/' '-') | |
debug_var "PROJECT" | |
debug_var "PROJECT_SLUG" | |
POLICY_NAME=$(echo $PROJECT_SLUG@$ENV-policy) | |
POLICY_ARN=$(echo arn:aws:iam::$CURRENT_ACCOUNT:policy/$POLICY_NAME) | |
debug_var "POLICY_NAME" | |
debug_var "POLICY_ARN" | |
POLICY_DOCUMENT_DEV=$(echo '{ | |
"Version":"2012-10-17", | |
"Statement":[ | |
{ | |
"Effect":"Allow", | |
"Action":"*", | |
"Resource":"*" | |
} | |
] | |
}' | jq .) | |
POLICY_DOCUMENT_PRD=$(echo '{ | |
"Version":"2012-10-17", | |
"Statement":[ | |
{ | |
"Effect":"Allow", | |
"Action":"*", | |
"Resource":"*" | |
} | |
] | |
}' | jq .) | |
POLICY_DOCUMENT="${!POLICY_ENV}" | |
debug_json "POLICY_DOCUMENT" | |
TAGS=$(echo '[ | |
{ | |
"Key": "Environment", | |
"Value": "'"$ENV"'" | |
}, | |
{ | |
"Key": "Project", | |
"Value": "'"$PROJECT"'" | |
} | |
]' | jq .) | |
debug_json "TAGS" | |
if ! aws iam get-policy --policy-arn "$POLICY_ARN" > /dev/null 2>&1; then | |
info "Creating policy" | |
aws iam create-policy --policy-name "$POLICY_NAME" --policy-document "$POLICY_DOCUMENT" --tags "$TAGS" | jq . | |
fi | |
# # Get the document because the previous command do not return the policy document | |
DOCUMENT_VERSION=$(aws iam get-policy --policy-arn "$POLICY_ARN" | jq -r .Policy.DefaultVersionId) | |
CURRENT_POLICY_DOCUMENT=$(aws iam get-policy-version --policy-arn "$POLICY_ARN" --version-id "$DOCUMENT_VERSION" | jq .PolicyVersion.Document ) | |
debug_var "DOCUMENT_VERSION" | |
debug_json "CURRENT_POLICY_DOCUMENT" | |
if ! diff <(echo "$POLICY_DOCUMENT" | jq .) <(echo "$CURRENT_POLICY_DOCUMENT" | jq .) >/dev/null; then | |
debug "Try to update the policy" | |
MAX_VERSIONS=5 | |
VERSIONS=$(aws iam list-policy-versions --policy-arn "$POLICY_ARN" | jq '.Versions | sort_by(.CreateDate)') | |
NUM_VERSIONS=$(echo "$VERSIONS" | jq length) | |
if [ "$NUM_VERSIONS" -ge "$MAX_VERSIONS" ]; then | |
TO_DELETE=$(echo "$VERSIONS" | jq -r '.[0].VersionId') | |
warning "Deleted oldest policy version: $TO_DELETE" | |
aws iam delete-policy-version --policy-arn "$POLICY_ARN" --version-id "$TO_DELETE" | |
fi | |
debug "Create a new policy version" | |
aws iam create-policy-version --policy-arn "$POLICY_ARN" --policy-document "$POLICY_DOCUMENT" --set-as-default | jq . | |
fi | |
TRUST_POLICY_DOCUMENT=$(echo '{ | |
"Version": "2012-10-17", | |
"Statement": [ | |
{ | |
"Effect": "Allow", | |
"Principal": { | |
"Federated": "arn:aws:iam::'"$CURRENT_ACCOUNT"':oidc-provider/gitlab.com" | |
}, | |
"Action": "sts:AssumeRoleWithWebIdentity", | |
"Condition": { | |
"StringEquals": { | |
"gitlab.com:aud": "https://gitlab.com" | |
}, | |
"StringLike": { | |
"gitlab.com:sub": "project_path:'"$PROJECT"':ref_type:'"$REF_TYPE"'" | |
} | |
} | |
} | |
] | |
}') | |
if ! aws iam get-role --role-name "$PROJECT_SLUG@$ENV" >/dev/null 2>&1; then | |
ARN=$(aws iam create-role --role-name "$PROJECT_SLUG@$ENV" --assume-role-policy-document "$TRUST_POLICY_DOCUMENT" | jq -r .Role.Arn) | |
debug "Role $PROJECT_SLUG@$ENV Created, ARN=$ARN" | |
fi | |
# Get the current trust policy of the role | |
CURRENT_TRUST_POLICY=$(aws iam get-role --role-name "$PROJECT_SLUG@$ENV" --query Role.AssumeRolePolicyDocument | jq .) | |
# Compare the current trust policy with the one stored in the variable | |
if [[ "$CURRENT_TRUST_POLICY" != "$TRUST_POLICY_DOCUMENT" ]]; then | |
debug "Update the trust policy of the role" | |
warning "The trust policy of the role \"$PROJECT_SLUG@$ENV\" is different and needs to be updated." | |
aws iam update-assume-role-policy --role-name "$PROJECT_SLUG@$ENV" --policy-document "$TRUST_POLICY_DOCUMENT" | |
fi | |
if ! aws iam list-attached-role-policies --role-name "$PROJECT_SLUG@$ENV" | grep -q "$POLICY_ARN"; then | |
debug "Attach policy if it is not already attached" | |
aws iam attach-role-policy --role-name "$PROJECT_SLUG@$ENV" --policy-arn "$POLICY_ARN" | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment