Skip to content

Instantly share code, notes, and snippets.

@TJM
Last active January 6, 2023 20:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TJM/028ca421068d518f943685dffc828df4 to your computer and use it in GitHub Desktop.
Save TJM/028ca421068d518f943685dffc828df4 to your computer and use it in GitHub Desktop.
Handle Artifactory License through script
#!/bin/bash
set -e
############################################################################
# shell script for applying license bucket and licenses to an Artifactory #
# deployment. #
# #
# Author: Andrew Milam <andrew.milam@davita.com> #
# #
# WARNING: This script is designed as a terraform shell_script resource! #
# Use otherwise at your own peril! #
# #
# Globals #
# Required: #
# url - artifactory base url #
# workspace - terraform workspace #
# bucket_id - license bucket id, will be in license file name #
# bucket_name - name of the bucket #
# license_key - key used by artifactory to decrypt the license #
# secrets_project_id - project id where secrets are stored #
# admin_password - artifactory admin password #
# license_count - license count to apply from bucket #
# secret_version - version of the secret in google secrets manager #
############################################################################
# required variables
: "${url:?}"
: "${workspace:?}"
: "${bucket_id:?}"
: "${bucket_name:?}"
: "${license_key:?}"
: "${secrets_project_id:?}"
: "${admin_password:?}"
: "${license_count:?}"
: "${secret_version:?}"
user="tf-$workspace-$(date '+%y-%m-%d-%H%M%S')"
file="${bucket_id}.json"
# function that retries other functions x amount of times, x=$1
retry() {
tries=$1
shift
while ! result=$("$@") && [ "$tries" -gt 0 ]; do
tries=$((tries - 1))
if [ "$tries" -le 0 ]; then
echo "Deadline exceeded" >&2
return 1
fi
echo "Retrying in 5 seconds" >&2
sleep 5
done
echo "$result"
}
# get the encrypted license file from google secrets manager
getSecret() {
gcloud secrets versions access "$secret_version" --secret "artifactory-license-file" --project "$secrets_project_id" --format='get(payload.data)' | tr '_-' '/+' | base64 --decode > "$file"
}
# login function
login() {
curl "https://$url/ui/api/v1/ui/auth/login" \
--fail \
--silent \
--show-error \
--location \
--cookie-jar cookiejar \
--header 'Accept: application/json, text/plain, */*' \
--header 'Accept-Encoding: gzip, deflate, br' \
--header 'Content-Type: application/json' \
--header 'X-Requested-With: XMLHttpRequest' \
--data-raw "{\"user\":\"admin\",\"password\":\"$admin_password\",\"type\":\"login\"}"
}
# function to get admin access token
getToken() {
curl "https://$url/ui/api/v1/access/token/scoped?expiry=24&services[]=all&scope=applied-permissions%2Fadmin&username=$user" \
--fail \
--silent \
--show-error \
--location \
-b cookiejar \
--globoff \
--header 'Accept: application/json, text/plain, */*' \
--header 'Accept-Encoding: gzip, deflate, br' \
--header 'X-Requested-With: XMLHttpRequest' \
--header 'Connection: keep-alive'
}
# function to apply enterprise license bucket
applyBucket() {
curl "https://$url/mc/api/v1/buckets" \
--fail \
--silent \
--show-error \
--location \
--header "Authorization: Bearer $1" \
--header 'Content-Type: multipart/form-data' \
--form "file=@./$file;type=application/octet-stream" \
--form "key=$2" \
--form "name=$3"
}
# function to check license count applied to the deployment
checkForLicenses() {
curl "https://$url/mc/api/v1/buckets" --silent --fail --show-error --location --header "Authorization: Bearer $1"
}
# function to check license count applied to the deployment
getLicenseCount() {
curl "https://$url/mc/api/v1/buckets/$bucket_id/report" --silent --fail --show-error --location --header "Authorization: Bearer $1"
}
# function to get the Artifactory deployment ID
getJpd() {
curl "https://$url/mc/api/v1/jpds" \
--fail \
--silent \
--show-error \
--location \
--header "Authorization: Bearer $1" \
--header 'Accept: application/json' | jq -r '.[]?| .id'
}
# function to apply license(s) from the bucket to the Artifactory deployment
applyLicense() {
curl "https://$url/mc/api/v1/buckets/$bucket_id/deploy" \
--fail \
--silent \
--show-error \
--location \
--header "Authorization: Bearer $1" \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data-raw "{\"jpd_id\" : \"$2\",\"license_count\" : \"$3\"}"
}
removeBucket() {
curl -X DELETE "https://$url/mc/api/v1/buckets/$2" \
--silent \
--fail \
--show-error \
--location \
--header "Authorization: Bearer $1"
}
# function to revoke the admin access token
revokeToken() {
# revoke the token when complete
curl -b cookiejar "https://$url/ui/api/v1/ui/admin/security/accesstokens/revokeTokens" \
--fail \
--silent \
--show-error \
--location \
--header 'Accept: application/json, text/plain, */*' \
--header 'Content-Type: application/json' \
--header 'X-Requested-With: XMLHttpRequest' \
--data-raw "[\"$1\"]"
}
main() {
echo "getting license file from google secrets manager"
retry 5 getSecret || {
echo "Failed to get secrets from Google Secrets Manager" >&2
return 1
}
# login to artifactory
echo "logging in"
retry 60 login || {
echo "Failed to login to Artifactory" >&2
return 1
}
# set variable to output from getToken function call
echo "generating artifactory admin access token"
payload=$(retry 60 getToken) || {
echo "Failed to get admin access token" >&2
return 1
}
# set variables from payload for usage and token revokaction
echo "getting token id"
token_id=$(echo "$payload" | jq -r '.token_id') || {
echo "Failed to get access token token_id"
return 1
}
echo "getting access token"
access_token=$(echo "$payload" | jq -r '.access_token') || {
echo "Failed to get access_token"
return 1
}
echo "checking if a bucket is already applied"
bucket_object=$(retry 60 checkForLicenses "$access_token") || {
echo "Failed to check for existing buckets" >&2
return 1
}
# if its present, grabs current bucket from artifactory for comparison potentially new value passed in
current_bucket_id=$(echo "$bucket_object"| jq -r '.[]?| .identifier')
current_bucket_name=$(echo "$bucket_object"| jq -r '.[]?| .name')
# if the current bucket is equal to the value passed in, or if empty
if [[ "$current_bucket_id" == "$bucket_id" ]] || [[ -z "$current_bucket_id" ]];
then
# apply enterprise license bucket to artifactory
echo "applying bucket"
retry 60 applyBucket "$access_token" "$license_key" "$bucket_name" || {
echo "failed to attach bucket" >&2
return 1
}
# checks to see if there are any licenses applied from the bucket to the artifactory deployment
echo "checking for applied licenses"
license=$(retry 60 getLicenseCount "$access_token" | jq -r '.jpds[]?| .license_count') || {
echo "Failed to check number of licenses" >&2
return 1
}
# set default to 0 if null
license_check=${license:="0"} # if null, sets the default to 0
# if the license_check is greater than or equal to the desired desired license_count
if [[ $license_check -ge $license_count ]]; then
echo "license already applied, skipping" >&2
else
# get artifactory deployment
echo "getting the artifactory deployment id"
jpd=$(retry 60 getJpd "$access_token") || {
echo "Failed to retrieve Artifactory JPD" >&2
return 1
}
# increment the license
increment=$((license_count - license_check))
echo "applying $increment licenses from bucket"
retry 60 applyLicense "$access_token" "$jpd" "$increment" || {
echo "Failed to attach license to Aritfactory Deployment" >&2
return 1
}
fi
else
# if the bucket needs to be updated
echo "current bucket is $current_bucket_id"
echo "new bucket id passed in is $bucket_id"
echo "bucket needs to be updated"
# get artifactory deployment
echo "getting the artifactory deployment id"
jpd=$(retry 60 getJpd "$access_token") || {
echo "Failed to retrieve Artifactory JPD" >&2
return 1
}
# apply updated enterprise license bucket to artifactory
echo "applying new bucket $bucket_name"
retry 60 applyBucket "$access_token" "$license_key" "$bucket_name" || {
echo "failed to attach bucket" >&2
return 1
}
# apply licenses from bucket
echo "applying $license_count licenses from bucket to $jpd"
retry 60 applyLicense "$access_token" "$jpd" "$license_count" || {
echo "Failed to attach license to Aritfactory Deployment" >&2
return 1
}
# remove the old bucket
echo "removing previous bucket $current_bucket_name"
retry 60 removeBucket "$access_token" "$current_bucket_name" || {
echo "Failed to remove previous bucket"
return 1
}
fi
# revoke the token
echo "revoking access token"
retry 60 revokeToken "$token_id" || {
echo "Failed to revoke access token" >&2
return 1
}
}
main "$@"
#!/bin/bash
set -e
############################################################################
# shell script for getting an admin access token from Artifactory #
# NOTE: This shell script uses undocumented "UI" API Access #
# #
# Author: Tommy McNeely <Tommy.McNeely@davita.com> #
# #
# WARNING: This script is designed as a test script! #
# Use otherwise at your own peril! #
# #
# Globals (env variables) #
# ARTIFACTORY_URL - artifactory base url #
# ARTIFACTORY_USERNAME - artifactory admin username #
# ARTIFACTORY_PASSWORD - artifactory admin password #
# TOKEN_USERNAME - generated token username $
############################################################################
# defaulted variables
ARTIFACTORY_URL="${ARTIFACTORY_URL:-http://localhost:8082}"
ARTIFACTORY_USERNAME="${ARTIFACTORY_USERNAME:-admin}"
ARTIFACTORY_PASSWORD="${ARTIFACTORY_PASSWORD:-password}"
TOKEN_USERNAME="${user:-admin-$(date '+%Y-%m-%d-%H%M%S')}"
# function that retries other functions x amount of times, x=$1
retry() {
tries=$1
shift
while ! result=$("$@") && [ "$tries" -gt 0 ]; do
tries=$((tries - 1))
if [ "$tries" -le 0 ]; then
echo "Deadline exceeded" >&2
return 1
fi
echo "Retrying in 5 seconds" >&2
sleep 5
done
echo "$result"
}
# login function
login() {
curl "${ARTIFACTORY_URL}/ui/api/v1/ui/auth/login" \
--fail \
--silent \
--show-error \
--location \
--cookie-jar cookiejar \
--header 'Accept: application/json, text/plain, */*' \
--header 'Accept-Encoding: gzip, deflate, br' \
--header 'Content-Type: application/json' \
--header 'X-Requested-With: XMLHttpRequest' \
--data-raw "{\"user\":\"${ARTIFACTORY_USERNAME}\",\"password\":\"${ARTIFACTORY_PASSWORD}\",\"type\":\"login\"}"
}
# function to get admin access token
getToken() {
curl "${ARTIFACTORY_URL}/ui/api/v1/access/token/scoped?expiry=24&services[]=all&scope=applied-permissions%2Fadmin&username=${TOKEN_USERNAME}" \
--fail \
--silent \
--show-error \
--location \
--cookie cookiejar \
--globoff \
--header 'Accept: application/json, text/plain, */*' \
--header 'Accept-Encoding: gzip, deflate, br' \
--header 'X-Requested-With: XMLHttpRequest' \
--header 'Connection: keep-alive'
}
# function to revoke the admin access token
revokeToken() {
# revoke the token when complete
curl "${ARTIFACTORY_URL}/ui/api/v1/ui/admin/security/accesstokens/revokeTokens" \
--fail \
--silent \
--show-error \
--location \
--cookie cookiejar \
--header 'Accept: application/json, text/plain, */*' \
--header 'Content-Type: application/json' \
--header 'X-Requested-With: XMLHttpRequest' \
--data-raw "[\"$1\"]"
}
# login to artifactory
echo "Logging in to Artifactory (${ARTIFACTORY_URL}) as ${ARTIFACTORY_USERNAME} ..." >&2
retry 60 login >&2 || {
echo "Failed to login to Artifactory" >&2
return 1
}
# set variable to output from getToken function call
echo "Generating artifactory admin access token." >&2
payload=$(retry 60 getToken) || {
echo "Failed to get admin access token" >&2
return 1
}
# set variables from payload for usage and token revokaction
# token_id=$(echo "$payload" | jq -r '.token_id') || {
# echo "Failed to get access token token_id" >&2
# return 1
# }
access_token=$(echo "$payload" | jq -r '.access_token') || {
echo "Failed to get access_token" >&2
return 1
}
echo $access_token
# revoke the token
# echo "revoking access token" >&2
# retry 60 revokeToken "$token_id" || {
# echo "Failed to revoke access token" >&2
# return 1
# }
before_script:
# Variables can't do transformations, so this script converts the branch name into a terraform workspace
- export TF_WORKSPACE=$(test "$CI_COMMIT_REF_SLUG" = master && echo default || echo "$CI_COMMIT_REF_SLUG")
- export TF_VAR_bucket=$TF_STATE_BUCKET
- |
set -e
if test -z "$TF_VAR_google_oauth_access_token"; then
TF_VAR_google_oauth_access_token=$(gcloud auth application-default print-access-token)
export TF_VAR_google_oauth_access_token
fi
- | # login to artifactory
set -e
echo "logging into artifactory"
curl "https://$ARTIFACTORY_URL/ui/api/v1/ui/auth/login" \
--retry 5 \
--cookie-jar cookiejar \
--header 'Accept: application/json, text/plain, */*' \
--header 'Accept-Encoding: gzip, deflate, br' \
--header 'Content-Type: application/json' \
--header 'X-Requested-With: XMLHttpRequest' \
--data-raw "{\"user\":\"admin\",\"password\":\"$ADMIN_PASSWORD\",\"type\":\"login\"}"
- | # create admin bearer token and set terraform variable from output to create jfrog resources
set -e
echo "creating artifactory admin token for jfrog providers to use"
payload=$(curl "https://$ARTIFACTORY_URL/ui/api/v1/access/token/scoped?expiry=24&services[]=all&scope=applied-permissions%2Fadmin&username=admin-$CI_COMMIT_REF_SLUG" \
-b cookiejar \
--globoff \
--header 'Accept: application/json, text/plain, */*' \
--header 'Accept-Encoding: gzip, deflate, br' \
--header 'X-Requested-With: XMLHttpRequest' \
--header 'Connection: keep-alive')
token_id=$(echo $payload| jq -r '.token_id')
- export TF_VAR_artifactory_access_token=$(echo $payload| jq -r '.access_token')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment