Skip to content

Instantly share code, notes, and snippets.

@aasanchez
Created May 9, 2023 12:43
Show Gist options
  • Save aasanchez/af8f2e1cf4cb4c560f1009ed8b2aa647 to your computer and use it in GitHub Desktop.
Save aasanchez/af8f2e1cf4cb4c560f1009ed8b2aa647 to your computer and use it in GitHub Desktop.
OIDC Gitlab
#!/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