From 34bed60a89e6db25eb61e96fcf0205ae28c670b5 Mon Sep 17 00:00:00 2001 From: volodymyrZotov Date: Thu, 11 Aug 2022 18:08:26 +0300 Subject: [PATCH] use op read to retrive item values --- entrypoint.sh | 218 ++++++++++++++------------------------------------ 1 file changed, 58 insertions(+), 160 deletions(-) diff --git a/entrypoint.sh b/entrypoint.sh index 8caf9d9..592fbfe 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -38,171 +38,38 @@ install_op_cli() { unzip -od /usr/local/bin/ op.zip && rm op.zip } -# Load environment variables using op cli. Iterate over them to find 1Password references, load the secret values, -# and make them available as environment variables in the next steps. -extract_from_op_env() { +populating_secret() { + ref=$(printenv $1) + + echo "Populating variable: $1" + secret_value=$(op read $ref) + echo "Secret value: $secret_value" + + if [ -z "$secret_value" ]; then + echo "Could not find or access secret $ref" + exit 1 + fi + + # Register a mask for the secret to prevent accidental log exposure. + # To support multiline secrets, escape percent signs and add a mask per line. + escaped_mask_value=$(echo "$secret_value" | sed -e 's/%/%25/g') IFS=$'\n' - for env_var in $(op env ls); do - ref=$(printenv $env_var) - - echo "Populating variable: $env_var" - secret_value=$(op read $ref) - - if [ -z "$secret_value" ]; then - echo "Could not find or access secret $ref" - exit 1 + for line in $escaped_mask_value; do + if [ "${#line}" -lt 3 ]; then + # To avoid false positives and unreadable logs, omit mask for lines that are too short. + continue fi - - # Register a mask for the secret to prevent accidental log exposure. - # To support multiline secrets, escape percent signs and add a mask per line. - escaped_mask_value=$(echo "$secret_value" | sed -e 's/%/%25/g') - IFS=$'\n' - for line in $escaped_mask_value; do - if [ "${#line}" -lt 3 ]; then - # To avoid false positives and unreadable logs, omit mask for lines that are too short. - continue - fi - echo "::add-mask::$line" - done - unset IFS - - if [ "$INPUT_EXPORT_ENV" == "true" ]; then - # To support multiline secrets, we'll use the heredoc syntax to populate the environment variables. - # As the heredoc identifier, we'll use a randomly generated 64-character string, - # so that collisions are practically impossible. - random_heredoc_identifier=$(openssl rand -hex 16) - - { - # Populate env var, using heredoc syntax with generated identifier - echo "$env_var<<${random_heredoc_identifier}" - echo "$secret_value" - echo "${random_heredoc_identifier}" - } >> $GITHUB_ENV - - else - # Prepare the secret_value to be outputed properly (especially multiline secrets) - secret_value=$(echo "$secret_value" | awk -v ORS='%0A' '1') - - echo "::set-output name=$env_var::$secret_value" - fi - - managed_variables+=("$env_var") - + echo "::add-mask::$line" done unset IFS -} - -# Load environment variables using connect service. Iterate over hem to find 1Password references, load the secret values, -# and make them available as environment variables in the next steps. -extract_from_connect() { - curl_headers=(-H "Content-Type: application/json" -H "Authorization: Bearer $OP_CONNECT_TOKEN") - IFS=$'\n' - - for possible_ref in $(printenv | grep "=op://" | grep -v "^#"); do - env_var=$(echo "$possible_ref" | cut -d '=' -f1) - ref=$(printenv $env_var) - - if [[ ! $ref == "op://"* ]]; then - echo "Not really a reference: $ref" - continue - fi - - path=$(echo $ref | sed -e "s/^op:\/\///") - if [ $(echo "$path" | tr -cd '/' | wc -c) -lt 2 ]; then - echo "Expected path to be in format op:///[/
]/: $ref" - continue - fi - - echo "Populating variable: $env_var" - - vault="" - item="" - section="" - field="" - i=0 - IFS="/" - for component in $path; do - ((i+=1)) - case "$i" in - 1) vault=$component ;; - 2) item=$component ;; - 3) section=$component ;; - 4) field=$component ;; - esac - done - unset IFS - - # If field is not set, it may have wrongfully been interpreted as the section. - if [ -z "$field" ]; then - field="$section" - section="" - fi - - if [[ $(echo -n $(echo $vault | grep "^[a-z0-9]*$") | wc -c) -ne 26 ]]; then - echo "Getting vault ID from vault name: $vault" - vault=$(curl -sSf "${curl_headers[@]}" "$OP_CONNECT_HOST/v1/vaults?filter=name%20eq%20%22$vault%22" | jq -r '.[0] | .id') - if [ -z "$vault" ]; then - echo "Could not find vault ID for vault: $vault" - exit 1 - fi - fi - - if [[ $(echo -n $(echo $item | grep "^[a-z0-9]*$") | wc -c) -ne 26 ]]; then - echo "Getting item ID from vault $vault..." - item=$(curl -sSf "${curl_headers[@]}" "$OP_CONNECT_HOST/v1/vaults/$vault/items?filter=title%20eq%20%22$item%22" | jq -r '.[0] | .id') - if [ -z "$item" ]; then - echo "Could not find item ID for item: $item" - exit 1 - fi - fi - - echo "Loading item $item from vault $vault..." - item_json=$(curl -sSf "${curl_headers[@]}" "$OP_CONNECT_HOST/v1/vaults/$vault/items/$item") - - jq_field_selector=".id == \"$field\" or .label == \"$field\"" - jq_section_selector=".section == null" - - # If the reference contains a section, edit the jq selector to take that into account. - if [ -n "$section" ]; then - echo "Looking for section: $section" - section_id=$(echo "$item_json" | jq -r ".sections[] | select(.id == \"$section\" or .label == \"$section\") | .id") - jq_section_selector=".section.id == \"$section_id\"" - fi - - jq_secret_selector="$jq_section_selector and ($jq_field_selector)" - - echo "Looking for field: $field" - secret_field_json=$(echo "$item_json" | jq -r "first(.fields[] | select($jq_secret_selector))") - - field_type=$(echo "$secret_field_json" | jq -r '.type') - field_purpose=$(echo "$secret_field_json" | jq -r '.purpose') - secret_value=$(echo "$secret_field_json" | jq -r '.value') - - if [ -z "$secret_value" ]; then - echo "Could not find or access secret $ref" - exit 1 - fi - - # If the field is marked as concealed or is a note, register a mask - # for the secret to prevent accidental log exposure. - if [ "$field_type" == "CONCEALED" ] || [ "$field_purpose" == "NOTES" ]; then - # To support multiline secrets, escape percent signs and add a mask per line. - escaped_mask_value=$(echo "$secret_value" | sed -e 's/%/%25/g') - IFS=$'\n' - for line in $escaped_mask_value; do - if [ "${#line}" -lt 3 ]; then - # To avoid false positives and unreadable logs, omit mask for lines that are too short. - continue - fi - echo "::add-mask::$line" - done - unset IFS - fi + if [ "$INPUT_EXPORT_ENV" == "true" ]; then + echo "inside if" # To support multiline secrets, we'll use the heredoc syntax to populate the environment variables. # As the heredoc identifier, we'll use a randomly generated 64-character string, # so that collisions are practically impossible. random_heredoc_identifier=$(openssl rand -hex 16) + echo "random_heredoc_identifier: $random_heredoc_identifier" { # Populate env var, using heredoc syntax with generated identifier @@ -210,12 +77,43 @@ extract_from_connect() { echo "$secret_value" echo "${random_heredoc_identifier}" } >> $GITHUB_ENV + echo "GITHUB_ENV: $(cat $GITHUB_ENV)" - managed_variables+=("$env_var") + else + echo "inside else" + # Prepare the secret_value to be outputed properly (especially multiline secrets) + secret_value=$(echo "$secret_value" | awk -v ORS='%0A' '1') + + echo "::set-output name=$env_var::$secret_value" + fi + + echo "env_var: $env_var" + echo "secret_value: $secret_value" + managed_variables+=("$env_var") +} + +# Load environment variables using op cli. Iterate over them to find 1Password references, load the secret values, +# and make them available as environment variables in the next steps. +extract_using_service_account() { + IFS=$'\n' + for env_var in $(op env ls); do + populating_secret $env_var done unset IFS } +# Load environment variables using connect service. Iterate over hem to find 1Password references, load the secret values, +# and make them available as environment variables in the next steps. +extract_using_connec() { + curl_headers=(-H "Content-Type: application/json" -H "Authorization: Bearer $OP_CONNECT_TOKEN") + IFS=$'\n' + + for possible_ref in $(printenv | grep "=op://" | grep -v "^#"); do + env_var=$(echo "$possible_ref" | cut -d '=' -f1) + populating_secret $env_var + done +} + read -r -a managed_variables <<< "$(printenv $managed_variables_var)" if [ -z "$OP_CONNECT_TOKEN" ] || [ -z "$OP_CONNECT_HOST" ]; then @@ -230,12 +128,12 @@ fi printf "Authenticated with %s \n" $auth_type unset_prev_secrets +install_op_cli if [ "$auth_type" == "$SERVICE_ACCOUNT" ]; then - install_op_cli - extract_from_op_env + extract_using_service_account elif [ "$auth_type" == "$CONNECT" ]; then - extract_from_connect + extract_using_connect fi # Add extra env var that lists which secrets are managed by 1Password so that in a later step