-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
236 additions
and
87 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,70 +15,29 @@ spec: | |
- name: gitlab-settings-botaccounts | ||
image: "{{ .Values.global.kubectl.image.repository }}:{{ .Values.global.kubectl.image.tag }}" | ||
command: ["/bin/bash", "-c"] | ||
|
||
# A handy command for testing this locally outside of a deploy lifecycle: | ||
# helm template charts/settings --show-only templates/bot-accounts-job.yaml | yq -r '.spec.template.spec.containers[0].args[0]' | sh | ||
args: | ||
- | | ||
create_gitlab_user_token() { | ||
# Input parameters | ||
username="$1" | ||
scopes="$2" # Scopes as a comma-separated list | ||
secretName="$3" | ||
secretNamespace="$4" | ||
secretKeyName="$5" | ||
# Function for logging messages with timestamp in UTC in parentheses | ||
log_message() { | ||
echo "$(date -u +'%Y-%m-%d %H:%M:%S') (UTC) $1" | ||
} | ||
log_message "Making bot account for $username" | ||
# Combining all kubectl exec calls into a single call | ||
user_info=$(kubectl exec -n gitlab deployment/gitlab-toolbox -- bash -c "gitlab-rails runner -e production \" | ||
# Step 1: Check if the user already exists | ||
user = User.find_by_username('$username'); | ||
if user.present? | ||
puts 'User already exists' | ||
puts 'User details:' | ||
puts 'Username: ' + user.username | ||
puts 'Email: ' + user.email | ||
puts 'Name: ' + user.name | ||
puts 'Active: ' + user.state # Whether the user is active or blocked | ||
puts 'Created at: ' + user.created_at.to_s # Log the created date | ||
exit 1 | ||
end | ||
# Step 2: Create the user account if it doesn't exist | ||
password = SecureRandom.alphanumeric(16) | ||
user = User.new(username: '$username', email: '[email protected]', name: '$username', password: password); | ||
user.assign_personal_namespace(Organizations::Organization.default_organization); | ||
user.skip_confirmation! # Skip email confirmation | ||
user.save! | ||
# Step 3: Generate a personal access token (PAT) for the user with multiple scopes | ||
scopes = '$scopes'.split(',').map(&:strip).map(&:to_sym) # Properly split and convert scopes to symbols | ||
token = user.personal_access_tokens.create( | ||
scopes: scopes, # Pass scopes as an array of symbols | ||
name: 'Bot Account $username Access Token', | ||
expires_at: 365.days.from_now | ||
); | ||
token.save! | ||
puts token.token # Only print the token to stdout | ||
\"") | ||
# If the user already exists, the script will exit early and return additional details | ||
if echo "$user_info" | grep -q "User already exists"; then | ||
log_message "$user_info" | ||
log_message "User '$username' already exists." | ||
elif [ -z "$user_info" ]; then | ||
log_message "Failed to generate personal access token for '$username'." | ||
return 1 | ||
fi | ||
# Global variable to store the generated PAT for each account | ||
generated_pat="" | ||
# Function for logging messages with timestamp in UTC in parentheses | ||
log_message() { | ||
echo "$(date -u +'%Y-%m-%d %H:%M:%S') (UTC) $1" | ||
} | ||
create_kubernetes_secret() { | ||
local secretName=$1 | ||
local secretNamespace=$2 | ||
local secretKeyName=$3 | ||
local generated_pat=$4 | ||
# Step 4: Create Kubernetes secret with the generated PAT | ||
kubectl create secret generic "$secretName" \ | ||
--namespace="$secretNamespace" \ | ||
--from-literal="$secretKeyName=$user_info" | ||
--from-literal="$secretKeyName=$generated_pat" | ||
if [ $? -eq 0 ]; then | ||
log_message "Kubernetes secret '$secretName' created successfully in namespace '$secretNamespace'." | ||
|
@@ -88,13 +47,219 @@ spec: | |
fi | ||
} | ||
create_gitlab_user_account() { | ||
# Input parameters | ||
local username="$1" | ||
local scope_list="$2" # Scopes as a comma-separated list | ||
local email="[email protected]" | ||
local name=$username | ||
# Check if the user already exists | ||
local user_exists | ||
user_exists=$(curl --silent --header "PRIVATE-TOKEN: $TOKEN" "https://gitlab.uds.dev/api/v4/users?username=$username") | ||
if echo "$user_exists" | grep -q '"id":'; then | ||
echo "User already exists" | ||
echo "User details: $user_exists" | ||
return 1 | ||
fi | ||
# Generate a random password | ||
local password | ||
password=$(openssl rand -base64 16) | ||
# Create the user if it doesn't exist | ||
user_response=$(curl --silent --request POST "https://gitlab.uds.dev/api/v4/users" \ | ||
--header "PRIVATE-TOKEN: $TOKEN" \ | ||
--header "Content-Type: application/json" \ | ||
--data "{ | ||
\"email\": \"$email\", | ||
\"username\": \"$username\", | ||
\"name\": \"$name\", | ||
\"password\": \"$password\", | ||
\"skip_confirmation\": true | ||
}") | ||
echo "response is: $user_response" | ||
# Check if user creation was successful | ||
if [ $? -ne 0 ]; then | ||
echo "Error: Failed to create the user." | ||
return 1 | ||
fi | ||
# Extract the new user's ID from the response | ||
user_id=$(echo "$user_response" | jq -r '.id') | ||
# Check if the user ID is valid | ||
if [ "$user_id" == "null" ] || [ -z "$user_id" ]; then | ||
echo "Error: Failed to retrieve the user ID." | ||
return 1 | ||
fi | ||
echo "User created with ID: $user_id" | ||
# Convert the comma-delimited list into separate --data fields for the request | ||
local scope_data="" | ||
IFS=',' read -ra scopes <<< "$scope_list" | ||
for scope in "${scopes[@]}"; do | ||
scope_data+="&scopes[]=$scope" | ||
done | ||
# Print scope data for debugging | ||
echo "Scopes for PAT: $scope_data" | ||
# Create a Personal Access Token (PAT) for the new user with the specified scopes | ||
pat_response=$(curl --header "PRIVATE-TOKEN: $TOKEN" \ | ||
--data "name=Service Account Token$scope_data" \ | ||
--request POST "https://gitlab.uds.dev/api/v4/users/$user_id/personal_access_tokens") | ||
echo "pat response is $pat_response" | ||
# Check if token creation was successful | ||
if [ $? -ne 0 ]; then | ||
echo "Error: Failed to create the Personal Access Token." | ||
return 1 | ||
fi | ||
# Extract the generated token from the response | ||
generated_pat=$(echo "$pat_response" | jq -r '.token') | ||
# Check if token is returned | ||
if [ "$generated_pat" == "null" ] || [ -z "$generated_pat" ]; then | ||
echo "Error: Failed to retrieve the generated token." | ||
return 1 | ||
fi | ||
} | ||
# Function to create a GitLab service account and set the PAT in the global variable | ||
create_gitlab_service_account() { | ||
local username="$1" | ||
local name="$2" | ||
local scope_list="$3" | ||
# Convert the comma-delimited list into separate --data fields for the request | ||
local scope_data="" | ||
IFS=',' read -ra scopes <<< "$scope_list" | ||
for scope in "${scopes[@]}"; do | ||
scope_data+="&scopes[]=$scope" | ||
done | ||
# Print scope data for debugging | ||
echo "Scopes for PAT: $scope_data" | ||
echo "Creating service account with username: $username and name: $name" | ||
# Create the service account user | ||
user_response=$(curl --header "PRIVATE-TOKEN: $TOKEN" \ | ||
--data "username=$username&name=$name" \ | ||
--request POST "https://gitlab.uds.dev/api/v4/service_accounts") | ||
echo "response is: $user_response" | ||
# Check if user creation was successful | ||
if [ $? -ne 0 ]; then | ||
echo "Error: Failed to create the service account user." | ||
return 1 | ||
fi | ||
# Extract the new user's ID from the response | ||
user_id=$(echo "$user_response" | jq -r '.id') | ||
# Check if the user ID is valid | ||
if [ "$user_id" == "null" ] || [ -z "$user_id" ]; then | ||
echo "Error: Failed to retrieve the service account user ID." | ||
return 1 | ||
fi | ||
echo "Service account user created with ID: $user_id" | ||
# Create a Personal Access Token (PAT) for the new user with the specified scopes | ||
pat_response=$(curl --header "PRIVATE-TOKEN: $TOKEN" \ | ||
--data "name=Service Account Token$scope_data" \ | ||
--request POST "https://gitlab.uds.dev/api/v4/users/$user_id/personal_access_tokens") | ||
# Check if token creation was successful | ||
if [ $? -ne 0 ]; then | ||
echo "Error: Failed to create the Personal Access Token." | ||
return 1 | ||
fi | ||
# Extract the generated token from the response | ||
generated_pat=$(echo "$pat_response" | jq -r '.token') | ||
# Check if token is returned | ||
if [ "$generated_pat" == "null" ] || [ -z "$generated_pat" ]; then | ||
echo "Error: Failed to retrieve the generated token." | ||
return 1 | ||
fi | ||
} | ||
# Generate and capture a GitLab token from the GitLab Toolbox Rails Console for the root user | ||
TOKEN=$(kubectl exec -n gitlab deployment/gitlab-toolbox -- \ | ||
gitlab-rails runner -e production \ | ||
"token = User.find_by_username('root').personal_access_tokens.create(scopes: ['api', 'admin_mode'], name: 'Bot Accounts API Token', expires_at: 1.days.from_now); token.save!; puts token.token" | tail -n 1) | ||
echo "root token is $TOKEN" | ||
response=$(curl --header "PRIVATE-TOKEN: $TOKEN" "https://gitlab.uds.dev/api/v4/license") | ||
# Check if the request was successful | ||
if [ $? -ne 0 ]; then | ||
echo "Error: Failed to make request to GitLab API." | ||
exit 1 | ||
fi | ||
echo "license response is $response" | ||
# Parse and extract the plan information using jq | ||
plan=$(echo "$response" | jq -r '.plan') | ||
service_accounts="false" | ||
# Check if plan is found and proceed based on the plan type | ||
if [ "$plan" != "null" ]; then | ||
echo "GitLab Plan: $plan" | ||
if [ "$plan" == "ultimate" ] || [ "$plan" == "premium" ]; then | ||
echo "Plan is $plan, creating GitLab service accounts..." | ||
service_accounts="true" | ||
else | ||
echo "No license plan information available. Creating Gitlab user accounts..." | ||
fi | ||
fi | ||
service_accounts="false" #todo @ewyles - take this back out, just here to force other path for local testin | ||
# Track failed accounts in a string | ||
failed_accounts="" | ||
{{- range .Values.botAccounts }} | ||
create_gitlab_user_token "{{ .username }}" "{{ .scopes | join "," }}" "{{ .secret.name }}" "{{ .secret.namespace }}" "{{ .secret.keyName }}" | ||
if [ $? -ne 0 ]; then | ||
failed_accounts="$failed_accounts {{ .username }}" | ||
if [ "$service_accounts" == "true" ]; then | ||
echo "Creating service account [{{ .username }}]..." | ||
# Call the function to create the service account and set the PAT | ||
create_gitlab_service_account "{{ .username }}" "{{ .username }}" "{{ .scopes | join "," }}" | ||
if [ $? -ne 0 ]; then | ||
failed_accounts+=" {{ .username }}" | ||
else | ||
create_kubernetes_secret "{{ .secret.name }}" "{{ .secret.namespace }}" "{{ .secret.keyName }}" "$generated_pat" | ||
if [ $? -ne 0 ]; then | ||
log_message "Failed to create Kubernetes secret for account '$account'." | ||
failed_accounts+=" {{ .username }}" | ||
fi | ||
fi | ||
else | ||
echo "Creating user account [{{ .username }}]..." | ||
create_gitlab_user_account "{{ .username }}" "{{ .scopes | join "," }}" | ||
if [ $? -ne 0 ]; then | ||
failed_accounts+=" {{ .username }}" | ||
else | ||
create_kubernetes_secret "{{ .secret.name }}" "{{ .secret.namespace }}" "{{ .secret.keyName }}" "$generated_pat" | ||
if [ $? -ne 0 ]; then | ||
log_message "Failed to create Kubernetes secret for account '$account'." | ||
failed_accounts+=" {{ .username }}" | ||
fi | ||
fi | ||
fi | ||
{{- end }} | ||
|
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