From 903ec77cbf9bdb051bfa0dd0886d0593efbf7f97 Mon Sep 17 00:00:00 2001 From: Matheus Lozano Date: Sun, 10 Jul 2022 01:28:37 +0200 Subject: [PATCH 1/5] Create CI/CD pipeline to release the project --- .github/workflows/main.yml | 55 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 .github/workflows/main.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..cb85164 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,55 @@ +name: "Build and Release" +on: + push: + branches: + - main + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: '0' + + - name: Set changelog + id: set-changelog + run: | + ARRAY_SIZE="$(jq -r '.event.commits[] | @base64' <<< '${{ toJSON(github) }}')" + + for i in ${ARRAY_SIZE}; do + MY_COMMIT_MSG="$(base64 -d <<< "${i}" | jq -c ".message" | sed -E 's/^"|"$//g')" + MY_COMMIT_ID="$(base64 -d <<< "${i}" | jq -r ".id[0:7]")" + MY_COMMIT_URL="$(base64 -d <<< "${i}" | jq -r ".url")" + MY_COMMIT_AUTHOR="$(base64 -d <<< "${i}" | jq -r ".author.username")" + CHANGELOG+="$(echo -n "* [${MY_COMMIT_ID}](${MY_COMMIT_URL}) ${MY_COMMIT_MSG//\\n/\\\\n} @${MY_COMMIT_AUTHOR}\n")" + done + + echo "CHANGELOG<> $GITHUB_ENV + echo -e "$CHANGELOG" >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + + - name: Bump version + id: bump-version + uses: anothrnick/github-tag-action@1.35.0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + WITH_V: true + RELEASE_BRANCHES: main + DEFAULT_BUMP: minor + + - name: Create release + uses: softprops/action-gh-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + name: ${{ steps.bump-version.outputs.tag }} + tag_name: ${{ steps.bump-version.outputs.tag }} + draft: false + prerelease: false + fail_on_unmatched_files: true + body: | + ## What's Changed + ${{ env.CHANGELOG }} + + Full Changelog: ${{ github.event.compare }} From 0932b7c5ff978cdea6f5fdc5ae52abeef1ddd1e1 Mon Sep 17 00:00:00 2001 From: Matheus Lozano Date: Sun, 10 Jul 2022 01:28:37 +0200 Subject: [PATCH 2/5] Add license --- LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..89765af --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Matheus Lozano + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From beec984b7392155b6e1d823c4d3d72b99026ab7d Mon Sep 17 00:00:00 2001 From: Matheus Lozano Date: Sun, 10 Jul 2022 01:28:37 +0200 Subject: [PATCH 3/5] awsecure-cli code for Bash --- bin/bash/aws | 25 +++++++++++++++++++++++++ src/bash/validate-prereqs.sh | 30 ++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100755 bin/bash/aws create mode 100755 src/bash/validate-prereqs.sh diff --git a/bin/bash/aws b/bin/bash/aws new file mode 100755 index 0000000..063d446 --- /dev/null +++ b/bin/bash/aws @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +set -eo pipefail + +[[ ! -z "${AWSECURE_CLI_AWS_BIN_FILEPATH}" ]] && declare -x AWSECURE_CLI_AWS_BIN_FILEPATH_TMP="${AWSECURE_CLI_AWS_BIN_FILEPATH}" +[[ ! -z "${AWSECURE_CLI_MUTED}" ]] && declare -lx AWSECURE_CLI_MUTED_TMP="${AWSECURE_CLI_MUTED}" +[[ ! -z "${AWSECURE_CLI_AUTOROTATE_AWS_ACCESS_KEYS}" ]] && declare -lx AWSECURE_CLI_AUTOROTATE_AWS_ACCESS_KEYS_TMP="${AWSECURE_CLI_AUTOROTATE_AWS_ACCESS_KEYS}" +[[ ! -z "${AWSECURE_CLI_AUTOROTATE_PERIOD}" ]] && declare -lx AWSECURE_CLI_AUTOROTATE_PERIOD_TMP="${AWSECURE_CLI_AUTOROTATE_PERIOD}" +[[ ! -z "${AWSECURE_CLI_AUTOROTATE_CHECK}" ]] && declare -lx AWSECURE_CLI_AUTOROTATE_CHECK_TMP="${AWSECURE_CLI_AUTOROTATE_CHECK}" + +. ~/.awsecure-cli + +[[ ! -z "${AWSECURE_CLI_AWS_BIN_FILEPATH_TMP}" ]] && declare -gx AWSECURE_CLI_AWS_BIN_FILEPATH="${AWSECURE_CLI_AWS_BIN_FILEPATH_TMP:-$AWSECURE_CLI_AWS_BIN_FILEPATH}" +[[ ! -z "${AWSECURE_CLI_MUTED_TMP}" ]] && declare -glx AWSECURE_CLI_MUTED="${AWSECURE_CLI_MUTED_TMP:-$AWSECURE_CLI_MUTED}" +[[ ! -z "${AWSECURE_CLI_AUTOROTATE_AWS_ACCESS_KEYS_TMP}" ]] && declare -glx AWSECURE_CLI_AUTOROTATE_AWS_ACCESS_KEYS="${AWSECURE_CLI_AUTOROTATE_AWS_ACCESS_KEYS_TMP:-$AWSECURE_CLI_AUTOROTATE_AWS_ACCESS_KEYS}" +[[ ! -z "${AWSECURE_CLI_AUTOROTATE_PERIOD_TMP}" ]] && declare -glx AWSECURE_CLI_AUTOROTATE_PERIOD="${AWSECURE_CLI_AUTOROTATE_PERIOD_TMP:-$AWSECURE_CLI_AUTOROTATE_PERIOD}" +[[ ! -z "${AWSECURE_CLI_AUTOROTATE_CHECK_TMP}" ]] && declare -glx AWSECURE_CLI_AUTOROTATE_CHECK="${AWSECURE_CLI_AUTOROTATE_CHECK_TMP:-$AWSECURE_CLI_AUTOROTATE_CHECK}" + +if [[ $(type awsecure_cli_log_info 2> /dev/null) == "" || -z "${AWSECURE_CLI_SRC_DIRECTORY// /}" ]]; then + [[ -L ${0} ]] && declare -gr AWSECURE_CLI_SRC_DIRECTORY="$(realpath $(readlink ${0}) | xargs dirname)/../../src" || declare -gr AWSECURE_CLI_SRC_DIRECTORY="$(realpath ${0} | xargs dirname)/../../src" + . ${AWSECURE_CLI_SRC_DIRECTORY}/common/logging.shinc +fi + +awsecure_cli_log_info "Using the AWSecure CLI wrapper" +. ${AWSECURE_CLI_SRC_DIRECTORY}/common/wrapper.sh diff --git a/src/bash/validate-prereqs.sh b/src/bash/validate-prereqs.sh new file mode 100755 index 0000000..a293a47 --- /dev/null +++ b/src/bash/validate-prereqs.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash + +set -eo pipefail + +function awsecure_cli_validate_commands() { + local -rl AWSECURE_CLI_VALIDATE_COMMANDS="jq ${AWSECURE_CLI_AWS_BIN_FILEPATH} ${AWSECURE_CLI_SH_INTERPRETER}" + for cmd in ${AWSECURE_CLI_VALIDATE_COMMANDS}; do + awsecure_cli_log_info "Testing if ${cmd} is installed" + ${cmd} --version &> /dev/null || awsecure_cli_log_error "The ${cmd} is not installed or not in the PATH environment variable" + done +} + +case "${AWSECURE_CLI_OS_NAME// /}" in +darwin) + true + ;; +linux) + true + ;; +*) + awsecure_cli_log_error "OS not supported" + ;; +esac + +awsecure_cli_validate_commands + +set +eo pipefail +${AWSECURE_CLI_AWS_BIN_FILEPATH} configure get aws_access_key_id > /dev/null 2>&1 +[[ $? -ne 0 ]] && { awsecure_cli_log_info "The profile ${AWS_PROFILE} is not using an AWS access key, skipping AWS access key rotation" ; SKIP_AWSECURE_CLI_AUTOROTATE_AWS_ACCESS_KEYS=true ; } +set -eo pipefail From 9f1ac7417c8e9344ce845934b07a4dc957a74dd9 Mon Sep 17 00:00:00 2001 From: Matheus Lozano Date: Sun, 10 Jul 2022 01:28:38 +0200 Subject: [PATCH 4/5] awsecure-cli code for zsh --- bin/zsh/aws | 13 +++++++++++++ src/zsh/validate-prereqs.sh | 30 ++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100755 bin/zsh/aws create mode 100755 src/zsh/validate-prereqs.sh diff --git a/bin/zsh/aws b/bin/zsh/aws new file mode 100755 index 0000000..8a5d1b0 --- /dev/null +++ b/bin/zsh/aws @@ -0,0 +1,13 @@ +#!/usr/bin/env zsh + +set -eo pipefail + +. ~/.awsecure-cli + +if [[ $(type awsecure_cli_log_info 2> /dev/null) == "" || -z "${AWSECURE_CLI_SRC_DIRECTORY// /}" ]]; then + [[ -L ${0} ]] && declare -gr AWSECURE_CLI_SRC_DIRECTORY="$(realpath $(readlink ${0}) | xargs dirname)/../../src" || declare -gr AWSECURE_CLI_SRC_DIRECTORY="$(realpath ${0} | xargs dirname)/../../src" + . ${AWSECURE_CLI_SRC_DIRECTORY}/common/logging.shinc +fi + +awsecure_cli_log_info "Using the AWSecure CLI wrapper" +. ${AWSECURE_CLI_SRC_DIRECTORY}/common/wrapper.sh diff --git a/src/zsh/validate-prereqs.sh b/src/zsh/validate-prereqs.sh new file mode 100755 index 0000000..e8b2b27 --- /dev/null +++ b/src/zsh/validate-prereqs.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env zsh + +set -eo pipefail + +function awsecure_cli_validate_commands() { + local -rl AWSECURE_CLI_VALIDATE_COMMANDS=(jq ${AWSECURE_CLI_AWS_BIN_FILEPATH} ${AWSECURE_CLI_SH_INTERPRETER}) + for cmd in ${AWSECURE_CLI_VALIDATE_COMMANDS}; do + awsecure_cli_log_info "Testing if ${cmd} is installed" + ${cmd} --version &> /dev/null || awsecure_cli_log_error "The ${cmd} is not installed or not in the PATH environment variable" + done +} + +case "${AWSECURE_CLI_OS_NAME// /}" in +darwin) + true + ;; +linux) + true + ;; +*) + awsecure_cli_log_error "OS not supported" + ;; +esac + +awsecure_cli_validate_commands + +set +eo pipefail +${AWSECURE_CLI_AWS_BIN_FILEPATH} configure get aws_access_key_id > /dev/null 2>&1 +[[ $? -ne 0 ]] && { awsecure_cli_log_info "The profile ${AWS_PROFILE} is not using an AWS access key, skipping AWS access key rotation" ; SKIP_AWSECURE_CLI_AUTOROTATE_AWS_ACCESS_KEYS=true ; } +set -eo pipefail From 4cc0149b52a873be26ec28c9e60c6da9b1b4e4ec Mon Sep 17 00:00:00 2001 From: Matheus Lozano Date: Sun, 10 Jul 2022 01:28:38 +0200 Subject: [PATCH 5/5] awsecure-cli core code --- src/common/autorotate_aws_keys.sh | 205 ++++++++++++++++++++++++++++++ src/common/logging.shinc | 27 ++++ src/common/wrapper.sh | 53 ++++++++ 3 files changed, 285 insertions(+) create mode 100755 src/common/autorotate_aws_keys.sh create mode 100755 src/common/logging.shinc create mode 100755 src/common/wrapper.sh diff --git a/src/common/autorotate_aws_keys.sh b/src/common/autorotate_aws_keys.sh new file mode 100755 index 0000000..fbf8be6 --- /dev/null +++ b/src/common/autorotate_aws_keys.sh @@ -0,0 +1,205 @@ +#!/usr/bin/env bash + +set -eo pipefail + +[[ ! -z "${AWSECURE_CLI_AWS_BIN_FILEPATH}" ]] && declare -x AWSECURE_CLI_AWS_BIN_FILEPATH_TMP="${AWSECURE_CLI_AWS_BIN_FILEPATH}" +[[ ! -z "${AWSECURE_CLI_MUTED}" ]] && declare -lx AWSECURE_CLI_MUTED_TMP="${AWSECURE_CLI_MUTED}" +[[ ! -z "${AWSECURE_CLI_AUTOROTATE_AWS_ACCESS_KEYS}" ]] && declare -lx AWSECURE_CLI_AUTOROTATE_AWS_ACCESS_KEYS_TMP="${AWSECURE_CLI_AUTOROTATE_AWS_ACCESS_KEYS}" +[[ ! -z "${AWSECURE_CLI_AUTOROTATE_PERIOD}" ]] && declare -lx AWSECURE_CLI_AUTOROTATE_PERIOD_TMP="${AWSECURE_CLI_AUTOROTATE_PERIOD}" +[[ ! -z "${AWSECURE_CLI_AUTOROTATE_CHECK}" ]] && declare -lx AWSECURE_CLI_AUTOROTATE_CHECK_TMP="${AWSECURE_CLI_AUTOROTATE_CHECK}" + +. ~/.awsecure-cli + +[[ ! -z "${AWSECURE_CLI_AWS_BIN_FILEPATH_TMP}" ]] && declare -gx AWSECURE_CLI_AWS_BIN_FILEPATH="${AWSECURE_CLI_AWS_BIN_FILEPATH_TMP:-$AWSECURE_CLI_AWS_BIN_FILEPATH}" +[[ ! -z "${AWSECURE_CLI_MUTED_TMP}" ]] && declare -glx AWSECURE_CLI_MUTED="${AWSECURE_CLI_MUTED_TMP:-$AWSECURE_CLI_MUTED}" +[[ ! -z "${AWSECURE_CLI_AUTOROTATE_AWS_ACCESS_KEYS_TMP}" ]] && declare -glx AWSECURE_CLI_AUTOROTATE_AWS_ACCESS_KEYS="${AWSECURE_CLI_AUTOROTATE_AWS_ACCESS_KEYS_TMP:-$AWSECURE_CLI_AUTOROTATE_AWS_ACCESS_KEYS}" +[[ ! -z "${AWSECURE_CLI_AUTOROTATE_PERIOD_TMP}" ]] && declare -glx AWSECURE_CLI_AUTOROTATE_PERIOD="${AWSECURE_CLI_AUTOROTATE_PERIOD_TMP:-$AWSECURE_CLI_AUTOROTATE_PERIOD}" +[[ ! -z "${AWSECURE_CLI_AUTOROTATE_CHECK_TMP}" ]] && declare -glx AWSECURE_CLI_AUTOROTATE_CHECK="${AWSECURE_CLI_AUTOROTATE_CHECK_TMP:-$AWSECURE_CLI_AUTOROTATE_CHECK}" + +if [[ $(type awsecure_cli_log_info 2> /dev/null) == "" || -z "${AWSECURE_CLI_SRC_DIRECTORY// /}" ]]; then + [[ -L ${0} ]] && declare -gr AWSECURE_CLI_SRC_DIRECTORY="$(realpath $(readlink ${0}) | xargs dirname)/../../src" || declare -gr AWSECURE_CLI_SRC_DIRECTORY="$(realpath ${0} | xargs dirname)/../../src" + . ${AWSECURE_CLI_SRC_DIRECTORY}/common/logging.shinc +fi + +if [[ ! -z "${ZSH_NAME}" ]]; then + declare -lr AWSECURE_CLI_SH_INTERPRETER="zsh" +elif [[ ! -z "${BASH}" ]]; then + declare -lr AWSECURE_CLI_SH_INTERPRETER="bash" +else + awsecure_cli_log_error "SH Interpreter not supported or not defined" +fi + +declare -lrx AWSECURE_CLI_OS_NAME="$(uname -s)" + +function awsecure_cli_date_format() { + date -u "${@}" +"%s" +} + +function awsecure_cli_aws_access_keys_not_older_than() { + case "${AWSECURE_CLI_OS_NAME// /}" in + darwin) + awsecure_cli_date_format -v "-${AWSECURE_CLI_AUTOROTATE_PERIOD// /}H" + ;; + linux) + awsecure_cli_date_format -d "now - ${AWSECURE_CLI_AUTOROTATE_PERIOD// /} hours" + ;; + *) + echo "Unknown OS" + ;; + esac +} + +function awsecure_cli_get_aws_access_keys() { + ${AWSECURE_CLI_AWS_BIN_FILEPATH} --output json iam list-access-keys +} + +function awsecure_cli_get_aws_access_key_age() { + jq -r '.AccessKeyMetadata[0].CreateDate' <<< ${AWSECURE_CLI_GET_AWS_ACCESS_KEYS} | sed 's/+.*//' +} + +function awsecure_cli_get_aws_access_first_key_id() { + jq -r '.AccessKeyMetadata[0].AccessKeyId' <<< ${AWSECURE_CLI_GET_AWS_ACCESS_KEYS} +} + +function awsecure_cli_validate_aws_access_key() { + : "${AWSECURE_CLI_CREATED_AWS_ACCESS_KEY:?"Variable not set or empty"}" + + jq -r '.AccessKey.Status' <<< "${AWSECURE_CLI_CREATED_AWS_ACCESS_KEY}" | grep "^Active$" &> /dev/null + + awsecure_cli_get_aws_access_keys | jq -r ".AccessKeyMetadata[] | select(.AccessKeyId == \"${AWSECURE_CLI_NEW_AWS_ACCESS_KEY_ID}\").Status" | grep "^Active$" &> /dev/null +} + +function awsecure_cli_disable_old_access_key() { + awsecure_cli_log_info "Disabling the old AWS key from AWS" + sleep 10 + ${AWSECURE_CLI_AWS_BIN_FILEPATH} iam update-access-key --access-key-id "${AWSECURE_CLI_GET_CURRENT_AWS_ACCESS_KEY_ID// /}" --status Inactive +} + +function awsecure_cli_remove_old_access_key() { + awsecure_cli_log_info "Deleting the old AWS key from AWS" + sleep 10 + ${AWSECURE_CLI_AWS_BIN_FILEPATH} iam delete-access-key --access-key-id "${AWSECURE_CLI_GET_CURRENT_AWS_ACCESS_KEY_ID// /}" +} + +function awsecure_cli_change_aws_config_file() { + awsecure_cli_log_info "Getting the AWS_ACCESS_KEY_ID in use" + local -r AWSECURE_CLI_GET_CURRENT_AWS_ACCESS_KEY_ID="$(${AWSECURE_CLI_AWS_BIN_FILEPATH} configure get aws_access_key_id)" + : "${AWSECURE_CLI_GET_CURRENT_AWS_ACCESS_KEY_ID:?"Variable not set or empty"}" + + awsecure_cli_log_info "Getting the AWS_SECRET_ACCESS_KEY in use" + local -r AWSECURE_CLI_GET_CURRENT_AWS_SECRET_ACCESS_KEY="$(${AWSECURE_CLI_AWS_BIN_FILEPATH} configure get aws_secret_access_key | sed 's,\+,\\+,g')" + : "${AWSECURE_CLI_GET_CURRENT_AWS_SECRET_ACCESS_KEY:?"Variable not set or empty"}" + + [[ ${AWSECURE_CLI_OS_NAME} == "darwin" ]] && local -r AWSECURE_CLI_SED_CMD=" " + + awsecure_cli_log_info "Setting the new AWS_ACCESS_KEY_ID and disabling the old AWS_ACCESS_KEY_ID in the AWS config file ${AWS_CONFIG_FILE}" + sed -i${AWSECURE_CLI_SED_CMD}'' -E "s,(${AWSECURE_CLI_GET_CURRENT_AWS_ACCESS_KEY_ID}),${AWSECURE_CLI_NEW_AWS_ACCESS_KEY_ID}\n# AWS_ACCESS_KEY_ID = \\1," ${AWS_CONFIG_FILE} + + awsecure_cli_log_info "Setting the new AWS_SECRET_ACCESS_KEY and disabling the old AWS_SECRET_ACCESS_KEY in the AWS config file ${AWS_CONFIG_FILE}" + sed -i${AWSECURE_CLI_SED_CMD}'' -E "s,(${AWSECURE_CLI_GET_CURRENT_AWS_SECRET_ACCESS_KEY}),${NEW_AWS_SECRET_ACCESS_KEY}\n# AWS_SECRET_ACCESS_KEY = \\1," ${AWS_CONFIG_FILE} + + awsecure_cli_disable_old_access_key + awsecure_cli_remove_old_access_key +} + +function awsecure_cli_rotate_aws_access_key() { + awsecure_cli_log_info "Creating a new AWS keys" + local -r AWSECURE_CLI_CREATED_AWS_ACCESS_KEY="$(${AWSECURE_CLI_AWS_BIN_FILEPATH} --output json iam create-access-key)" + : "${AWSECURE_CLI_CREATED_AWS_ACCESS_KEY:?"Variable not set or empty"}" + + awsecure_cli_log_info "Getting the new AWS_ACCESS_KEY_ID" + local -r AWSECURE_CLI_NEW_AWS_ACCESS_KEY_ID="$(jq -r '.AccessKey.AccessKeyId' <<< ${AWSECURE_CLI_CREATED_AWS_ACCESS_KEY})" + : "${AWSECURE_CLI_NEW_AWS_ACCESS_KEY_ID:?"Variable not set or empty"}" + + awsecure_cli_log_info "Getting the new AWS_SECRET_ACCESS_KEY" + local -r NEW_AWS_SECRET_ACCESS_KEY="$(jq -r '.AccessKey.SecretAccessKey' <<< ${AWSECURE_CLI_CREATED_AWS_ACCESS_KEY})" + : "${NEW_AWS_SECRET_ACCESS_KEY:?"Variable not set or empty"}" + + awsecure_cli_log_info "Validating the new AWS_SECRET_ACCESS_KEY" + awsecure_cli_validate_aws_access_key + + awsecure_cli_log_info "Changing your AWS_CONFIG_FILE" + awsecure_cli_change_aws_config_file +} + +function awsecure_cli_create_autorotate_state_file() { + set -eo pipefail + ${AWSECURE_CLI_STATE_FILE_OPTION} ${AWSECURE_CLI_AUTOROTATE_STATE_FILE// /} &> /dev/null +} + +function awsecure_cli_autorotate_aws_access_keys() { + . ${AWSECURE_CLI_SRC_DIRECTORY}/${AWSECURE_CLI_SH_INTERPRETER}/validate-prereqs.sh + [[ "${SKIP_AWSECURE_CLI_AUTOROTATE_AWS_ACCESS_KEYS}" = "true" ]] && return 0 + + local -r AWS_CONFIG_FILE=${AWS_CONFIG_FILE:-~/.aws/credentials} + + local -r AWSECURE_CLI_AUTOROTATE_PERIOD="${AWSECURE_CLI_AUTOROTATE_PERIOD:-"168"}" + local -r AWSECURE_CLI_AWS_ACCESS_KEYS_NOT_OLDER_THAN=$(awsecure_cli_aws_access_keys_not_older_than) + : "${AWSECURE_CLI_AWS_ACCESS_KEYS_NOT_OLDER_THAN:?"Variable not set or empty"}" + + local -r AWSECURE_CLI_GET_AWS_ACCESS_KEYS="$(awsecure_cli_get_aws_access_keys)" + : "${AWSECURE_CLI_GET_AWS_ACCESS_KEYS:?"Variable not set or empty"}" + + case "${AWSECURE_CLI_OS_NAME// /}" in + darwin) + local -r AWSECURE_CLI_FIRST_AWS_ACCESS_KEY_AGE="$(awsecure_cli_get_aws_access_key_age | xargs -I{} ${AWSECURE_CLI_SH_INTERPRETER} -c "$(declare -f awsecure_cli_date_format) ; awsecure_cli_date_format -jf%Y-%m-%dT%H:%M:%S {}")" + : "${AWSECURE_CLI_FIRST_AWS_ACCESS_KEY_AGE:?"Variable not set or empty"}" + ;; + linux) + local -r AWSECURE_CLI_FIRST_AWS_ACCESS_KEY_AGE="$(awsecure_cli_get_aws_access_key_age | xargs -I{} ${AWSECURE_CLI_SH_INTERPRETER} -c "$(declare -f awsecure_cli_date_format) ; awsecure_cli_date_format -d {}")" + : "${AWSECURE_CLI_FIRST_AWS_ACCESS_KEY_AGE:?"Variable not set or empty"}" + ;; + *) + echo "Unknown OS" + ;; + esac + + local -r AWSECURE_CLI_FIRST_ACCESS_KEY_ID="$(awsecure_cli_get_aws_access_first_key_id)" + + if [[ ${AWSECURE_CLI_AWS_ACCESS_KEYS_NOT_OLDER_THAN} -gt ${AWSECURE_CLI_FIRST_AWS_ACCESS_KEY_AGE} ]]; then + awsecure_cli_log_info "Your key ${AWSECURE_CLI_FIRST_ACCESS_KEY_ID} is older than ${AWSECURE_CLI_AUTOROTATE_PERIOD// /} hours" + awsecure_cli_log_info "Starting renewing your access key ${AWSECURE_CLI_FIRST_ACCESS_KEY_ID}" + awsecure_cli_rotate_aws_access_key + else + awsecure_cli_log_info "No need to renew the access keys ${AWSECURE_CLI_FIRST_ACCESS_KEY_ID}, it's newer than ${AWSECURE_CLI_AUTOROTATE_PERIOD// /} hours" + fi + + set +eo pipefail + [[ ! -z "${AWSECURE_CLI_STATE_FILE_OPTION// /}" ]] && awsecure_cli_create_autorotate_state_file + set -eo pipefail +} + +function awsecure_cli_autorotate_check() { + local -rl AWSECURE_CLI_AUTOROTATE_STATE_FILE=~/.awsecure-cli-state-file-${AWS_PROFILE// /} + local -rl AWSECURE_CLI_AUTOROTATE_CHECK="${AWSECURE_CLI_AUTOROTATE_CHECK:-"daily"}" + + case "${AWSECURE_CLI_AUTOROTATE_CHECK// /}" in + daily) + local -r AWSECURE_CLI_STATE_FILE_OPTION="touch" + set +eo pipefail + local -r FIND_AWSECURE_CLI_AUTOROTATE_STATE_FILE_CMD="$(find ${AWSECURE_CLI_AUTOROTATE_STATE_FILE} -type f -ctime +24h 2> /dev/null | grep . > /dev/null 2>&1 ; echo $?)" + set -eo pipefail + if [[ ! -f ${AWSECURE_CLI_AUTOROTATE_STATE_FILE} ]]; then + awsecure_cli_autorotate_aws_access_keys + elif [[ ${FIND_AWSECURE_CLI_AUTOROTATE_STATE_FILE_CMD} -eq 0 ]]; then + set -eo pipefail + awsecure_cli_autorotate_aws_access_keys + else + awsecure_cli_log_info "AWS Access Keys autorotate was already checked in the last 24h" + fi + set -eo pipefail + ;; + on-reboot) + local -r AWSECURE_CLI_STATE_FILE_OPTION="mktemp" + [[ ! -f ${AWSECURE_CLI_AUTOROTATE_STATE_FILE} ]] && awsecure_cli_autorotate_aws_access_keys || awsecure_cli_log_info "AWS Access Keys autorotate was already checked since the last time you reboot the machine" + ;; + always) + local -r AWSECURE_CLI_STATE_FILE_OPTION="" + awsecure_cli_autorotate_aws_access_keys + ;; + *) + awsecure_cli_log_info "The option ${AWSECURE_CLI_AUTOROTATE_CHECK} is unknown" + ;; + esac +} +awsecure_cli_autorotate_check diff --git a/src/common/logging.shinc b/src/common/logging.shinc new file mode 100755 index 0000000..64bed78 --- /dev/null +++ b/src/common/logging.shinc @@ -0,0 +1,27 @@ +declare -lr AWSECURE_CLI_LOG_FILEPATH=/tmp/awsecure-cli.log.$(date +'%Y%m%d') +[[ ! -f "${AWSECURE_CLI_LOG_FILEPATH// /}" ]] && mktemp ${AWSECURE_CLI_LOG_FILEPATH} &> /dev/null +declare -l AWSECURE_CLI_MUTED="${AWSECURE_CLI_MUTED:-"false"}" +declare -l AWSECURE_CLI_LOG_TO_FILE="${AWSECURE_CLI_LOG_TO_FILE:-"false"}" + +function awsecure_cli_log_info() { + case "${AWSECURE_CLI_MUTED// /}-${AWSECURE_CLI_LOG_TO_FILE// /}" in + false-true) + echo "$(date +'%Y-%m-%d %T')Z INFO ${@}" ${AWSECURE_CLI_LOG_TO_FILE_CMD} | tee -a ${AWSECURE_CLI_LOG_FILEPATH} + ;; + false-false) + echo "$(date +'%Y-%m-%d %T')Z INFO ${@}" ${AWSECURE_CLI_LOG_TO_FILE_CMD} + ;; + esac +} + +function awsecure_cli_log_error() { + case "${AWSECURE_CLI_MUTED// /}-${AWSECURE_CLI_LOG_TO_FILE// /}" in + false-true) + echo "$(date +'%Y-%m-%d %T')Z ERROR ${@}" ${AWSECURE_CLI_LOG_TO_FILE_CMD} | tee -a ${AWSECURE_CLI_LOG_FILEPATH} + ;; + false-false) + echo "$(date +'%Y-%m-%d %T')Z ERROR ${@}" ${AWSECURE_CLI_LOG_TO_FILE_CMD} + ;; + esac + false +} diff --git a/src/common/wrapper.sh b/src/common/wrapper.sh new file mode 100755 index 0000000..a4224a8 --- /dev/null +++ b/src/common/wrapper.sh @@ -0,0 +1,53 @@ +#!/usr/bin/env bash + +if [[ $(type awsecure_cli_log_info 2> /dev/null) == "" || -z "${AWSECURE_CLI_SRC_DIRECTORY// /}" ]]; then + [[ -L ${0} ]] && declare -gr AWSECURE_CLI_SRC_DIRECTORY="$(realpath $(readlink ${0}) | xargs dirname)/../../src" || declare -gr AWSECURE_CLI_SRC_DIRECTORY="$(realpath ${0} | xargs dirname)/../../src" + . ${AWSECURE_CLI_SRC_DIRECTORY}/common/logging.shinc +fi + +declare -g AWSECURE_CLI_AWS_BIN_FILEPATH=${AWSECURE_CLI_AWS_BIN_FILEPATH:-~/.asdf/shims/aws} + +function awsecure_cli_get_aws_profile_set() { + if grep -i '\-\-profile=' <<< "${@}" &> /dev/null; then + local -r AWSECURE_CLI_AWS_PROFILE_SET="cli_equals" + elif grep -i '\-\-profile ' <<< "${@}" &> /dev/null; then + local -r AWSECURE_CLI_AWS_PROFILE_SET="cli_space" + elif [[ ! -z ${AWS_PROFILE// /} ]]; then + local -r AWSECURE_CLI_AWS_PROFILE_SET="var" + fi + + case "${AWSECURE_CLI_AWS_PROFILE_SET// /}" in + cli_space) + echo "${@}" | tr ' ' '\n' | grep -A1 '\-\-profile' | tail -1 + ;; + cli_equals) + echo "${@}" | tr ' ' '\n' | grep '\-\-profile' | sed -E 's/.*profile=(.*)/\1/' + ;; + var) + echo "${AWS_PROFILE}" + ;; + *) + declare -rxg AWS_PROFILE="default" + echo "${AWS_PROFILE}" + ;; + esac +} + +awsecure_cli_log_info "Getting the AWS profile in use" +declare -rxg AWS_PROFILE="$(awsecure_cli_get_aws_profile_set "${@}")" +awsecure_cli_log_info "The AWS profile in use is the ${AWS_PROFILE}" + +function awsecure_cli_autorotate_invoke() { + local -l AWSECURE_CLI_AUTOROTATE_AWS_ACCESS_KEYS="${AWSECURE_CLI_AUTOROTATE_AWS_ACCESS_KEYS:-"true"}" + case "${AWSECURE_CLI_AUTOROTATE_AWS_ACCESS_KEYS// /}" in + true) + . ${AWSECURE_CLI_SRC_DIRECTORY}/common/autorotate_aws_keys.sh + ;; + *) + awsecure_cli_log_info "The AWSECURE_CLI_AUTOROTATE_AWS_ACCESS_KEYS is not set to true. Skiping the AWS Access Keys autorotation" + ;; + esac +} +awsecure_cli_autorotate_invoke + +[[ -z "${AWSECURE_CLI_AUTOROTATE_ONLY// /}" || "${AWSECURE_CLI_AUTOROTATE_ONLY// /}" != "true" ]] && ${AWSECURE_CLI_AWS_BIN_FILEPATH} "${@}"