Merge pull request #22 from eest/backport-edit-secrets-from-cnaas-ops

Backport edit secrets from cnaas ops
This commit is contained in:
Fredrik Thulin 2023-01-18 14:32:30 +01:00 committed by GitHub
commit 44f4fb6620
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -18,91 +18,10 @@ umask 077
LAST_OUTPUT_FILENAME="/root/.last_edit-secrets_output"
if [[ "x${EDITOR}" != "x" ]]; then
declare -r REMOTE_EDITOR="${EDITOR}"
else
declare -r REMOTE_EDITOR='/usr/bin/vim.tiny'
fi
test -d /dev/shm && export TMPDIR='/dev/shm'
if [ "x$1" = "x" ]; then
echo "Syntax: $0 -l OR fqdn"
exit 1
fi
if [ "x$1" != "x-l" ]; then
host=$(echo $1 | sed -e 's!/*$!!') # remove trailing slashes
if [ ! -d $host ]; then
echo "$0: No host-directory for '$host' found - execute in top-level cosmos dir"
exit 1
fi
# Execute this very script, on a remote host
TMPFILE=$(mktemp edit-secrets.$$.XXXXXXX)
if [ ! -f $TMPFILE ]; then
echo "$0: Failed creating temporary file"
exit 1
fi
TMPFILE2=$(mktemp edit-secrets.$$.XXXXXXX)
if [ ! -f $TMPFILE2 ]; then
echo "$0: Failed creating temporary file"
exit 1
fi
trap "rm -f $TMPFILE $TMPFILE2" EXIT
ssh -t root@$host EDITOR="${REMOTE_EDITOR}" /var/cache/cosmos/repo/edit-secrets -l
scp -q root@$host:$LAST_OUTPUT_FILENAME $TMPFILE
if grep ^"STATUS=UPDATED" $TMPFILE > /dev/null; then
# extract the path of the file that should be updated in the Cosmos repo
save_to="${host}/overlay/etc/hiera/data/secrets.yaml.asc"
mkdir -p "`dirname $save_to`"
# extract the GPG output
perl -e '$a = 0; while (<>) { $a = 1 if ($_ =~ /-+BEGIN PGP MESSAGE-+/);
print $_ if $a; $a = 0 if ($_ =~ /-+END PGP MESSAGE-+/); }' < $TMPFILE > $TMPFILE2
if ! grep "END PGP MESSAGE" $TMPFILE2 > /dev/null; then
echo "$0: Failed extracting PGP output from file $TMPFILE into $TMPFILE2"
exit 1
fi
# use cat to preserve permissions etc.
cat $TMPFILE > $save_to
git add $save_to
echo ""
echo "$save_to updated"
echo ""
else
echo ""
echo "Not updated"
echo ""
fi
rm $TMPFILE $TMPFILE2
exit 0
fi
#
# Local execution on a host
#
SECRETFILE=/etc/hiera/data/secrets.yaml.asc
GNUPGHOME=/etc/hiera/gpg/
export GNUPGHOME
GPG=`which gpg2 || true`
if [ ! -x "$GPG" ]; then
GPG=`which gpg || true`
if [ ! -x "$GPG" ]; then
echo "$0: gpg2 or gpg not found"
exit 1
fi
fi
TMPFILE=$(mktemp --tmpdir=/dev/shm)
TMPFILE2=$(mktemp --tmpdir=/dev/shm)
TMPFILE=$(mktemp edit-secrets.XXXXXXXXXX)
TMPFILE2=$(mktemp edit-secrets.XXXXXXXXXX)
if [ ! -f $TMPFILE ]; then
echo "$TMPFILE"
@ -117,47 +36,239 @@ fi
trap "rm -f $TMPFILE $TMPFILE2" EXIT
if ! $GPG --list-secret-keys | grep -q ^"sec\s"; then
echo "$0: Secret key does not exist (in $GNUPGHOME)."
echo ""
echo "Generate it with /var/cache/cosmos/model/pre-tasks.d/040hiera-gpg"
echo ""
if [[ ! $1 ]]; then
# deliberately don't mention the --on-host argument
echo "Syntax: $0 fqdn"
exit 1
fi
if [ -s $SECRETFILE ]; then
$GPG -d $SECRETFILE > $TMPFILE
fi
function patch_broken_eyaml {
#
# Ubuntu 22.04 (jammy) has a broken hiera-eyaml package, a bug report
# exists here: https://bugs.launchpad.net/ubuntu/+source/hiera-eyaml/+bug/1974059
#
cp $TMPFILE $TMPFILE2
sensible-editor $TMPFILE
rm -f ${TMPFILE}~ ${TMPFILE2}~
if [ "$(lsb_release -cs)" == "jammy" ]; then
plugins_file="/usr/share/rubygems-integration/all/gems/hiera-eyaml-3.2.2/lib/hiera/backend/eyaml/plugins.rb"
if [ -f $plugins_file ]; then
# We only want to try patching the file if it is the known broken version
bad_sum="1d0f14765ebcfcdae300d8ac5d715845ef9b283345d19114a23d96161556618f"
sum=$(sha256sum $plugins_file | awk '{print $1}')
if [ "$sum" == "$bad_sum" ]; then
patch --fuzz=0 --directory=/ --strip=0 <<'EOF'
--- /usr/share/rubygems-integration/all/gems/hiera-eyaml-3.2.2/lib/hiera/backend/eyaml/plugins.rb.orig 2023-01-18 08:20:22.140338419 +0000
+++ /usr/share/rubygems-integration/all/gems/hiera-eyaml-3.2.2/lib/hiera/backend/eyaml/plugins.rb 2023-01-18 08:21:05.654053501 +0000
@@ -32,6 +32,7 @@
specs = Gem::VERSION >= "1.6.0" ? source.latest_specs(true) : source.latest_specs
echo ""
echo ""
specs.each do |spec|
+ spec = spec.to_spec if spec.respond_to?(:to_spec)
next if @@plugins.include? spec
status=0
cmp -s $TMPFILE $TMPFILE2 || status=1
if [ $status -eq 0 ]; then
(
echo "STATUS=NOT_CHANGED"
) > $LAST_OUTPUT_FILENAME
echo ""
echo "$0: No changes detected"
else
# figure out this hosts gpg key id
recipient=$($GPG --list-secret-key | grep ^sec | head -1 | awk '{print $2}' | cut -d / -f 2)
dependency = spec.dependencies.find { |d| d.name == "hiera-eyaml" }
EOF
fi
fi
fi
}
save_to="`hostname --fqdn`/overlay${SECRETFILE}"
echo ""
(
echo "STATUS=UPDATED"
function edit_copy_and_commit()
{
#
# This code runs on the administrators local machine
#
local host=$1
if [[ ${EDITOR} ]]; then
declare -r REMOTE_EDITOR="${EDITOR}"
else
declare -r REMOTE_EDITOR='/usr/bin/vim.tiny'
fi
# Execute this script, on a remote host
ssh -t root@"${host}" EDITOR="${REMOTE_EDITOR}" /var/cache/cosmos/repo/edit-secrets --on-host
scp -q root@"${host}:${LAST_OUTPUT_FILENAME}" ${TMPFILE}
local save_to
if grep ^"STATUS=UPDATED" $TMPFILE > /dev/null; then
save_to="${host}/overlay/etc/hiera/data/secrets.yaml.asc"
# extract the GPG output
perl -e '$a = 0; while (<>) { $a = 1 if ($_ =~ /-+BEGIN PGP MESSAGE-+/);
print $_ if $a; $a = 0 if ($_ =~ /-+END PGP MESSAGE-+/); }' < $TMPFILE > $TMPFILE2
if ! grep "END PGP MESSAGE" $TMPFILE2 > /dev/null; then
echo "$0: Failed extracting PGP output from file $TMPFILE into $TMPFILE2"
exit 1
fi
elif grep ^"STATUS=EYAML_UPDATED" $TMPFILE > /dev/null; then
save_to="${host}/overlay/etc/hiera/data/local.eyaml"
# extract the eyaml output
perl -e '$a = 0; while (<>) { $a = 1 if ($_ =~ /^---$/);
print $_ if $a }' < $TMPFILE > $TMPFILE2
if ! grep "^---$" $TMPFILE2 > /dev/null; then
echo "$0: Failed extracting yaml output from file $TMPFILE into $TMPFILE2"
exit 1
fi
else
echo ""
) > $LAST_OUTPUT_FILENAME
$GPG --output - --armor --recipient $recipient --sign --encrypt $TMPFILE >> $LAST_OUTPUT_FILENAME
echo "Not updated"
echo ""
exit 0
fi
# use cat to preserve permissions etc.
mkdir -p "`dirname ${save_to}`"
cat $TMPFILE2 > "${save_to}"
git add "${save_to}"
if grep ^"STATUS=EYAML_UPDATED" $TMPFILE > /dev/null; then
git diff --cached "${save_to}"
fi
echo ""
echo "GPG output saved in $LAST_OUTPUT_FILENAME - save it in Cosmos as"
echo "$save_to updated"
echo ""
echo " $save_to"
exit 0
}
function edit_file_on_host() {
#
# Local execution on a host
#
local SECRETFILE=/etc/hiera/data/secrets.yaml.asc
local EYAMLFILE=/etc/hiera/data/local.eyaml
if [ -f "${EYAMLFILE}" ]; then
edit_eyaml_file ${EYAMLFILE}
elif [ -f "${SECRETFILE}" ]; then
edit_gpg_file ${SECRETFILE}
elif [ -f /etc/hiera/eyaml/public_certkey.pkcs7.pem ]; then
# default to eyaml if the key exists and none of the secrets-file above exist
touch ${EYAMLFILE}
edit_eyaml_file ${EYAMLFILE}
fi
}
function edit_gpg_file()
{
local SECRETFILE=$1
GNUPGHOME=/etc/hiera/gpg/
export GNUPGHOME
local GPG=`which gpg2 || true`
if [ ! -x "$GPG" ]; then
GPG=`which gpg || true`
if [ ! -x "$GPG" ]; then
echo "$0: gpg2 or gpg not found"
exit 1
fi
fi
if ! $GPG --list-secret-keys | grep -q ^"sec\s"; then
echo "$0: Secret key does not exist (in $GNUPGHOME)."
echo ""
echo "Generate it with /var/cache/cosmos/model/pre-tasks.d/040hiera-gpg"
echo ""
exit 1
fi
if [ -s $SECRETFILE ]; then
$GPG -d $SECRETFILE > $TMPFILE
fi
cp $TMPFILE $TMPFILE2
sensible-editor $TMPFILE
rm -f ${TMPFILE}~ ${TMPFILE2}~
echo ""
echo ""
local status=0
cmp -s $TMPFILE $TMPFILE2 || status=1
if [ $status -eq 0 ]; then
(
echo "STATUS=NOT_CHANGED"
) > $LAST_OUTPUT_FILENAME
echo ""
echo "$0: No changes detected"
else
# figure out this hosts gpg key id
if lsb_release -r | grep -qE '(18|20).04'; then
recipient=$($GPG --list-secret-keys | grep -A1 '^sec' | tail -1 | awk '{print $1}')
else
recipient=$($GPG --list-secret-key | grep ^sec | head -1 | awk '{print $2}' | cut -d / -f 2)
fi
save_to="`hostname --fqdn`/overlay${SECRETFILE}"
echo ""
(
echo "STATUS=UPDATED"
echo ""
) > $LAST_OUTPUT_FILENAME
$GPG --output - --armor --recipient $recipient --sign --encrypt $TMPFILE >> $LAST_OUTPUT_FILENAME
echo ""
echo "GPG output saved in $LAST_OUTPUT_FILENAME - save it in Cosmos as"
echo ""
echo " $save_to"
echo ""
fi
}
function edit_eyaml_file()
{
local EYAMLFILE=$1
local FQDN=$(hostname --fqdn)
local privkey='/etc/hiera/eyaml/private_key.pkcs7.pem'
local pubkey='/etc/hiera/eyaml/public_certkey.pkcs7.pem'
for f in $privkey $pubkey; do
test -f "${f}" || { echo "$0: eyaml key file ${f} not found"; exit 1; }
done
patch_broken_eyaml
# save source file for comparision afterwards
cp "${EYAMLFILE}" "${TMPFILE}"
eyaml edit --pkcs7-private-key "${privkey}" --pkcs7-public-key "${pubkey}" "${EYAMLFILE}"
local status=0
cmp -s "${EYAMLFILE}" $TMPFILE || status=1
if [ $status -eq 0 ]; then
(
echo "STATUS=NOT_CHANGED"
) > $LAST_OUTPUT_FILENAME
echo ""
echo "$0: No changes detected"
else
echo ""
(
echo "STATUS=EYAML_UPDATED"
echo ""
) > $LAST_OUTPUT_FILENAME
cat "${EYAMLFILE}" >> $LAST_OUTPUT_FILENAME
fi
}
if [[ $1 == '--on-host' ]]; then
edit_file_on_host
else
host=$(echo $1 | sed -e 's!/*$!!') # remove trailing slashes
if [ ! -d $host ]; then
echo "$0: No host-directory for '$host' found - execute in top-level cosmos dir"
exit 1
fi
edit_copy_and_commit $host
fi
exit 0