Merge pull request #5 from tazjin/feat/cloud-kms-secrets
Introduce secrets management via Google Cloud KMS
This commit is contained in:
commit
628cec3433
14 changed files with 129 additions and 15 deletions
1
.envrc
1
.envrc
|
@ -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"
|
||||||
|
|
13
default.nix
13
default.nix
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
1
infra/kubernetes/nixery/id_nixery.pub
Normal file
1
infra/kubernetes/nixery/id_nixery.pub
Normal file
|
@ -0,0 +1 @@
|
||||||
|
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCzBM6ydst77jDHNcTFWKD9Fw4SReqyNEEp2MtQBk2wt94U4yLp8MQIuNeOEn1GaDEX4RGCxqai/2UVF1w9ZNdU+v2fXcKWfkKuGQH2XcNfXor2cVNObd40H78++iZiv3nmM/NaEdkTbTBbi925cRy9u5FgItDgsJlyKNRglCb0fr6KlgpvWjL20dp/eeZ8a/gLniHK8PnEsgERQSvJnsyFpxxVhxtoUiyLWpXDl4npf/rQr0eRDf4Q5sN/nbTwksapPHfze8dKcaoA7A2NqT3bJ6DPGrwVCzGRtGw/SXJwFwmmtAl9O6BklpeReyiknSxc+KOtrjDW6O0r6yvymD5Z nixery
|
1
infra/kubernetes/nixery/known_hosts
Normal file
1
infra/kubernetes/nixery/known_hosts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==
|
19
infra/kubernetes/nixery/secrets.yaml
Normal file
19
infra/kubernetes/nixery/secrets.yaml
Normal 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
|
4
infra/kubernetes/nixery/ssh_config
Normal file
4
infra/kubernetes/nixery/ssh_config
Normal 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
BIN
secrets/nixery-gcs-json
Normal file
Binary file not shown.
BIN
secrets/nixery-gcs-pem
Normal file
BIN
secrets/nixery-gcs-pem
Normal file
Binary file not shown.
BIN
secrets/nixery-ssh-private
Normal file
BIN
secrets/nixery-ssh-private
Normal file
Binary file not shown.
|
@ -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
1
tools/bin/pass
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
__dispatch.sh
|
60
tools/kms_pass/default.nix
Normal file
60
tools/kms_pass/default.nix
Normal 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
|
||||||
|
''
|
Loading…
Reference in a new issue