From 25801cd4e9e59c309ebe30d9c51fb9be4c4a263b Mon Sep 17 00:00:00 2001 From: Rafal Jendraszak Date: Tue, 7 Feb 2023 11:37:24 +0100 Subject: [PATCH 1/5] Support for puppet using gcloud CLI --- lib/hiera/backend/eyaml/encryptors/gkms.rb | 52 +++++-------------- .../backend/eyaml/encryptors/gkms/version.rb | 2 +- 2 files changed, 13 insertions(+), 41 deletions(-) diff --git a/lib/hiera/backend/eyaml/encryptors/gkms.rb b/lib/hiera/backend/eyaml/encryptors/gkms.rb index 6af58ed..340d16a 100644 --- a/lib/hiera/backend/eyaml/encryptors/gkms.rb +++ b/lib/hiera/backend/eyaml/encryptors/gkms.rb @@ -1,12 +1,5 @@ # frozen_string_literal: true -begin - require 'google/cloud/kms' - require 'google/cloud/kms/v1' -rescue LoadError - raise StandardError, 'hiera-eyaml-gkms requires the google-cloud-kms gem' -end - require 'hiera/backend/eyaml/encryptor' require 'hiera/backend/eyaml/utils' require 'hiera/backend/eyaml/options' @@ -49,46 +42,25 @@ class Gkms < Encryptor } } - def self.kms_client - auth_type = option :auth_type - - if auth_type == 'serviceaccount' - credentials = option :credentials - raise StandardError, 'gkms_credentials is not defined' unless credentials - - Google::Cloud::Kms.configure do |config| - config.credentials = credentials - config.timeout = 10.0 - end - else - ENV['GOOGLE_AUTH_SUPPRESS_CREDENTIALS_WARNINGS'] = '1' - end - - ::Google::Cloud::Kms.key_management_service - end - - def self.key_path + def self.encrypt(plaintext) + enc_plaintext = Base64.encode64(plaintext) project = option :project location = option :location key_ring = option :keyring crypto_key = option :crypto_key - - raise StandardError, 'gkms_project is not defined' unless project - raise StandardError, 'gkms_keyring is not defined' unless key_ring - raise StandardError, 'gkms_crypto_key is not defined' unless crypto_key - - kms_client.crypto_key_path project: project, - location: location, - key_ring: key_ring, - crypto_key: crypto_key - end - - def self.encrypt(plaintext) - kms_client.encrypt(name: key_path, plaintext: plaintext).ciphertext + encrypted = `echo "#{enc_plaintext}" | gcloud kms encrypt --location #{location} --keyring #{key_ring} --key #{crypto_key} --project #{project} --plaintext-file - --ciphertext-file -` end def self.decrypt(ciphertext) - kms_client.decrypt(name: key_path, ciphertext: ciphertext).plaintext + project = option :project + location = option :location + key_ring = option :keyring + crypto_key = option :crypto_key + + decryptor = Encryptor.find "Gkms" + ciphertext = decryptor.encode(ciphertext) + shell_response = `echo #{ciphertext} | base64 -d | gcloud kms decrypt --location #{location} --keyring #{key_ring} --key #{crypto_key} --project #{project} --plaintext-file - --ciphertext-file -` + Base64.decode64(shell_response) end end end diff --git a/lib/hiera/backend/eyaml/encryptors/gkms/version.rb b/lib/hiera/backend/eyaml/encryptors/gkms/version.rb index f0a4756..7800df0 100644 --- a/lib/hiera/backend/eyaml/encryptors/gkms/version.rb +++ b/lib/hiera/backend/eyaml/encryptors/gkms/version.rb @@ -5,7 +5,7 @@ module Backend module Eyaml module Encryptors module GkmsVersion - VERSION = '0.2.0' + VERSION = '0.2.1' end end end From df237e299c957b60b1d5cf83d00dc9b7af6c643c Mon Sep 17 00:00:00 2001 From: Rafal Jendraszak Date: Sat, 25 Mar 2023 15:47:42 +0100 Subject: [PATCH 2/5] Add use_gcloud_cli option --- lib/hiera/backend/eyaml/encryptors/gkms.rb | 73 ++++++++++++++++++---- 1 file changed, 62 insertions(+), 11 deletions(-) diff --git a/lib/hiera/backend/eyaml/encryptors/gkms.rb b/lib/hiera/backend/eyaml/encryptors/gkms.rb index 340d16a..58fd2dc 100644 --- a/lib/hiera/backend/eyaml/encryptors/gkms.rb +++ b/lib/hiera/backend/eyaml/encryptors/gkms.rb @@ -4,6 +4,8 @@ require 'hiera/backend/eyaml/utils' require 'hiera/backend/eyaml/options' require 'hiera/backend/eyaml/encryptors/gkms/version' +require 'google/cloud/kms' +require 'google/cloud/kms/v1' class Hiera module Backend @@ -39,28 +41,77 @@ class Gkms < Encryptor credentials: { desc: 'GCP Service Account credentials', type: :string + }, + use_gcloud_cli: { + desc: 'Use gcloud CLI to encrypt/decrypt secrets', + type: :bool, + default: false } } - def self.encrypt(plaintext) - enc_plaintext = Base64.encode64(plaintext) + def self.kms_client + auth_type = option :auth_type + + if auth_type == 'serviceaccount' + credentials = option :credentials + raise StandardError, 'gkms_credentials is not defined' unless credentials + + Google::Cloud::Kms.configure do |config| + config.credentials = credentials + config.timeout = 10.0 + end + else + ENV['GOOGLE_AUTH_SUPPRESS_CREDENTIALS_WARNINGS'] = '1' + end + + ::Google::Cloud::Kms.key_management_service + end + + def self.key_path project = option :project location = option :location key_ring = option :keyring crypto_key = option :crypto_key - encrypted = `echo "#{enc_plaintext}" | gcloud kms encrypt --location #{location} --keyring #{key_ring} --key #{crypto_key} --project #{project} --plaintext-file - --ciphertext-file -` + + raise StandardError, 'gkms_project is not defined' unless project + raise StandardError, 'gkms_keyring is not defined' unless key_ring + raise StandardError, 'gkms_crypto_key is not defined' unless crypto_key + + kms_client.crypto_key_path project: project, + location: location, + key_ring: key_ring, + crypto_key: crypto_key + end + + def self.encrypt(plaintext) + use_gcloud_cli = option :use_gcloud_cli + if use_gcloud_cli + enc_plaintext = Base64.encode64(plaintext) + project = option :project + location = option :location + key_ring = option :keyring + crypto_key = option :crypto_key + encrypted = `echo "#{enc_plaintext}" | gcloud kms encrypt --location #{location} --keyring #{key_ring} --key #{crypto_key} --project #{project} --plaintext-file - --ciphertext-file -` + else + kms_client.encrypt(name: key_path, plaintext: plaintext).ciphertext + end end def self.decrypt(ciphertext) - project = option :project - location = option :location - key_ring = option :keyring - crypto_key = option :crypto_key + use_gcloud_cli = option :use_gcloud_cli + if use_gcloud_cli + project = option :project + location = option :location + key_ring = option :keyring + crypto_key = option :crypto_key - decryptor = Encryptor.find "Gkms" - ciphertext = decryptor.encode(ciphertext) - shell_response = `echo #{ciphertext} | base64 -d | gcloud kms decrypt --location #{location} --keyring #{key_ring} --key #{crypto_key} --project #{project} --plaintext-file - --ciphertext-file -` - Base64.decode64(shell_response) + decryptor = Encryptor.find 'Gkms' + ciphertext = decryptor.encode(ciphertext) + shell_response = `echo #{ciphertext} | base64 -d | gcloud kms decrypt --location #{location} --keyring #{key_ring} --key #{crypto_key} --project #{project} --plaintext-file - --ciphertext-file -` + Base64.decode64(shell_response) + else + kms_client.decrypt(name: key_path, ciphertext: ciphertext).plaintext + end end end end From 83770cc69df66f665161561b64bb2c26345b5312 Mon Sep 17 00:00:00 2001 From: Rafal Jendraszak Date: Sat, 25 Mar 2023 15:49:37 +0100 Subject: [PATCH 3/5] Fix Rubocop issues --- lib/hiera/backend/eyaml/encryptors/gkms.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/hiera/backend/eyaml/encryptors/gkms.rb b/lib/hiera/backend/eyaml/encryptors/gkms.rb index 58fd2dc..7f6b5d9 100644 --- a/lib/hiera/backend/eyaml/encryptors/gkms.rb +++ b/lib/hiera/backend/eyaml/encryptors/gkms.rb @@ -91,7 +91,7 @@ def self.encrypt(plaintext) location = option :location key_ring = option :keyring crypto_key = option :crypto_key - encrypted = `echo "#{enc_plaintext}" | gcloud kms encrypt --location #{location} --keyring #{key_ring} --key #{crypto_key} --project #{project} --plaintext-file - --ciphertext-file -` + `echo "#{enc_plaintext}" | gcloud kms encrypt --location #{location} --keyring #{key_ring} --key #{crypto_key} --project #{project} --plaintext-file - --ciphertext-file -` else kms_client.encrypt(name: key_path, plaintext: plaintext).ciphertext end @@ -107,8 +107,8 @@ def self.decrypt(ciphertext) decryptor = Encryptor.find 'Gkms' ciphertext = decryptor.encode(ciphertext) - shell_response = `echo #{ciphertext} | base64 -d | gcloud kms decrypt --location #{location} --keyring #{key_ring} --key #{crypto_key} --project #{project} --plaintext-file - --ciphertext-file -` - Base64.decode64(shell_response) + response = `echo #{ciphertext} | base64 -d | gcloud kms decrypt --location #{location} --keyring #{key_ring} --key #{crypto_key} --project #{project} --plaintext-file - --ciphertext-file -` + Base64.decode64(response) else kms_client.decrypt(name: key_path, ciphertext: ciphertext).plaintext end From 6143b7ece831967ad1b8e300011ba4b6564a8690 Mon Sep 17 00:00:00 2001 From: Rafal Jendraszak Date: Sat, 25 Mar 2023 15:51:55 +0100 Subject: [PATCH 4/5] Fix Rubocop issues --- lib/hiera/backend/eyaml/encryptors/gkms.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/hiera/backend/eyaml/encryptors/gkms.rb b/lib/hiera/backend/eyaml/encryptors/gkms.rb index 7f6b5d9..5319394 100644 --- a/lib/hiera/backend/eyaml/encryptors/gkms.rb +++ b/lib/hiera/backend/eyaml/encryptors/gkms.rb @@ -107,8 +107,8 @@ def self.decrypt(ciphertext) decryptor = Encryptor.find 'Gkms' ciphertext = decryptor.encode(ciphertext) - response = `echo #{ciphertext} | base64 -d | gcloud kms decrypt --location #{location} --keyring #{key_ring} --key #{crypto_key} --project #{project} --plaintext-file - --ciphertext-file -` - Base64.decode64(response) + resp = `echo #{ciphertext} | base64 -d | gcloud kms decrypt --location #{location} --keyring #{key_ring} --key #{crypto_key} --project #{project} --plaintext-file - --ciphertext-file -` + Base64.decode64(resp) else kms_client.decrypt(name: key_path, ciphertext: ciphertext).plaintext end From 7b2e2766122831cebb2a0899cf494e2d273e393b Mon Sep 17 00:00:00 2001 From: Rafal Jendraszak Date: Sat, 25 Mar 2023 16:11:11 +0100 Subject: [PATCH 5/5] Fix testing --- .github/workflows/test.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3c99012..aa1c425 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -70,12 +70,14 @@ jobs: --gkms-location="${GCP_LOCATION}" \ --gkms-keyring="${GCP_KEYRING}" \ --gkms-crypto-key="${GCP_CRYPTO_KEY}" \ + --gkms-auth-type="serviceaccount" \ --gkms-credentials=./credentials.json \ -n gkms -o string -s "${GITHUB_SHA}" > ./cipher.txt bundle exec eyaml decrypt --gkms-project="${GCP_PROJECT}" \ --gkms-location="${GCP_LOCATION}" \ --gkms-keyring="${GCP_KEYRING}" \ --gkms-crypto-key="${GCP_CRYPTO_KEY}" \ + --gkms-auth-type="serviceaccount" \ --gkms-credentials=./credentials.json \ -n gkms -f ./cipher.txt > ./plain.txt echo "Input: ${GITHUB_SHA}"