From 056e65893dbeef43838aaef34375d079885a3a46 Mon Sep 17 00:00:00 2001 From: Matthias Kay Date: Wed, 1 May 2024 13:25:33 +0200 Subject: [PATCH 1/7] KEEPASS --- aws_login.sh | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/aws_login.sh b/aws_login.sh index 84e0367..59edb7a 100644 --- a/aws_login.sh +++ b/aws_login.sh @@ -35,6 +35,28 @@ function aws_login() { fi } + function get_rackspace_username_and_api_key() { + kpscript_executable=$(command -v kpscript) + + if [ -z "$KEEPASS_FILE" ] || [ -z "$kpscript_executable" ] ; then + # no Keepass in place --> ask the user + echo "Did not found your Keepass file or KPScript executable. Please enter your Rackspace credentials." + + read -r -p 'Rackspace username: ' username + read -r -sp 'Rackspace API key: ' api_key + else + # get credentials from Keepass + echo "Reading credentials from Keepass: $KEEPASS_FILE" + + read -r -sp 'Keepass Password: ' keepass_password + + username=$(KPScript.exe -c:GetEntryString "${KEEPASS_FILE}" -Field:UserName -ref-Title:"Rackspace" -FailIfNoEntry -pw:"$keepass_password" | head -n1 ) + api_key=$( KPScript.exe -c:GetEntryString "${KEEPASS_FILE}" -Field:api-key -ref-Title:"Rackspace" -FailIfNoEntry -pw:"$keepass_password" | head -n1 ) + fi + + echo "$username" "$api_key" + } + temporary_rackspace_token=$(jq -r '.access.token.id' <<<"$rackspace_token_json") tennant_id=$(jq -r '.access.token.tenant.id' <<<"$rackspace_token_json") @@ -51,9 +73,6 @@ function aws_login() { aws sts get-caller-identity --profile "$aws_profile_name" >/dev/null 2>&1 || exit_state=$? if [ $exit_state -ne 0 ]; then - read -r -p 'Rackspace username: ' username - read -r -sp 'Rackspace API key: ' api_key - # insert new line after last input echo From b1669dddc92b9c026e82d45cf9896375f56fc0fe Mon Sep 17 00:00:00 2001 From: Matthias Kay Date: Wed, 1 May 2024 13:46:23 +0200 Subject: [PATCH 2/7] KEEPASS --- aws_login.sh | 45 +++++++++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/aws_login.sh b/aws_login.sh index 59edb7a..fa35456 100644 --- a/aws_login.sh +++ b/aws_login.sh @@ -50,15 +50,40 @@ function aws_login() { read -r -sp 'Keepass Password: ' keepass_password - username=$(KPScript.exe -c:GetEntryString "${KEEPASS_FILE}" -Field:UserName -ref-Title:"Rackspace" -FailIfNoEntry -pw:"$keepass_password" | head -n1 ) - api_key=$( KPScript.exe -c:GetEntryString "${KEEPASS_FILE}" -Field:api-key -ref-Title:"Rackspace" -FailIfNoEntry -pw:"$keepass_password" | head -n1 ) + username=$($kpscript_executable -c:GetEntryString "${KEEPASS_FILE}" -Field:UserName -ref-Title:"Rackspace" -FailIfNoEntry -pw:"$keepass_password" | head -n1 ) + api_key=$($kpscript_executable -c:GetEntryString "${KEEPASS_FILE}" -Field:api-key -ref-Title:"Rackspace" -FailIfNoEntry -pw:"$keepass_password" | head -n1 ) fi echo "$username" "$api_key" } - temporary_rackspace_token=$(jq -r '.access.token.id' <<<"$rackspace_token_json") - tennant_id=$(jq -r '.access.token.tenant.id' <<<"$rackspace_token_json") + function get_rackspace_token_and_tenant() { + read rackspace_username rackspace_api_key < <(get_rackspace_username_and_api_key) + + rackspace_token_json=$(curl --location 'https://identity.api.rackspacecloud.com/v2.0/tokens' \ + --header 'Content-Type: application/json' \ + --silent \ + --data "{ + \"auth\": { + \"RAX-KSKEY:apiKeyCredentials\": { + \"username\": \"$rackspace_username\", + \"apiKey\": \"$rackspace_api_key\" + } + } + }") + + temporary_token=$(jq -r '.access.token.id' <<<"$rackspace_token_json") + tennant_id=$(jq -r '.access.token.tenant.id' <<<"$rackspace_token_json") + + echo "$temporary_token" "$tennant_id" + } + + local temporary_rackspace_token + local tennant_id + + if [ ! -f "$config_dir/aws_accounts.txt" ]; then + read temporary_rackspace_token tennant_id < <(get_rackspace_token_and_tenant "$rackspace_username" "$rackspace_api_key") + fi aws_accounts=$(get_aws_accounts_from_rackspace "$temporary_rackspace_token" "$tennant_id") @@ -76,18 +101,6 @@ function aws_login() { # insert new line after last input echo - rackspace_token_json=$(curl --location 'https://identity.api.rackspacecloud.com/v2.0/tokens' \ - --header 'Content-Type: application/json' \ - --silent \ - --data "{ - \"auth\": { - \"RAX-KSKEY:apiKeyCredentials\": { - \"username\": \"$username\", - \"apiKey\": \"$api_key\" - } - } - }") - temp_credentials=$(curl --location --silent \ --request POST "https://accounts.api.manage.rackspace.com/v0/awsAccounts/$aws_account_no/credentials" \ --header "X-Auth-Token: $temporary_rackspace_token" \ From e12e27a00e27301c495e1f51e2843c2967ca1899 Mon Sep 17 00:00:00 2001 From: Matthias Kay Date: Wed, 1 May 2024 13:48:35 +0200 Subject: [PATCH 3/7] KEEPASS --- aws_login.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aws_login.sh b/aws_login.sh index fa35456..0bb9130 100644 --- a/aws_login.sh +++ b/aws_login.sh @@ -82,7 +82,7 @@ function aws_login() { local tennant_id if [ ! -f "$config_dir/aws_accounts.txt" ]; then - read temporary_rackspace_token tennant_id < <(get_rackspace_token_and_tenant "$rackspace_username" "$rackspace_api_key") + read temporary_rackspace_token tennant_id < <(get_rackspace_token_and_tenant) fi aws_accounts=$(get_aws_accounts_from_rackspace "$temporary_rackspace_token" "$tennant_id") From 655d909b7404d1ff512c83276acd6704369e316f Mon Sep 17 00:00:00 2001 From: Matthias Kay Date: Fri, 3 May 2024 16:42:22 +0200 Subject: [PATCH 4/7] KEEPASS --- README.md | 19 +++++++++++++-- aws_login.sh | 65 +++++++++++++++++++++++----------------------------- 2 files changed, 46 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index 561916b..3873a71 100644 --- a/README.md +++ b/README.md @@ -9,18 +9,33 @@ Main features: - fetch new credentials only if old ones are expired or not present - use AWS profiles via `aws configure` - list all AWS accounts you are authorized to +- supports Keepass for storing the Rackspace username and API key ## Installation The minimum requirements are the AWS CLI and [JQ](https://github.com/jqlang/jq). Install them first. +## KeePass support + +Create a new entry in your KeePass database with the following fields: + +- titls: Rackspace +- username: your Rackspace username +- add a custom field with the name `api-key` and the value of your Rackspace API key + +Set the path to your KeePass database in the environment variable `KEEPASS_FILE`. + +```bash +export KEEPASS_FILE="$HOME/keepass.kdbx" +``` + ## Usage Execute `aws_login` on the command line. The first time, the script creates a file in -`$HOME/config/rackspace-aws-login/aws_accounts.json` caching your accounts. Remove the file to reset the accounts. +`$HOME/.config/rackspace-aws-login/aws_accounts.txt` caching your accounts. Remove the file to reset the accounts. In case the script retrieves the credentials from Rackspace, it asks for the Rackspace username and API key. Check your -Rackspace account to set up the API key. +Rackspace account to set up the API key. You can put both in a KeePass database and the script will fetch them from there. ```bash # place this in your .bash_profile diff --git a/aws_login.sh b/aws_login.sh index 0bb9130..e2398c1 100644 --- a/aws_login.sh +++ b/aws_login.sh @@ -15,50 +15,47 @@ function aws_login() { mkdir -p "$config_dir" fi - function get_aws_accounts_from_rackspace() { - local temporary_rackspace_token - local tennant_id + local temporary_rackspace_token + local rackspace_tennant_id + local rackspace_username + local rackspace_api_key - temporary_rackspace_token=$1 - tennant_id=$2 + function get_aws_accounts_from_rackspace() { + if [ -z "$temporary_rackspace_token" ]; then + get_rackspace_token_and_tenant + fi - if [ -f "$config_dir/aws_accounts.txt" ]; then - cat "$config_dir/aws_accounts.txt" - else - aws_accounts=$(curl --location 'https://accounts.api.manage.rackspace.com/v0/awsAccounts' \ - --silent \ - --header "X-Auth-Token: $temporary_rackspace_token" \ - --header "X-Tenant-Id: $tennant_id" | jq -r '.awsAccounts[] | .awsAccountNumber + "_" + .name' | sed 's/\r//' | sort) + aws_accounts=$(curl --location 'https://accounts.api.manage.rackspace.com/v0/awsAccounts' \ + --silent \ + --header "X-Auth-Token: $temporary_rackspace_token" \ + --header "X-Tenant-Id: $rackspace_tennant_id" | jq -r '.awsAccounts[] | .awsAccountNumber + "_" + .name' | sed 's/\r//' | sort) - echo "$aws_accounts" > "$config_dir/aws_accounts.txt" - echo "$aws_accounts" - fi + echo "$aws_accounts" > "$config_dir/aws_accounts.txt" } function get_rackspace_username_and_api_key() { kpscript_executable=$(command -v kpscript) - if [ -z "$KEEPASS_FILE" ] || [ -z "$kpscript_executable" ] ; then + if [ -z "$KEEPASS_FILE" ] || [ -z "$kpscript_executable" ]; then # no Keepass in place --> ask the user echo "Did not found your Keepass file or KPScript executable. Please enter your Rackspace credentials." - read -r -p 'Rackspace username: ' username - read -r -sp 'Rackspace API key: ' api_key + read -r -p 'Rackspace username: ' rackspace_username + read -r -sp 'Rackspace API key: ' rackspace_api_key else # get credentials from Keepass - echo "Reading credentials from Keepass: $KEEPASS_FILE" + echo "Reading credentials from Keepass: $KEEPASS_FILE. Entry Rackspace (username + api-key field)." read -r -sp 'Keepass Password: ' keepass_password + echo "" - username=$($kpscript_executable -c:GetEntryString "${KEEPASS_FILE}" -Field:UserName -ref-Title:"Rackspace" -FailIfNoEntry -pw:"$keepass_password" | head -n1 ) - api_key=$($kpscript_executable -c:GetEntryString "${KEEPASS_FILE}" -Field:api-key -ref-Title:"Rackspace" -FailIfNoEntry -pw:"$keepass_password" | head -n1 ) + rackspace_username=$($kpscript_executable -c:GetEntryString "${KEEPASS_FILE}" -Field:UserName -ref-Title:"Rackspace" -FailIfNoEntry -pw:"$keepass_password" | head -n1 ) + rackspace_api_key=$($kpscript_executable -c:GetEntryString "${KEEPASS_FILE}" -Field:api-key -ref-Title:"Rackspace" -FailIfNoEntry -pw:"$keepass_password" | head -n1 ) fi - - echo "$username" "$api_key" } function get_rackspace_token_and_tenant() { - read rackspace_username rackspace_api_key < <(get_rackspace_username_and_api_key) + get_rackspace_username_and_api_key rackspace_token_json=$(curl --location 'https://identity.api.rackspacecloud.com/v2.0/tokens' \ --header 'Content-Type: application/json' \ @@ -72,20 +69,15 @@ function aws_login() { } }") - temporary_token=$(jq -r '.access.token.id' <<<"$rackspace_token_json") - tennant_id=$(jq -r '.access.token.tenant.id' <<<"$rackspace_token_json") - - echo "$temporary_token" "$tennant_id" + temporary_rackspace_token=$(jq -r '.access.token.id' <<<"$rackspace_token_json") + rackspace_tennant_id=$(jq -r '.access.token.tenant.id' <<<"$rackspace_token_json") } - local temporary_rackspace_token - local tennant_id - if [ ! -f "$config_dir/aws_accounts.txt" ]; then - read temporary_rackspace_token tennant_id < <(get_rackspace_token_and_tenant) + get_rackspace_token_and_tenant fi - aws_accounts=$(get_aws_accounts_from_rackspace "$temporary_rackspace_token" "$tennant_id") + aws_accounts=$(cat "$config_dir/aws_accounts.txt") PS3='Select the AWS account to connect to: ' select opt in $aws_accounts; do @@ -98,13 +90,14 @@ function aws_login() { aws sts get-caller-identity --profile "$aws_profile_name" >/dev/null 2>&1 || exit_state=$? if [ $exit_state -ne 0 ]; then - # insert new line after last input - echo + if [ -z "$temporary_rackspace_token" ]; then + get_rackspace_token_and_tenant + fi temp_credentials=$(curl --location --silent \ --request POST "https://accounts.api.manage.rackspace.com/v0/awsAccounts/$aws_account_no/credentials" \ --header "X-Auth-Token: $temporary_rackspace_token" \ - --header "X-Tenant-Id: $tennant_id") + --header "X-Tenant-Id: $rackspace_tennant_id") access_key=$(jq -r '.credential.accessKeyId' <<<"$temp_credentials") secret_access_key=$(jq -r '.credential.secretAccessKey' <<<"$temp_credentials") From 982379294d8e8f716e96fb00429ccd1d718b88e2 Mon Sep 17 00:00:00 2001 From: Matthias Kay Date: Fri, 3 May 2024 16:49:59 +0200 Subject: [PATCH 5/7] spell check --- .config/cspell.json | 3 +++ README.md | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.config/cspell.json b/.config/cspell.json index 9513826..1aed13e 100644 --- a/.config/cspell.json +++ b/.config/cspell.json @@ -8,6 +8,7 @@ "dockerhub", "Hapag", "Infracost", + "keepass", "oidc", "pytest", "Repology", @@ -35,6 +36,8 @@ "hmarr", "ibiqlik", "kayman", + "kdbx", + "kpscript", "kskey", "ludeeus", "markdownlint", diff --git a/README.md b/README.md index 3873a71..dbe6c25 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ The minimum requirements are the AWS CLI and [JQ](https://github.com/jqlang/jq). Create a new entry in your KeePass database with the following fields: -- titls: Rackspace +- title: Rackspace - username: your Rackspace username - add a custom field with the name `api-key` and the value of your Rackspace API key From 9165e16a821c0ff8f0690b089f0b709d9c10e925 Mon Sep 17 00:00:00 2001 From: Matthias Kay Date: Fri, 3 May 2024 16:57:07 +0200 Subject: [PATCH 6/7] KEEPASS --- aws_login.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/aws_login.sh b/aws_login.sh index e2398c1..7c540c2 100644 --- a/aws_login.sh +++ b/aws_login.sh @@ -42,6 +42,8 @@ function aws_login() { read -r -p 'Rackspace username: ' rackspace_username read -r -sp 'Rackspace API key: ' rackspace_api_key + + echo "" else # get credentials from Keepass echo "Reading credentials from Keepass: $KEEPASS_FILE. Entry Rackspace (username + api-key field)." @@ -74,7 +76,7 @@ function aws_login() { } if [ ! -f "$config_dir/aws_accounts.txt" ]; then - get_rackspace_token_and_tenant + get_aws_accounts_from_rackspace fi aws_accounts=$(cat "$config_dir/aws_accounts.txt") From 5683bbaf5c1478e50751ddbd95d117b57c1f36c1 Mon Sep 17 00:00:00 2001 From: Matthias Kay Date: Sat, 4 May 2024 23:37:23 +0200 Subject: [PATCH 7/7] Check for existing and non-empty file --- aws_login.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aws_login.sh b/aws_login.sh index 7c540c2..00c6bf3 100644 --- a/aws_login.sh +++ b/aws_login.sh @@ -75,7 +75,7 @@ function aws_login() { rackspace_tennant_id=$(jq -r '.access.token.tenant.id' <<<"$rackspace_token_json") } - if [ ! -f "$config_dir/aws_accounts.txt" ]; then + if [ ! -s "$config_dir/aws_accounts.txt" ]; then get_aws_accounts_from_rackspace fi