HBASE-23339 release scripts should use host gpg-agent when running in container.

* put together a docker container that can use host gpg-agent forwarded over ssh.
* use gpg-agent forwarding container on OS X and directly forward the agent on Linux
* clean up the release container on exit
* use docker mounts instead of the deprecated volume syntax
* use image names within our project namespace
* update README to walk through running on GCE with gpg-agent forwarding

closes #1620

Signed-off-by: Matt Foley <mattf@apache.org>
Signed-off-by: Nick Dimiduk <ndimiduk@apache.org>
This commit is contained in:
Sean Busbey 2020-04-18 00:40:19 -05:00
parent 7fee4b5fb6
commit 497862bb47
No known key found for this signature in database
GPG Key ID: A926FD051016402D
7 changed files with 374 additions and 80 deletions

View File

@ -17,13 +17,29 @@ anomalies are explained up in JIRA.
See http://hbase.apache.org/book.html#maven.release
Regardless of where your release build will run (locally, locally in docker, on a remote machine,
etc) you will need a local gpg-agent with access to your secret keys. A quick way to tell gpg
to clear out state and start a gpg-agent is via the following command phrase:
$ gpgconf --kill all && gpg-connect-agent /bye
Before starting an RC build, make sure your local gpg-agent has configs
to properly handle your credentials, especially if you want to avoid
typing the passphrase to your secret key.
e.g. if you are going to run and step away, best to increase the TTL
on caching the unlocked secret via ~/.gnupg/gpg-agent.conf
# in seconds, e.g. a day
default-cache-ttl 86400
max-cache-ttl 86400
Running a build on GCE is easy enough. Here are some notes if of use.
Create an instance. 4CPU/15G/10G disk seems to work well enough.
Once up, run the below to make your machine fit for RC building:
# Presuming debian-compatible OS
$ sudo apt-get install -y git openjdk-8-jdk maven gnupg gnupg-agent
# Install docker
# Presuming debian-compatible OS, do these steps on the VM
# your VM username should be your ASF id, because it will show up in build artifacts.
# Follow the docker install guide: https://docs.docker.com/engine/install/debian/
$ sudo apt-get install -y \
apt-transport-https \
ca-certificates \
@ -37,15 +53,55 @@ $ sudo add-apt-repository -y \
stable"
$ sudo apt-get update
$ sudo apt-get install -y docker-ce docker-ce-cli containerd.io
$ sudo usermod -a -G docker $USERID
# Follow the post installation steps: https://docs.docker.com/engine/install/linux-postinstall/
$ sudo usermod -aG docker $USER
# LOGOUT and then LOGIN again so $USERID shows as part of docker group
# Copy up private key for $USERID export from laptop and import on gce.
$ gpg --import stack.duboce.net.asc
$ export GPG_TTY=$(tty) # https://github.com/keybase/keybase-issues/issues/2798
$ eval $(gpg-agent --disable-scdaemon --daemon --no-grab --allow-preset-passphrase --default-cache-ttl=86400 --max-cache-ttl=86400)
$ export PROJECT="${PROJECT:-hbase}"
$ git clone https://github.com/apache/${PROJECT}.git
$ cd "${PROJECT}"
# Test here by running docker's hello world as your build user
$ docker run hello-world
# Follow the GPG guide for forwarding your gpg-agent from your local machine to the VM
# https://wiki.gnupg.org/AgentForwarding
# On the VM find out the location of the gpg agent socket and extra socket
$ gpgconf --list-dir agent-socket
/run/user/1000/gnupg/S.gpg-agent
$ gpgconf --list-dir agent-extra-socket
/run/user/1000/gnupg/S.gpg-agent.extra
# On the VM configure sshd to remove stale sockets
$ sudo bash -c 'echo "StreamLocalBindUnlink yes" >> /etc/ssh/sshd_config'
$ sudo systemctl restart ssh
# logout of the VM
# Do these steps on your local machine.
# make sure gpg-agent is running
$ gpg-connect-agent /bye
# Export your public key and copy it to the VM.
# Assuming 'example.gce.host' maps to your VM's external IP (or use the IP)
$ gpg --export example@apache.org > ~/gpg.example.apache.pub
$ scp ~/gpg.example.apache.pub example.gce.host:
# ssh into the VM while forwarding the remote gpg socket locations found above to your local
# gpg-agent's extra socket (this will restrict what commands the remote node is allowed to have
# your agent handle. Note that the gpg guide above can help you set this up in your ssh config
# rather than typing it in ssh like this every time.
$ ssh -i ~/.ssh/my_id \
-R "/run/user/1000/gnupg/S.gpg-agent:$(gpgconf --list-dir agent-extra-socket)" \
-R "/run/user/1000/gnupg/S.gpg-agent.extra:$(gpgconf --list-dir agent-extra-socket)" \
example.gce.host
# now in an SSH session on the VM with the socket forwarding
# import your public key and test signing with the forwarding to your local agent.
$ gpg --no-autostart --import gpg.example.apache.pub
$ echo "foo" > foo.txt
$ gpg --no-autostart --detach --armor --sign foo.txt
$ gpg --no-autostart --verify foo.txt.asc
# install git and clone the main project on the build machine
$ sudo apt-get install -y git
$ git clone https://github.com/apache/hbase.git
# finally set up an output folder and launch a dry run.
$ mkdir ~/build
$ ./dev-resources/create-release/do-release-docker.sh -d ~/build
# etc.
$ cd hbase
$ ./dev-support/create-release/do-release-docker.sh -d ~/build
# for building the main repo specifically you can save an extra download by pointing the build
# to the local clone you just made
$ ./dev-support/create-release/do-release-docker.sh -d ~/build -r .git

