#!/bin/bash # Copyright (C) 2023 RES IT srl. All rights reserved. # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . set -e ProgName=$(basename $0) sub_help(){ echo "Usage: $ProgName [options]\n" echo "Subcommands:" echo " generate-keys Generates private and public keys to be used to sign secrets" echo " register-secrets Signs the secrets and uploads them to Jenres API into the secrets repository" echo "" echo "For help with each subcommand run:" echo "$ProgName -h|--help" echo "" } sub_generate_keys(){ echo "Running generate-keys command" # Parse command line arguments for generate-keys while [[ $# -gt 0 ]]; do key="$1" case $key in --scrooj) jenres_config_folder_prefix=".scrooj" shift # past argument ;; *) # unknown option shift # past argument ;; esac done # Set default folder prefix if not provided jenres_config_folder_prefix=${jenres_config_folder_prefix:-".jenres"} mkdir -p ${jenres_config_folder_prefix} openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4092 -outform pem -out ${jenres_config_folder_prefix}/jenres_rsa_private.pem openssl pkey -in ${jenres_config_folder_prefix}/jenres_rsa_private.pem -pubout -out ${jenres_config_folder_prefix}/jenres_rsa_public.pem cp ${jenres_config_folder_prefix}/jenres_rsa_public.pem ${jenres_config_folder_prefix}/pub.key # add ${jenres_config_folder_prefix}/jenres_rsa_public.pem and ${jenres_config_folder_prefix}/jenres_rsa_private.pem to gitignore file if not already there if ! grep -q "${jenres_config_folder_prefix}/jenres_rsa_public.pem" .gitignore; then echo "" >> .gitignore echo "${jenres_config_folder_prefix}/jenres_rsa_public.pem" >> .gitignore fi if ! grep -q "${jenres_config_folder_prefix}/jenres_rsa_private.pem" .gitignore; then echo "" >> .gitignore echo "${jenres_config_folder_prefix}/jenres_rsa_private.pem" >> .gitignore fi if ! grep -q "${jenres_config_folder_prefix}/jenres_rsa_private.pem" .gitignore; then echo "" >> .gitignore echo "${jenres_config_folder_prefix}/jenres_rsa_private.pem" >> .gitignore fi # perform git add on .gitignore and ${jenres_config_folder_prefix}/pub.key git add .gitignore ${jenres_config_folder_prefix}/pub.key echo "Keys generated and the public key has been added to Git index." echo "Now you should review the changes, commit and push them." } sub_register_secrets(){ echo "Running register-secrets command" # Function to generate the secret and signature generate_secret(){ openai_api_key=$1 sonarcloud_token=$2 # Generate the secret if [ ! -z "$sonarcloud_token" ]; then secret="{\"openai_api_key\":\"$openai_api_key\",\"sonar_token\":\"$sonarcloud_token\"}" else secret="{\"openai_api_key\":\"$openai_api_key\"}" fi echo $secret } # Function to generate the secret and signature generate_signature(){ private_key_path=$1 secret=$2 # Generate the signature signature=$(echo -n $secret | openssl dgst -sha256 -sign $private_key_path | openssl enc -base64 | tr -d '\n') echo $signature } # Function to update the secret using curl update_secret(){ url=$1 repository=$2 secret=$3 signature=$4 # Check if all parameters are provided if [ -z "$url" ] || [ -z "$repository" ] || [ -z "$secret" ] || [ -z "$signature" ]; then echo "Usage: update_secret " return 1 fi # $secret and $signature are not escaped, create the escaped versions escaped_secret=$(echo $secret | sed 's/"/\\"/g') escaped_signature=$(echo $signature | sed 's/"/\\"/g') # Use curl to update the secret response=$(curl -X PUT -H "Content-Type: application/json" -d "{\"secret\":\"$escaped_secret\",\"signature\":\"$escaped_signature\"}" $url/$repository ) # Print the response echo "Response:" echo "${response}" } # Parse command line arguments while [[ $# -gt 0 ]]; do key="$1" case $key in --url) url="$2" shift # past argument shift # past value ;; --private-key) private_key_path="$2" shift # past argument shift # past value ;; --repo) repository="$2" shift # past argument shift # past value ;; -h|--help) echo "Usage: $0 [--url ] [--private-key ] [--repo ] [--scrooj]" echo "" echo "Options:" echo " --url URL of the secrets API. Default is 'https://jenres-api.aws.res-it.com/secrets'." echo " --private-key Path to the private key file. Default is '${jenres_config_folder_prefix}/jenres_rsa_private.pem'." echo " --scrooj Use the '.scrooj' configuration folder and test API URL." echo " --repo Name of the repository. If not provided, it will be extracted from the git remote URL." echo " -h, --help Show this help message." exit 0 ;; --scrooj) echo "Using Jenres test environment: Scrooj" jenres_config_folder_prefix=".scrooj" url="https://scrooj-api.aws.res-it.com/secrets" shift # past argument ;; *) # unknown option shift # past argument ;; esac done # Set default values if not provided jenres_config_folder_prefix=${jenres_config_folder_prefix:-".jenres"} url=${url:-"https://jenres-api.aws.res-it.com/secrets"} private_key_path=${private_key_path:-"${jenres_config_folder_prefix}/jenres_rsa_private.pem"} # If the repository parameter was not provided, extract the repository name from the git remote URL if [ -z "$repository" ]; then git_url=$(git remote -v | head -n1 | awk '{print $2}') if [[ $git_url == https://github.com/* ]]; then repository=${git_url#https://github.com/} repository=${repository%.git} elif [[ $git_url == git@github.com:* ]]; then repository=${git_url#git@github.com:} repository=${repository%.git} else echo "Could not extract repository name from git remote URL. Please provide it as a parameter." exit 1 fi fi read -p "Enter OPENAI_API_KEY: " openai_api_key read -p "Enter SonarCloud token [optional, empty to skip]: " sonarcloud_token # Generate the secret and signature secret=$(generate_secret $openai_api_key $sonarcloud_token) signature=$(generate_signature $private_key_path $secret) # Print a summary of the parameters echo "URL: $url" echo "Private Key Path: $private_key_path" echo "Repository: $repository" echo "OPENAI_API_KEY: $openai_api_key" echo "SonarCloud token: $sonarcloud_token" # Ask for confirmation before uploading read -p "Are you sure you want to upload these secrets? (y/n) " confirm if [[ $confirm == [yY] || $confirm == [yY][eE][sS] ]]; then # Update the secret update_secret $url $repository $secret $signature else echo "Aborted." exit 1 fi } subcommand=$1 case $subcommand in "" | "-h" | "--help") sub_help ;; *) shift # replace "-" with "_" for subcommand function name subcommand_fun=${subcommand//-/_} sub_${subcommand_fun} $@ if [ $? = 127 ]; then echo "Error: '$subcommand' is not a known subcommand." >&2 echo " Run '$ProgName --help' for a list of known subcommands." >&2 exit 1 fi ;; esac