diff --git a/puppet/zulip_ops/files/install-ssh-keys b/puppet/zulip_ops/files/install-ssh-keys new file mode 100644 index 0000000000..fa13f66d80 --- /dev/null +++ b/puppet/zulip_ops/files/install-ssh-keys @@ -0,0 +1,39 @@ +#!/usr/bin/env bash +set -eu + +username="$1" +ssh_secret_name="$2" + +homedir="$(getent passwd "$username" | cut -d: -f6)" +sshdir="$homedir/.ssh" + +umask 077 +workdir=$(mktemp -d) +chown "$username:$username" "$workdir" +cleanup() { ls -al "$workdir" && rm -rf "$workdir"; } +trap cleanup EXIT + +umask 033 + +keydata="$(/srv/zulip-aws-tools/bin/aws --output text \ + secretsmanager get-secret-value \ + --secret-id "$ssh_secret_name" \ + --query SecretString)" +for keyfile in $(jq -r 'keys[]' <<<"$keydata"); do + touch "$workdir/$keyfile" + if [[ "$keyfile" != *".pub" ]]; then + chmod 600 "$workdir/$keyfile" + fi + jq -r ".[\"$keyfile\"]" <<<"$keydata" | base64 -d >"$workdir/$keyfile" + chown "$username:$username" "$workdir/$keyfile" +done + +if [ "$#" -gt 2 ]; then + diff -rN -x config -x authorized_keys -x known_hosts \ + "$workdir/" "$sshdir/" + exit 0 +fi + +rsync -rv --delete \ + --exclude config --exclude authorized_keys --exclude known_hosts \ + "$workdir/" "$sshdir/" diff --git a/puppet/zulip_ops/manifests/aws_tools.pp b/puppet/zulip_ops/manifests/aws_tools.pp index 908db24d20..31e12d8570 100644 --- a/puppet/zulip_ops/manifests/aws_tools.pp +++ b/puppet/zulip_ops/manifests/aws_tools.pp @@ -68,4 +68,14 @@ class zulip_ops::aws_tools { group => 'root', content => template('zulip_ops/dotfiles/aws_config.erb'), } + + # Pull keys from AWS secretsmanager + file { '/usr/local/bin/install-ssh-keys': + ensure => file, + require => File['/root/.aws/config'], + mode => '0755', + owner => 'root', + group => 'root', + source => 'puppet:///modules/zulip_ops/install-ssh-keys', + } } diff --git a/puppet/zulip_ops/manifests/profile/base.pp b/puppet/zulip_ops/manifests/profile/base.pp index b612b07779..78419ab234 100644 --- a/puppet/zulip_ops/manifests/profile/base.pp +++ b/puppet/zulip_ops/manifests/profile/base.pp @@ -61,9 +61,14 @@ class zulip_ops::profile::base { } user { 'root': } - zulip_ops::user_dotfiles { 'root': home => '/root' } + zulip_ops::user_dotfiles { 'root': + home => '/root', + keys => 'common', + } - zulip_ops::user_dotfiles { 'zulip': } + zulip_ops::user_dotfiles { 'zulip': + keys => 'common', + } file { '/etc/pam.d/common-session': ensure => file, diff --git a/puppet/zulip_ops/manifests/profile/nagios.pp b/puppet/zulip_ops/manifests/profile/nagios.pp index 714ef2cf66..336a9ff182 100644 --- a/puppet/zulip_ops/manifests/profile/nagios.pp +++ b/puppet/zulip_ops/manifests/profile/nagios.pp @@ -2,6 +2,7 @@ class zulip_ops::profile::nagios { include zulip_ops::profile::base include zulip_ops::apache + zulip::ssh_keys { 'nagios': } $nagios_packages = [# Packages needed for Nagios 'nagios4', # For sending outgoing email diff --git a/puppet/zulip_ops/manifests/ssh_keys.pp b/puppet/zulip_ops/manifests/ssh_keys.pp new file mode 100644 index 0000000000..c3a75adca3 --- /dev/null +++ b/puppet/zulip_ops/manifests/ssh_keys.pp @@ -0,0 +1,15 @@ +define zulip_ops::ssh_keys( + $keys = true, +) { + $user = $name + if $keys == true { + $keypath = "prod/ssh/keys/${user}" + } else { + $keypath = "prod/ssh/keys/${keys}" + } + exec { "ssh_keys ${user}": + require => File['/usr/local/bin/install-ssh-keys'], + command => "/usr/local/bin/install-ssh-keys ${user} ${keypath}", + unless => "[ -f /usr/local/bin/install-ssh-keys ] && /usr/local/bin/install-ssh-keys ${user} ${keypath} check", + } +} diff --git a/puppet/zulip_ops/manifests/user_dotfiles.pp b/puppet/zulip_ops/manifests/user_dotfiles.pp index ac4ade41e8..515c3437d1 100644 --- a/puppet/zulip_ops/manifests/user_dotfiles.pp +++ b/puppet/zulip_ops/manifests/user_dotfiles.pp @@ -1,5 +1,6 @@ define zulip_ops::user_dotfiles ( $home = '', + $keys = false, ) { $user = $name @@ -37,4 +38,11 @@ define zulip_ops::user_dotfiles ( mode => '0644', content => '', } + + if $keys != false { + zulip_ops::ssh_keys{ $user: + keys => $keys, + require => File["${homedir}/.ssh"], + } + } } diff --git a/tools/setup/bootstrap-aws-installer b/tools/setup/bootstrap-aws-installer index f081840380..a0c4527f9f 100644 --- a/tools/setup/bootstrap-aws-installer +++ b/tools/setup/bootstrap-aws-installer @@ -6,7 +6,6 @@ #FULL_ROLES= #REPO_URL= #BRANCH= -#SSH_SECRET_ID= export RUNNING_IN_CLOUD_INIT=1 if ! curl -fLs -m 5 -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 10" >/dev/null; then @@ -45,7 +44,6 @@ AWS_INSTALLER="inline!puppet/zulip_ops/files/install-aws-cli" # We then call it, to install the AWS CLI "$AWS_INSTALLER" -AWS=/srv/zulip-aws-tools/bin/aws # Set up a bare-bones AWS configuration mkdir -p /root/.aws @@ -56,25 +54,11 @@ output = text # Credentials are from the IAM role attached to the EC2 instance EOF -# Set up public keys for root, so we can fetch the repo; this is a -# function so we do can it again later with the zulip user -function install_keys() { - USERNAME="$1" - SSHDIR="$(getent passwd "$USERNAME" | cut -d: -f6)/.ssh" - KEYDATA="$($AWS --output text \ - secretsmanager get-secret-value \ - --secret-id "$SSH_SECRET_ID" \ - --query SecretString)" - mkdir -p "$SSHDIR" - for KEYFILE in $(echo "$KEYDATA" | jq -r 'keys[]'); do - echo "$KEYDATA" | jq -r ".[\"$KEYFILE\"]" | base64 -d >"$SSHDIR/$KEYFILE" - if [[ "$KEYFILE" != *".pub" ]]; then - chmod 600 "$SSHDIR/$KEYFILE" - fi - done - chown -R "$USERNAME:$USERNAME" "$SSHDIR" -} -install_keys root +# The following line gets replaced by pack-local-script output, which +# smuggles the install-ssh-keys binary into this one. +# install-ssh-keys, in turn, pulls key data from AWS' secret manager. +INSTALL_SSH_KEYS="inline!puppet/zulip_ops/files/install-ssh-keys" +"$INSTALL_SSH_KEYS" root prod/ssh/keys/common # Provide GitHub known_hosts setup; you can verify against fingerprints at # https://docs.github.com/en/github/authenticating-to-github/githubs-ssh-key-fingerprints @@ -98,8 +82,6 @@ git -C zulip checkout "$BRANCH" --no-init-db ) -install_keys zulip - # Delete the ubuntu user userdel ubuntu diff --git a/tools/setup/install-aws-server b/tools/setup/install-aws-server index c6955aa0e1..76a0ad0abe 100755 --- a/tools/setup/install-aws-server +++ b/tools/setup/install-aws-server @@ -26,7 +26,6 @@ repo_url=git@github.com:zulip/zulip.git zone_id=Z2U988IEXAMPLE security_groups=sg-01234567 instance_type=m4.large -ssh_secret_id=prod/git/deploy EOF } @@ -107,7 +106,6 @@ AWS_ZONE_ID=$(lookup zone_id) SECURITY_GROUPS=$(lookup security_groups) INSTANCE_TYPE=$(lookup instance_type) IAM_PROFILE=$(lookup iam_profile) -SSH_SECRET_ID=$(lookup ssh_secret_id) AZ=$(lookup availability_zone) DISK_SIZE=$(lookup disk_size) @@ -157,7 +155,6 @@ BOOTDATA=$(mktemp) echo "FULL_ROLES=$FULL_ROLES" echo "REPO_URL=$REPO_URL" echo "BRANCH=$BRANCH" - echo "SSH_SECRET_ID=$SSH_SECRET_ID" # Replace anything which looks like FOO="inline!bar/baz" with the # output of pack-local-script, which will make "$FOO" inside the # $BOOTDATA be the path to that script (smuggled inline and