Merge pull request #5 from tazjin/feat/cloud-kms-secrets

Introduce secrets management via Google Cloud KMS
This commit is contained in:
Vincent Ambo 2019-09-03 16:26:17 +01:00 committed by GitHub
commit 628cec3433
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 129 additions and 15 deletions

1
.envrc
View file

@ -4,3 +4,4 @@
export PATH="${PWD}/tools/bin:${PATH}" export PATH="${PWD}/tools/bin:${PATH}"
export NIX_PATH="nixpkgs=${PWD}/default.nix" export NIX_PATH="nixpkgs=${PWD}/default.nix"
export REPO_ROOT="${PWD}" export REPO_ROOT="${PWD}"
export SECRETS_DIR="${PWD}/secrets"

View file

@ -28,6 +28,13 @@ let
blog = self.callPackage ./services/tazblog {}; blog = self.callPackage ./services/tazblog {};
blog_cli = self.callPackage ./tools/blog_cli {}; blog_cli = self.callPackage ./tools/blog_cli {};
gemma = self.callPackage ./services/gemma {}; gemma = self.callPackage ./services/gemma {};
kms_pass = self.callPackage ./tools/kms_pass {
project = "tazjins-infrastructure";
region = "europe-north1";
keyring = "tazjins-keys";
key = "kontemplate-key";
};
}; };
# Third-party projects (either vendored or modified from nixpkgs) go here: # Third-party projects (either vendored or modified from nixpkgs) go here:
@ -49,6 +56,12 @@ let
sha256 = "1wn7nmb1cqfk2j91l3rwc6yhimfkzxprb8wknw5wi57yhq9m6lv1"; sha256 = "1wn7nmb1cqfk2j91l3rwc6yhimfkzxprb8wknw5wi57yhq9m6lv1";
}) {}).elmPackages; }) {}).elmPackages;
# Wrap kontemplate to inject the Cloud KMS version of 'pass'
kontemplate = self.writeShellScriptBin "kontemplate" ''
export PATH="${self.tazjin.kms_pass}/bin:$PATH"
exec ${super.kontemplate}/bin/kontemplate $@
'';
# One of Gemma's dependencies is missing in nixpkgs' Quicklisp # One of Gemma's dependencies is missing in nixpkgs' Quicklisp
# package set, it is overlaid locally here. # package set, it is overlaid locally here.
lispPackages = import ./third_party/common_lisp/quicklisp.nix { lispPackages = import ./third_party/common_lisp/quicklisp.nix {

View file

@ -27,24 +27,25 @@ resource "google_project_services" "primary" {
"bigquerystorage.googleapis.com", "bigquerystorage.googleapis.com",
"cloudapis.googleapis.com", "cloudapis.googleapis.com",
"clouddebugger.googleapis.com", "clouddebugger.googleapis.com",
"cloudkms.googleapis.com",
"cloudtrace.googleapis.com", "cloudtrace.googleapis.com",
"compute.googleapis.com",
"container.googleapis.com",
"containerregistry.googleapis.com",
"datastore.googleapis.com", "datastore.googleapis.com",
"dns.googleapis.com", "dns.googleapis.com",
"iam.googleapis.com",
"iamcredentials.googleapis.com",
"logging.googleapis.com", "logging.googleapis.com",
"monitoring.googleapis.com", "monitoring.googleapis.com",
"oslogin.googleapis.com",
"pubsub.googleapis.com",
"servicemanagement.googleapis.com", "servicemanagement.googleapis.com",
"serviceusage.googleapis.com", "serviceusage.googleapis.com",
"sourcerepo.googleapis.com",
"sql-component.googleapis.com", "sql-component.googleapis.com",
"storage-api.googleapis.com", "storage-api.googleapis.com",
"storage-component.googleapis.com", "storage-component.googleapis.com",
"container.googleapis.com",
"iam.googleapis.com",
"compute.googleapis.com",
"iamcredentials.googleapis.com",
"oslogin.googleapis.com",
"pubsub.googleapis.com",
"containerregistry.googleapis.com",
"sourcerepo.googleapis.com",
] ]
} }
@ -82,7 +83,21 @@ resource "google_service_account" "nixery" {
display_name = "Nixery service account" display_name = "Nixery service account"
} }
# Configure a git repository in which to store my monorepo # Configure Cloud KMS for secret encryption
resource "google_sourcerepo_repository" "monorepo" { resource "google_kms_key_ring" "tazjins_keys" {
name = "monorepo" name = "tazjins-keys"
location = "europe-north1"
lifecycle {
prevent_destroy = true
}
}
resource "google_kms_crypto_key" "kontemplate_key" {
name = "kontemplate-key"
key_ring = google_kms_key_ring.tazjins_keys.id
lifecycle {
prevent_destroy = true
}
} }

View file

