From f9844a8080646b9ac9d4bf93cc871fea666bf96a Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone <exarkun@twistedmatrix.com> Date: Fri, 25 Jun 2021 14:21:14 -0400 Subject: [PATCH] Parameterize more things --- .gitlab-ci.yml | 18 +++++++++++++- ci-tools/deploy-to-staging | 43 +++++++++++++++++++++++---------- nixos/modules/deployment.nix | 28 +++++++++++++++++++-- nixos/modules/update-deployment | 4 ++- 4 files changed, 76 insertions(+), 17 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 4e68fd45..b2e33fac 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -46,7 +46,23 @@ deploy-to-staging: name: "staging" url: "https://privatestorage-staging.com/" script: - - "./ci-tools/deploy-to-staging" + # Copy the deploy key from the environment to a file so we can actually + # tell ssh to use it. + - | + # The environment variable is configured with GitLab using Terraform so + # we can retain some bare minimum level of confidentiality. + echo "${PRIVATESTORAGEIO_STAGING_SSH_DEPLOY_KEY}" > "${PWD}"/deploy_key + + # Update the deployment + - | + ./ci-tools/deploy-to-staging "${PWD}"/deploy_key ${name} + + # Remove the key from the filesystem to less the chance of unintentional + # disclosure. Overall our handling of this key is still not *particulary* + # safe or secure but that's why the key is only authorized to perform a + # single very specific operation. + - | + rm -v "${PWD}"/deploy_key deploy-to-production: stage: "deploy" diff --git a/ci-tools/deploy-to-staging b/ci-tools/deploy-to-staging index 47cdafa4..1bcaae6a 100644 --- a/ci-tools/deploy-to-staging +++ b/ci-tools/deploy-to-staging @@ -3,25 +3,42 @@ set -euxo pipefail -GRIDNAME="staging" +DEPLOY_KEY=$1 +shift + +GRIDNAME=$1 +shift # Tell one node to update itself. -update_yourself() { +update_one_node() { + deploy_key=$1 + shift + node=$1 shift - ssh -i deploy_key "${node}" + ssh -i "${deploy_key}" "deployment@${node}" } -# Find the names of all hosts that belong to this grid. This list includes -# one extra string, "network", which is morph configuration stuff and we need -# to filter out later. -NODES=$(nix eval --json '(builtins.attrNames (import ./morph/${GRIDNAME}/grid.nix))') +update_grid_nodes() { + deploy_key=$1 + shift -# Tell every system in the network to update itself. -for node in ${NODES}; do - if [ "${node}" = "network" ]; then - continue + gridname=$1 + shift + + # Find the names of all hosts that belong to this grid. This list includes + # one extra string, "network", which is morph configuration stuff and we need + # to filter out later. + nodes=$(nix eval --json '(builtins.attrNames (import ./morph/${gridname}/grid.nix))') + + # Tell every system in the network to update itself. + for node in ${nodes}; do + if [ "${node}" = "network" ]; then + continue + fi + update_one_node "${deploy_key}" "${node}" fi - update_yourself "${node}" -fi +} + +update_grid_nodes "${DEPLOY_KEY}" "${GRIDNAME}" diff --git a/nixos/modules/deployment.nix b/nixos/modules/deployment.nix index a12ff054..592d373f 100644 --- a/nixos/modules/deployment.nix +++ b/nixos/modules/deployment.nix @@ -1,17 +1,41 @@ # A NixOS module which enables remotely-triggered deployment updates. { config, ... }: let + # A handy alias for our part of the configuration. + cfg = config.services.private-storage.deployment; + # Compute an authorized_keys line that allows the holder of a certain key to # execute a certain command *only*. - restrictedKey = pubKey: command: "restrict,command=\"${command}\" ${pubKey}"; + restrictedKey = + { authorizedKey, command, gridName }: + "restrict,command=\"${command} ${gridName}\" ${authorizedKey}"; in { options = { + services.private-storage.deployment.authorizedKey = { + type = lib.types.str; + example = lib.literalExample '' + ssh-ed25519 AAAAC3N... + ''; + description = '' + The SSH public key to authorize to trigger a deployment update. + ''; + }; + services.private-storage.deployment.gridName = { + type = lib.types.str; + example = lib.literalExample "staging"; + description = '' + The name of the grid configuration to use to update this deployment. + ''; + }; }; config = { users.users.deployment = { openssh.authorizedKeys.keys = [ - restrictedKey cfg.deployKey ./update-deployment + (restrictedKey { + inherit (cfg) authorizedKey gridName; + command = ./update-deployment; + }) ]; }; }; diff --git a/nixos/modules/update-deployment b/nixos/modules/update-deployment index 7685423e..dd988031 100644 --- a/nixos/modules/update-deployment +++ b/nixos/modules/update-deployment @@ -3,8 +3,10 @@ set -euxo pipefail +GRIDNAME=$1 +shift + CHECKOUT="/run/user/$(id --user)/PrivateStorageio" -GRIDNAME="staging" REPO="https://whetstone.privatestorage.io/privatestorage/PrivateStorageio.git" if [ -e "${CHECKOUT}" ]; then -- GitLab