View File

@ -76,6 +76,7 @@ Options:
-s [step] runs a single step of the process; valid steps are: tag|publish-dist|publish-release.
If none specified, runs tag, then publish-dist, and then publish-release.
'publish-snapshot' is also an allowed, less used, option.
-x debug. do less clean up. (env file, gpg forwarding on mac)
EOF
exit 1
}
@ -85,7 +86,7 @@ IMGTAG=latest
JAVA=
RELEASE_STEP=
GIT_REPO=
while getopts "d:fhj:p:r:s:t:" opt; do
while getopts "d:fhj:p:r:s:t:x" opt; do
case $opt in
d) WORKDIR="$OPTARG" ;;
f) DRY_RUN=0 ;;
@ -94,6 +95,7 @@ while getopts "d:fhj:p:r:s:t:" opt; do
p) PROJECT="$OPTARG" ;;
r) GIT_REPO="$OPTARG" ;;
s) RELEASE_STEP="$OPTARG" ;;
x) DEBUG=1 ;;
h) usage ;;
?) error "Invalid option. Run with -h for help." ;;
esac
@ -102,6 +104,7 @@ shift $((OPTIND-1))
if (( $# > 0 )); then
error "Arguments can only be provided with option flags, invalid args: $*"
fi
export DEBUG
if [ -z "$WORKDIR" ] || [ ! -d "$WORKDIR" ]; then
error "Work directory (-d) must be defined and exist. Run with -h for help."
@ -114,12 +117,26 @@ if [ -d "$WORKDIR/output" ]; then
fi
fi
if [ -f "${WORKDIR}/gpg-proxy.ssh.pid" ] || \
[ -f "${WORKDIR}/gpg-proxy.cid" ] || \
[ -f "${WORKDIR}/release.cid" ]; then
read -r -p "container/pid files from prior run exists. Overwrite and continue? [y/n] " ANSWER
if [ "$ANSWER" != "y" ]; then
error "Exiting."
fi
fi
cd "$WORKDIR"
rm -rf "$WORKDIR/output"
rm -rf "${WORKDIR}/gpg-proxy.ssh.pid" "${WORKDIR}/gpg-proxy.cid" "${WORKDIR}/release.cid"
mkdir "$WORKDIR/output"
banner "Gathering release details."
HOST_OS="$(get_host_os)"
get_release_info
banner "Setup"
# Place all RM scripts and necessary data in a local directory that must be defined in the command
# line. This directory is mounted into the image. Its WORKDIR, the arg passed with -d.
for f in "$SELF"/*; do
@ -128,25 +145,65 @@ for f in "$SELF"/*; do
fi
done
GPG_KEY_FILE="$WORKDIR/gpg.key"
# We need to import that public key in the container in order to use the private key via the agent.
GPG_KEY_FILE="$WORKDIR/gpg.key.public"
echo "Exporting public key for ${GPG_KEY}"
fcreate_secure "$GPG_KEY_FILE"
$GPG --passphrase "$GPG_PASSPHRASE" --export-secret-key --armor "$GPG_KEY" > "$GPG_KEY_FILE"
$GPG "${GPG_ARGS[@]}" --export "${GPG_KEY}" > "${GPG_KEY_FILE}"
function cleanup {
local id
banner "Release Cleanup"
if is_debug; then
echo "skipping due to debug run"
return 0
fi
echo "details in cleanup.log"
if [ -f "${ENVFILE}" ]; then
rm -f "$ENVFILE"
fi
rm -f "$GPG_KEY_FILE"
if [ -f "${WORKDIR}/gpg-proxy.ssh.pid" ]; then
id=$(cat "${WORKDIR}/gpg-proxy.ssh.pid")
echo "Stopping ssh tunnel for gpg-agent at PID ${id}" | tee -a cleanup.log
kill -9 "${id}" >>cleanup.log 2>&1 || true
rm -f "${WORKDIR}/gpg-proxy.ssh.pid" >>cleanup.log 2>&1
fi
if [ -f "${WORKDIR}/gpg-proxy.cid" ]; then
id=$(cat "${WORKDIR}/gpg-proxy.cid")
echo "Stopping gpg-proxy container with ID ${id}" | tee -a cleanup.log
docker kill "${id}" >>cleanup.log 2>&1 || true
rm -f "${WORKDIR}/gpg-proxy.cid" >>cleanup.log 2>&1
# TODO we should remove the gpgagent volume?
fi
if [ -f "${WORKDIR}/release.cid" ]; then
id=$(cat "${WORKDIR}/release.cid")
echo "Stopping release container with ID ${id}" | tee -a cleanup.log
docker kill "${id}" >>cleanup.log 2>&1 || true
rm -f "${WORKDIR}/release.cid" >>cleanup.log 2>&1
fi
}
trap cleanup EXIT
echo "Host OS: ${HOST_OS}"
if [ "${HOST_OS}" == "DARWIN" ]; then
run_silent "Building gpg-agent-proxy image with tag ${IMGTAG}..." "docker-proxy-build.log" \
docker build --build-arg "UID=${UID}" --build-arg "RM_USER=${USER}" \
--tag "org.apache.hbase/gpg-agent-proxy:${IMGTAG}" "${SELF}/mac-sshd-gpg-agent"
fi
run_silent "Building hbase-rm image with tag $IMGTAG..." "docker-build.log" \
docker build -t "hbase-rm:$IMGTAG" --build-arg UID=$UID "$SELF/hbase-rm"
docker build --tag "org.apache.hbase/hbase-rm:$IMGTAG" --build-arg "UID=$UID" \
--build-arg "RM_USER=${USER}" "$SELF/hbase-rm"
banner "Final prep for container launch."
echo "Writing out environment for container."
# Write the release information to a file with environment variables to be used when running the
# image.
ENVFILE="$WORKDIR/env.list"
fcreate_secure "$ENVFILE"
function cleanup {
rm -f "$ENVFILE"
rm -f "$GPG_KEY_FILE"
}
trap cleanup EXIT
cat > "$ENVFILE" <<EOF
PROJECT=$PROJECT
DRY_RUN=$DRY_RUN
@ -162,15 +219,15 @@ GIT_NAME=$GIT_NAME
GIT_EMAIL=$GIT_EMAIL
GPG_KEY=$GPG_KEY
ASF_PASSWORD=$ASF_PASSWORD
GPG_PASSPHRASE=$GPG_PASSPHRASE
RELEASE_STEP=$RELEASE_STEP
API_DIFF_TAG=$API_DIFF_TAG
HOST_OS=$HOST_OS
EOF
JAVA_VOL=()
JAVA_MOUNT=()
if [ -n "$JAVA" ]; then
echo "JAVA_HOME=/opt/hbase-java" >> "$ENVFILE"
JAVA_VOL=(--volume "$JAVA:/opt/hbase-java")
JAVA_MOUNT=(--mount "type=bind,src=${JAVA},dst=/opt/hbase-java,readonly")
fi
#TODO some debug output would be good here
@ -226,14 +283,61 @@ if [ -n "${GIT_REPO}" ]; then
echo "GIT_REPO=${GIT_REPO}" >> "${ENVFILE}"
fi
echo "Building $RELEASE_TAG; output will be at $WORKDIR/output"
GPG_PROXY_MOUNT=()
if [ "${HOST_OS}" == "DARWIN" ]; then
GPG_PROXY_MOUNT=(--mount "type=volume,src=gpgagent,dst=/home/${USER}/.gnupg/")
echo "Setting up GPG agent proxy container needed on OS X."
echo " we should clean this up for you. If that fails the container ID is below and in " \
"gpg-proxy.cid"
#TODO the key pair used should be configurable
docker run --rm -p 62222:22 \
--detach --cidfile "${WORKDIR}/gpg-proxy.cid" \
--mount \
"type=bind,src=${HOME}/.ssh/id_rsa.pub,dst=/home/${USER}/.ssh/authorized_keys,readonly" \
"${GPG_PROXY_MOUNT[@]}" \
"org.apache.hbase/gpg-agent-proxy:${IMGTAG}"
# gotta trust the container host
ssh-keyscan -p 62222 localhost 2>/dev/null | sort > "${WORKDIR}/gpg-agent-proxy.ssh-keyscan"
sort "${HOME}/.ssh/known_hosts" | comm -1 -3 - "${WORKDIR}/gpg-agent-proxy.ssh-keyscan" \
> "${WORKDIR}/gpg-agent-proxy.known_hosts"
if [ -s "${WORKDIR}/gpg-agent-proxy.known_hosts" ]; then
echo "Your ssh known_hosts does not include the entries for the gpg-agent proxy container."
echo "The following entry(ies) arre missing:"
sed -e 's/^/ /' "${WORKDIR}/gpg-agent-proxy.known_hosts"
read -r -p "Okay to add these entries to ${HOME}/.ssh/known_hosts? [y/n] " ANSWER
if [ "$ANSWER" != "y" ]; then
error "Exiting."
fi
cat "${WORKDIR}/gpg-agent-proxy.known_hosts" >> "${HOME}/.ssh/known_hosts"
fi
echo "Launching ssh reverse tunnel from the container to gpg agent."
echo " we should clean this up for you. If that fails the PID is in gpg-proxy.ssh.pid"
ssh -p 62222 -R "/home/${USER}/.gnupg/S.gpg-agent:$(gpgconf --list-dir agent-extra-socket)" \
-i "${HOME}/.ssh/id_rsa" -N -n localhost >gpg-proxy.ssh.log 2>&1 &
echo $! > "${WORKDIR}/gpg-proxy.ssh.pid"
else
# Note that on linux we always directly mount the gpg agent's extra socket to limit what the
# container can ask the gpg-agent to do.
# When working on a remote linux machine you should be sure to forward both the remote machine's
# agent socket and agent extra socket to your local gpg-agent's extra socket. See the README.txt
# for an example.
GPG_PROXY_MOUNT=(--mount \
"type=bind,src=$(gpgconf --list-dir agent-extra-socket),dst=/home/${USER}/.gnupg/S.gpg-agent")
fi
banner "Building $RELEASE_TAG; output will be at $WORKDIR/output"
echo "We should clean the container up when we are done. If that fails then the container ID " \
"is in release.cid"
echo
# Where possible we specifcy "consistency=delegated" when we do not need host access during the
# build run. On Mac OS X specifically this gets us a big perf improvement.
cmd=(docker run -ti \
cmd=(docker run --rm -ti \
--env-file "$ENVFILE" \
--mount "type=bind,src=${WORKDIR},dst=/opt/hbase-rm,consistency=delegated" \
"${JAVA_VOL[@]}" \
--cidfile "${WORKDIR}/release.cid" \
--mount "type=bind,src=${WORKDIR},dst=/home/${USER}/hbase-rm,consistency=delegated" \
"${JAVA_MOUNT[@]}" \
"${GIT_REPO_MOUNT[@]}" \
"hbase-rm:$IMGTAG")
"${GPG_PROXY_MOUNT[@]}" \
"org.apache.hbase/hbase-rm:$IMGTAG")
echo "${cmd[*]}"
"${cmd[@]}"

View File

@ -17,6 +17,7 @@
# limitations under the License.
#
set -e
# Use the adjacent do-release-docker.sh instead, if you can.
# Otherwise, this runs core of the release creation.
# Will ask you questions on what to build and for logins
@ -40,29 +41,64 @@ if (( $# > 0 )); then
error "Arguments can only be provided with option flags, invalid args: $*"
fi
function gpg_agent_help {
cat <<EOF
Trying to sign a test file using your GPG setup failed.
Please make sure you have a local gpg-agent running with access to your secret keys prior to
starting a release build. If you are creating release artifacts on a remote machine please check
that you have set up ssh forwarding to the gpg-agent extra socket.
For help on how to do this please see the README file in the create-release directory.
EOF
exit 1
}
# If running in docker, import and then cache keys.
if [ "$RUNNING_IN_DOCKER" = "1" ]; then
# Run gpg agent.
eval "$(gpg-agent --disable-scdaemon --daemon --no-grab --allow-preset-passphrase \
--default-cache-ttl=86400 --max-cache-ttl=86400)"
echo "GPG Version: $(gpg --version)"
# Inside docker, need to import the GPG keyfile stored in the current directory.
# (On workstation, assume GPG has access to keychain/cache with key_id already imported.)
echo "$GPG_PASSPHRASE" | $GPG --passphrase-fd 0 --import "$SELF/gpg.key"
# when Docker Desktop for mac is running under load there is a delay before the mounted volume
# becomes available. if we do not pause then we may try to use the gpg-agent socket before docker
# has got it ready and we will not think there is a gpg-agent.
if [ "${HOST_OS}" == "DARWIN" ]; then
sleep 5
fi
# in docker our working dir is set to where all of our scripts are held
# and we want default output to go into the "output" directory that should be in there.
if [ -d "output" ]; then
cd output
fi
GPG_ARGS=("${GPG_ARGS[@]}" --local-user "${GPG_KEY}")
echo "GPG Version: $("${GPG}" "${GPG_ARGS[@]}" --version)"
# Inside docker, need to import the GPG key stored in the current directory.
if ! $GPG "${GPG_ARGS[@]}" --import "$SELF/gpg.key.public" ; then
gpg_agent_help
fi
# We may need to adjust the path since JAVA_HOME may be overridden by the driver script.
if [ -n "$JAVA_HOME" ]; then
echo "Using JAVA_HOME from host."
export PATH="$JAVA_HOME/bin:$PATH"
else
# JAVA_HOME for the openjdk package.
export JAVA_HOME=/usr
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/
fi
else
# Outside docker, need to ask for information about the release.
get_release_info
GPG_ARGS=("${GPG_ARGS[@]}" --local-user "${GPG_KEY}")
fi
GPG_TTY="$(tty)"
export GPG_TTY
echo "Testing gpg signing."
echo "foo" > gpg_test.txt
if ! "${GPG}" "${GPG_ARGS[@]}" --detach --armor --sign gpg_test.txt ; then
gpg_agent_help
fi
# In --batch mode we have to be explicit about what we are verifying
if ! "${GPG}" "${GPG_ARGS[@]}" --verify gpg_test.txt.asc gpg_test.txt ; then
gpg_agent_help
fi
if [[ -z "$RELEASE_STEP" ]]; then
# If doing all stages, leave out 'publish-snapshot'

View File

@ -50,10 +50,15 @@ RUN wget -qO- "https://www.apache.org/dyn/mirrors/mirrors.cgi?action=download&fi
tar xvz -C /opt
ENV YETUS_HOME /opt/apache-yetus-${YETUS_VERSION}
WORKDIR /opt/hbase-rm/output
ARG UID
RUN useradd -m -s /bin/bash -p hbase-rm -u $UID hbase-rm
USER hbase-rm:hbase-rm
ARG RM_USER
RUN groupadd hbase-rm && \
useradd --create-home --shell /bin/bash -p hbase-rm -u $UID $RM_USER && \
mkdir /home/$RM_USER/.gnupg && \
chown -R $RM_USER:hbase-rm /home/$RM_USER && \
chmod -R 700 /home/$RM_USER
ENTRYPOINT [ "/opt/hbase-rm/do-release.sh" ]
USER $RM_USER:hbase-rm
WORKDIR /home/$RM_USER/hbase-rm/
ENTRYPOINT [ "./do-release.sh" ]

View File

@ -0,0 +1,100 @@
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Image for use on Mac boxes to get a gpg agent socket available
# within transient release building ocntainers.
#
# build like:
#
# docker build --build-arg "UID=$UID" --build-arg "RM_USER=$USER" \
# --tag org.apache.hbase/gpg-agent-proxy mac-sshd-gpg-agent
#
# run like:
#
# docker run --rm -p 62222:22 \
# --mount "type=bind,src=${HOME}/.ssh/id_rsa.pub,dst=/home/${USER}/.ssh/authorized_keys,readonly" \
# --mount "type=volume,src=gpgagent,dst=/home/${USER}/.gnupg/" \
# org.apache.hbase/gpg-agent-proxy:latest
#
# test like:
#
# ssh -p 62222 -R "/home/${USER}/.gnupg/S.gpg-agent:$(gpgconf --list-dir agent-extra-socket)" \
# -i "${HOME}/.ssh/id_rsa" -N -n localhost
#
# launch a docker container to do work that shares the mount for the gpg agent
# expressly does not need to be this same image, but needs to have defined the same user
#
# docker run --rm -it \
# --mount "type=volume,src=gpgagent,dst=/home/${USER}/.gnupg/" \
# --mount "type=bind,src=${HOME}/projects/hbase-releases/KEYS,dst=/home/${USER}/KEYS,readonly" \
# --entrypoint /bin/bash --user "${USER}" --workdir "/home/${USER}/" \
# org.apache.hbase/gpg-agent-proxy:latest
#
#
# Make sure to import the public keys
#
# gpg --no-autostart --import < ${HOME}/KEYS
# Optional?
# gpg --no-autostart --edit-key ${YOUR_KEY}
# trust
# 5
# y
# quit
#
# echo "foo" > foo
# gpg --no-autostart --armor --detach --sign foo
# gpg --no-autostart --verify foo.asc
#
# For more info see
# * gpg forwarding over ssh: https://wiki.gnupg.org/AgentForwarding
# * example docker for sshd: https://github.com/hotblac/nginx-ssh
# * why we have to bother with this: https://github.com/docker/for-mac/issues/483
#
# If the docker image changes then the host key used by sshd will change and you will get a
# nastygram when launching ssh about host identification changing. This is expected. you should
# remove the previous host key.
#
# Tested with
# * Docker Desktop 2.2.0.5
# * gpg 2.2.20
# * pinentry-mac 0.9.4
# * yubikey 5
#
FROM ubuntu:18.04
# This is all in a single "RUN" command so that if anything changes, "apt update" is run to fetch
# the most current package versions (instead of potentially using old versions cached by docker).
#
# We only need gnupg2 here if we want the ability to test out the gpg-agent forwarding by sshing
# into the container rather than launching a new docker container.
RUN DEBIAN_FRONTEND=noninteractive apt-get -qq -y update \
&& DEBIAN_FRONTEND=noninteractive apt-get -qq -y install --no-install-recommends \
openssh-server=1:7.6p1-4ubuntu0.3 gnupg2=2.2.4-1ubuntu1.2 && mkdir /run/sshd \
&& echo "StreamLocalBindUnlink yes" >> /etc/ssh/sshd_config \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
EXPOSE 22
# Set up our ssh user
ARG UID
ARG RM_USER
RUN groupadd sshgroup && \
useradd --create-home --shell /bin/bash --groups sshgroup --uid $UID $RM_USER && \
mkdir /home/$RM_USER/.ssh /home/$RM_USER/.gnupg && \
chown -R $RM_USER:sshgroup /home/$RM_USER/ && \
chmod -R 700 /home/$RM_USER/
# When we run we run sshd
ENTRYPOINT ["/usr/sbin/sshd", "-D"]

View File

@ -66,13 +66,12 @@ Used only for 'publish':
separately define GIT_REF if RELEASE_TAG is not actually present as a tag at publish time)
If both RELEASE_TAG and GIT_REF are undefined it will default to HEAD of master.
GPG_KEY - GPG key id (usually email addr) used to sign release artifacts
GPG_PASSPHRASE - Passphrase for GPG key
REPO - Set to full path of a directory to use as maven local repo (dependencies cache)
to avoid re-downloading dependencies for each stage. It is automatically set if you
request full sequence of stages (tag, publish-dist, publish-release) in do-release.sh.
For example:
$ PROJECT="hbase-operator-tools" ASF_USERNAME=NAME ASF_PASSWORD=PASSWORD GPG_PASSPHRASE=PASSWORD GPG_KEY=stack@apache.org ./release-build.sh publish-dist
$ PROJECT="hbase-operator-tools" ASF_USERNAME=NAME ASF_PASSWORD=PASSWORD GPG_KEY=stack@apache.org ./release-build.sh publish-dist
EOF
exit 1
}
@ -165,12 +164,7 @@ fi
### Below is for 'publish-*' stages ###
check_get_passwords ASF_PASSWORD
if [[ -z "$GPG_PASSPHRASE" ]]; then
check_get_passwords GPG_PASSPHRASE
GPG_TTY="$(tty)"
export GPG_TTY
fi
check_needed_vars PROJECT ASF_USERNAME ASF_PASSWORD GPG_KEY GPG_PASSPHRASE
check_needed_vars PROJECT ASF_USERNAME ASF_PASSWORD GPG_KEY
# Commit ref to checkout when building
BASE_DIR=$(pwd)

View File

@ -17,7 +17,9 @@
# limitations under the License.
#
DRY_RUN=${DRY_RUN:-1} #default to dry run
GPG="gpg --pinentry-mode loopback --no-tty --batch"
DEBUG=${DEBUG:-0}
GPG=${GPG:-gpg}
GPG_ARGS=(--no-autostart --batch)
# Maven Profiles for publishing snapshots and release to Maven Central and Dist
PUBLISH_PROFILES=("-P" "apache-release,release")
@ -46,23 +48,26 @@ function parse_version {
head -n 2 | tail -n 1 | cut -d'>' -f2 | cut -d '<' -f1
}
function banner {
local msg="$1"
echo "========================"
echo "=== ${msg}"
echo
}
function run_silent {
local BANNER="$1"
local LOG_FILE="$2"
shift 2
echo "========================"
echo "=== $BANNER"
banner "${BANNER}"
echo "Command: $*"
echo "Log file: $LOG_FILE"
"$@" 1>"$LOG_FILE" 2>&1
local EC=$?
if [ $EC != 0 ]; then
if ! "$@" 1>"$LOG_FILE" 2>&1; then
echo "Command FAILED. Check full logs for details."
tail "$LOG_FILE"
exit $EC
exit 1
fi
echo "=== SUCCESS"
}
@ -260,20 +265,17 @@ EOF
ASF_PASSWORD="***INVALID***"
fi
if [ -z "$GPG_PASSPHRASE" ]; then
stty -echo && printf "GPG_PASSPHRASE: " && read -r GPG_PASSPHRASE && printf '\n' && stty echo
GPG_TTY="$(tty)"
export GPG_TTY
fi
export ASF_PASSWORD
export GPG_PASSPHRASE
}
function is_dry_run {
[[ "$DRY_RUN" = 1 ]]
}
function is_debug {
[[ "${DEBUG}" = 1 ]]
}
function check_get_passwords {
for env in "$@"; do
if [ -z "${!env}" ]; then
@ -381,8 +383,6 @@ function configure_maven {
<password>${env.ASF_PASSWORD}</password></server>
<server><id>apache.releases.https</id><username>${env.ASF_USERNAME}</username>
<password>${env.ASF_PASSWORD}</password></server>
<server><id>gpg.passphrase</id>
<passphrase>${env.GPG_PASSPHRASE}</passphrase></server>
</servers>
<profiles>
<profile>
@ -436,6 +436,7 @@ function git_clone_overwrite {
}
# Writes report into cwd!
# TODO should have option for maintenance release that include LimitedPrivate in report
function generate_api_report {
local project="$1"
local previous_tag="$2"
@ -518,10 +519,9 @@ function update_releasenotes {
# named for 'project', the first arg passed.
# Expects the following three defines in the environment:
# - GPG needs to be defined, with the path to GPG: defaults 'gpg'.
# - The passphrase in the GPG_PASSPHRASE variable: no default (we don't make .asc file).
# - GIT_REF which is the tag to create the tgz from: defaults to 'master'.
# For example:
# $ GPG_PASSPHRASE="XYZ" GIT_REF="master" make_src_release hbase-operator-tools 1.0.0
# $ GIT_REF="master" make_src_release hbase-operator-tools 1.0.0
make_src_release() {
# Tar up the src and sign and hash it.
local project="${1}"
@ -533,9 +533,8 @@ make_src_release() {
git clean -d -f -x
git archive --format=tar.gz --output="../${tgz}" --prefix="${base_name}/" "${GIT_REF:-master}"
cd .. || exit
echo "$GPG_PASSPHRASE" | $GPG --passphrase-fd 0 --armour --output "${tgz}.asc" \
--detach-sig "${tgz}"
echo "$GPG_PASSPHRASE" | $GPG --passphrase-fd 0 --print-md SHA512 "${tgz}" > "${tgz}.sha512"
$GPG "${GPG_ARGS[@]}" --armor --output "${tgz}.asc" --detach-sig "${tgz}"
$GPG "${GPG_ARGS[@]}" --print-md SHA512 "${tgz}" > "${tgz}.sha512"
}
# Make binary release.
@ -544,11 +543,10 @@ make_src_release() {
# named for 'project', the first arg passed.
# Expects the following three defines in the environment:
# - GPG needs to be defined, with the path to GPG: defaults 'gpg'.
# - The passphrase in the GPG_PASSPHRASE variable: no default (we don't make .asc file).
# - GIT_REF which is the tag to create the tgz from: defaults to 'master'.
# - MVN Default is "mvn -B --settings $MAVEN_SETTINGS_FILE".
# For example:
# $ GPG_PASSPHRASE="XYZ" GIT_REF="master" make_src_release hbase-operator-tools 1.0.0
# $ GIT_REF="master" make_src_release hbase-operator-tools 1.0.0
make_binary_release() {
local project="${1}"
local version="${2}"
@ -573,8 +571,8 @@ make_binary_release() {
cp "${f_bin_prefix}"*-bin.tar.gz ..
cd .. || exit
for i in "${base_name}"*-bin.tar.gz; do
echo "$GPG_PASSPHRASE" | $GPG --passphrase-fd 0 --armour --output "$i.asc" --detach-sig "$i"
echo "$GPG_PASSPHRASE" | $GPG --passphrase-fd 0 --print-md SHA512 "${i}" > "$i.sha512"
"${GPG}" "${GPG_ARGS[@]}" --armour --output "${i}.asc" --detach-sig "${i}"
"${GPG}" "${GPG_ARGS[@]}" --print-md SHA512 "${i}" > "${i}.sha512"
done
else
cd .. || exit
@ -588,10 +586,11 @@ make_binary_release() {
# 'assembly' build (where gpg signing occurs) experiences timeout, without this "kick".
function kick_gpg_agent {
# All that's needed is to run gpg on a random file
# TODO could we just call gpg-connect-agent /bye
local i
i="$(mktemp)"
echo "This is a test file" > "$i"
echo "$GPG_PASSPHRASE" | $GPG --passphrase-fd 0 --armour --output "$i.asc" --detach-sig "$i"
"${GPG}" "${GPG_ARGS[@]}" --armour --output "${i}.asc" --detach-sig "${i}"
rm "$i" "$i.asc"
}