@ -3,10 +3,6 @@
# The service via which Nixery is exposed has a private DNS entry # The service via which Nixery is exposed has a private DNS entry
# pointing to it, which makes it possible to resolve `nixery.local` # pointing to it, which makes it possible to resolve `nixery.local`
# in-cluster without things getting nasty. # in-cluster without things getting nasty.
#
# The 'nixery-keys' secret was configured manually using a created
# service account key. This does not use metadata-based authentication
# due to the requirement for having an actual PEM-key to sign with.
--- ---
apiVersion: apps/v1 apiVersion: apps/v1
kind: Deployment kind: Deployment

View file

@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCzBM6ydst77jDHNcTFWKD9Fw4SReqyNEEp2MtQBk2wt94U4yLp8MQIuNeOEn1GaDEX4RGCxqai/2UVF1w9ZNdU+v2fXcKWfkKuGQH2XcNfXor2cVNObd40H78++iZiv3nmM/NaEdkTbTBbi925cRy9u5FgItDgsJlyKNRglCb0fr6KlgpvWjL20dp/eeZ8a/gLniHK8PnEsgERQSvJnsyFpxxVhxtoUiyLWpXDl4npf/rQr0eRDf4Q5sN/nbTwksapPHfze8dKcaoA7A2NqT3bJ6DPGrwVCzGRtGw/SXJwFwmmtAl9O6BklpeReyiknSxc+KOtrjDW6O0r6yvymD5Z nixery

View file

@ -0,0 +1 @@
github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==

View file

@ -0,0 +1,19 @@
# The secrets below are encrypted using keys stored in Cloud KMS and
# templated in by kontemplate when deploying.
#
# Not all of the values are actually secret (see the matching)
---
apiVersion: v1
data:
gcs-key.json: {{ passLookup "nixery-gcs-json" | b64enc }}
gcs-key.pem: {{ passLookup "nixery-gcs-pem" | b64enc }}
id_nixery: {{ passLookup "nixery-ssh-private" | b64enc }}
id_nixery.pub: {{ insertFile "id_nixery.pub" | b64enc }}
known_hosts: {{ insertFile "known_hosts" | b64enc }}
ssh_config: {{ insertFile "ssh_config" | b64enc }}
kind: Secret
metadata:
creationTimestamp: null
name: nixery-secrets
selfLink: /api/v1/namespaces/kube-public/secrets/nixery-secrets
type: Opaque

View file

@ -0,0 +1,4 @@
Match host *
User tazjin@google.com
IdentityFile /var/nixery/id_nixery
UserKnownHostsFile /var/nixery/known_hosts

BIN
secrets/nixery-gcs-json Normal file

Binary file not shown.

BIN
secrets/nixery-gcs-pem Normal file

Binary file not shown.

BIN
secrets/nixery-ssh-private Normal file

Binary file not shown.

View file

@ -22,6 +22,9 @@ case "${TARGET_TOOL}" in
stern) stern)
attr="stern" attr="stern"
;; ;;
pass)
attr="tazjin.kms_pass"
;;
*) *)
echo "The tool '${TARGET_TOOL}' is currently not installed in this repository." echo "The tool '${TARGET_TOOL}' is currently not installed in this repository."
exit 1 exit 1

1
tools/bin/pass Symbolic link
View file

@ -0,0 +1 @@
__dispatch.sh

View file

@ -0,0 +1,60 @@
# This tool mimics a subset of the interface of 'pass', but uses
# Google Cloud KMS for encryption.
#
# It is intended to be compatible with how 'kontemplate' invokes
# 'pass.'
#
# Only the 'show' and 'insert' commands are supported.
{ google-cloud-sdk, tree, writeShellScriptBin
, project, region, keyring, key }:
writeShellScriptBin "pass" ''
set -eo pipefail
CMD="$1"
readonly SECRET=$2
readonly SECRET_PATH="$SECRETS_DIR/$SECRET"
function secret_check {
if [[ -z $SECRET ]]; then
echo 'Secret must be specified'
exit 1
fi
}
if [[ -z $CMD ]]; then
CMD="ls"
fi
case "$CMD" in
ls)
${tree}/bin/tree $SECRETS_DIR
;;
show)
secret_check
${google-cloud-sdk}/bin/gcloud kms decrypt \
--project ${project} \
--location ${region} \
--keyring ${keyring} \
--key ${key} \
--ciphertext-file $SECRET_PATH \
--plaintext-file -
;;
insert)
secret_check
${google-cloud-sdk}/bin/gcloud kms encrypt \
--project ${project} \
--location ${region} \
--keyring ${keyring} \
--key ${key} \
--ciphertext-file $SECRET_PATH \
--plaintext-file -
echo "Inserted secret '$SECRET'"
;;
*)
echo "Usage: pass show/insert <secret>"
exit 1
;;
esac
''