Skip to content

Commit 2d0b189

Browse files
authored
Allow for private CA on the Agent side (#3494)
* Allow for private CA on the Agent side PBENCH-1209 The staging server and local development servers now use HTTPS with certs signed by a private pbench CA. An HTTPS connection can't be validated without a reference to this CA. The primary change here is in the `contrib/containerized-pbench/pbench` script which now looks for a private CA definition, maps the CA bundle file into the container, and defines `REQUESTS_CA_BUNDLE` within the container. In an attempt to handle RPM installs, there's also logic to support a new `[results]` section `pbench_ca` configuration variable to define a CA path that will be used to verify the `PUT` to a server. Note, this isn't being used for the `--relay` path, as that's currently not using `https` and we'll need to figure out how we want to configure this in the future.
1 parent 971ed19 commit 2d0b189

File tree

4 files changed

+110
-40
lines changed

4 files changed

+110
-40
lines changed

agent/config/pbench-agent-default.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ ssh_opts = -o BatchMode=yes -o StrictHostKeyChecking=no
2121
api_version = 1
2222
rest_endpoint = api/v%(api_version)s
2323
server_rest_url = https://%(pbench_web_server)s/%(rest_endpoint)s
24+
#server_ca =
2425

2526
[pbench/tools]
2627
light-tool-set = vmstat
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#!/bin/bash
2+
3+
# This is an essentially "trivial" script to interactively build a full set of
4+
# Pbench Agent containers for a platform specified by the PB_AGENT_DISTRO
5+
# environment variable, defaulting to fedora-38.
6+
#
7+
# These are the same commands used in the CI; however, the CI builds the
8+
# RPMs in the common build.sh script while the Jenkins Pipeline.gy builds the
9+
# CI container on top of that. Here we encapsulate the steps used to get a
10+
# functional result to make this more convenient interactively.
11+
#
12+
# WORKSPACE_TMP is assumed to be the root of the work area, and by default will
13+
# be set to ${HOME}.
14+
#
15+
# If you want to clean the make targets for RPM and container builds, use:
16+
#
17+
# agent/containers/images/container_build.sh --clean
18+
19+
export PB_AGENT_DISTRO=${PB_AGENT_DISTRO:-fedora-38}
20+
export WORKSPACE_TMP=${WORKSPACE_TMP:-${HOME}}
21+
22+
function usage {
23+
printf "Build a Pbench Agent container for the distribution named by the\n"
24+
printf "PB_AGENT_DISTRO environment variable, which defaults to '${PB_AGENT_DISTRO}'.\n"
25+
printf "\nThe following options are available:\n"
26+
printf "\n"
27+
printf -- "\t-c|--clean\n"
28+
printf "\t\tRemove old RPM and container image targets before building.\n"
29+
printf -- "\t-h|--help\n"
30+
printf "\t\tPrint this usage message and terminate.\n"
31+
}
32+
33+
opts=$(getopt -q -o ch --longoptions "clean,help" -n "${0}" -- "${@}")
34+
if [[ ${?} -ne 0 ]]; then
35+
printf -- "%s %s\n\n\tunrecognized option specified\n\n" "${0}" "${*}" >&2
36+
usage >&2
37+
exit 1
38+
fi
39+
eval set -- "${opts}"
40+
rpm_clean=
41+
image_clean=
42+
while true; do
43+
arg=${1}
44+
shift
45+
case "${arg}" in
46+
-c|--clean)
47+
rpm_clean=distclean
48+
image_clean=clean
49+
;;
50+
-h|--help)
51+
usage
52+
exit 0
53+
;;
54+
--)
55+
break
56+
;;
57+
*)
58+
printf -- "${0}: unrecognized command line argument, '${arg}'\n" >&2
59+
usage >&2
60+
exit 1
61+
;;
62+
esac
63+
done
64+
65+
make -C agent/rpm ${rpm_clean} ${PB_AGENT_DISTRO}-rpm
66+
make -C agent/containers/images CI=1 CI_RPM_ROOT=${WORKSPACE_TMP} \
67+
${image_clean} ${PB_AGENT_DISTRO}-everything
Lines changed: 32 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,62 @@
11
#! /bin/bash
22
#
33
# This script is a wrapper to facilitate the invocation of a Pbench Agent
4-
# command using a containerized deployment of the Pbench Agent. Simply prefix
4+
# command using a containerized deployment of the Pbench Agent. Simply prefix
55
# a Pbench Agent command line with the path to this script to run it inside a
66
# container, without needing to install the Agent on the host system.
77
#
88
# Invocation options are provided as environment variables:
9-
# PB_AGENT_IMAGE_NAME: the full image name for the containerized Pbench Agent
10-
# _PBENCH_AGENT_CONFIG: the location of the Pbench Agent configuration file
11-
# PB_AGENT_RUN_DIR: the directory for use as the Pbench Agent "run directory"
12-
# PB_AGENT_SERVER_LOC: the host and port for the Pbench Server
13-
# PB_AGENT_PODMAN_OPTIONS: Additional options to be supplied to Podman run
9+
# PB_AGENT_IMAGE_NAME: the full image name for the containerized Pbench Agent
10+
# PB_AGENT_RUN_DIR: the directory for use as the Pbench Agent "run directory"
11+
# PB_AGENT_CA: a CA bundle to verify Pbench Server PUTs
12+
# PB_AGENT_PODMAN_OPTIONS: Additional options to be supplied to Podman run
1413
#
1514
# In all cases, reasonable defaults are supplied if the environment variables
1615
# are not defined.
1716
#
18-
# This script checks for the presence of a `~/.ssh` directory, an existing
19-
# Pbench Agent configuration file, and a Pbench Agent "run directory" and maps
20-
# them into the container if they exist. If the configuration file is missing
21-
# but the location of the Pbench Server is available, then this script will
22-
# generate the configuration file, and the script creates the run directory if
23-
# it does not exist. The script then invokes the Pbench Agent container with
24-
# these options and any others which the user has specified and passes in the
25-
# command to be executed.
17+
# This script manages a persistent host Pbench Agent "run directory", which
18+
# defaults to /var/tmp/{USER}/pbench-agent/run, and maps that directory into
19+
# the container so that multiple runs can be generated and uploaded at once.
20+
#
21+
# To upload results to a Pbench Server, use this script to execute the
22+
# pbench-results-move command within the container, specifying either --relay
23+
# with the address of a Pbench Relay Server, or --server with the address of a
24+
# Pbench Server and --token to specify a Pbench Server API key for user
25+
# authentication.
26+
#
27+
# To use a server with a certificate signed by the Pbench development CA bundle
28+
# define the environment variable PB_AGENT_CA to cause the CA to be mapped into
29+
# the container and defined using REQUESTS_CA_BUNDLE:
30+
#
31+
# PB_AGENT_CA=server/pbenchinacan/etc/pki/tls/certs/pbench_CA.crt \
32+
# contrib/containerized-pbench/pbench pbench-results-move \
33+
# --server https://<server>:8443 --token <api-token>
2634

2735
image_name=${PB_AGENT_IMAGE_NAME:-quay.io/pbench/pbench-agent-all-centos-8:main}
28-
config_file=${_PBENCH_AGENT_CONFIG:-${HOME}/.config/pbench/pbench-agent.cfg}
2936
pbench_run_dir=${PB_AGENT_RUN_DIR:-/var/tmp/${USER}/pbench-agent/run}
30-
pbench_server=${PB_AGENT_SERVER_LOC}
37+
ca=${PB_AGENT_CA:-${REQUESTS_CA_BUNDLE}}
38+
if [[ ${ca} ]]; then
39+
pbench_ca=$(realpath ${ca}) # expand path outside container
40+
fi
41+
container_ca=/etc/pki/tls/certs/pbench_CA.crt # path inside container
3142
other_options=${PB_AGENT_PODMAN_OPTIONS}
3243

3344
if [[ $# == 0 || $1 == "help" || $1 == "-h" || $1 == "--help" ]]; then
3445
echo "Usage: ${0} <Pbench Agent Command> [<arg>...]" >&2
3546
exit 2
3647
fi
3748

38-
if [[ -d "${HOME}/.ssh" && -r "${HOME}/.ssh" ]]; then
39-
other_options="--security-opt=label=disable -v ${HOME}/.ssh:/root/.ssh ${other_options}"
40-
fi
41-
42-
if [[ -f "${config_file}" && -r "${config_file}" ]]; then
43-
other_options="-v ${config_file}:/opt/pbench-agent/config/pbench-agent.cfg:z ${other_options}"
44-
elif [[ -n "${pbench_server}" ]]; then
45-
echo "Warning: the Pbench Agent config file is missing; attempting to generate one in ${config_file}" >&2
46-
# TODO: this should be handled by a separate Pbench Agent "configuration wizard".
47-
mkdir -p $(dirname ${config_file})
48-
cat > ${config_file} <<- EOF
49-
[DEFAULT]
50-
pbench_install_dir = /opt/pbench-agent
51-
pbench_web_server = ${pbench_server}
52-
[config]
53-
path = %(pbench_install_dir)s/config
54-
files = pbench-agent-default.cfg
55-
EOF
56-
else
57-
echo "Warning: the Pbench Agent config file (e.g., ${config_file}) is missing or inaccessible -- using default configuration." >&2
58-
fi
59-
6049
mkdir -p ${pbench_run_dir}
61-
other_options="-v ${pbench_run_dir}:/var/lib/pbench-agent:z ${other_options}"
50+
if [[ -f "${pbench_ca}" ]]; then
51+
other_options="-v ${pbench_ca}:${container_ca}:Z ${other_options}"
52+
other_options="-e REQUESTS_CA_BUNDLE=${container_ca} ${other_options}"
53+
fi
6254

6355
podman run \
6456
-it \
6557
--rm \
6658
--network host \
6759
--name pbench-agent \
60+
-v ${pbench_run_dir}:/var/lib/pbench-agent:Z \
6861
${other_options} \
6962
${image_name} "${@}"

lib/pbench/agent/results.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -406,8 +406,13 @@ def __init__(
406406
if server:
407407
path = config.get("results", "rest_endpoint")
408408
uri = f"{server}/{path}"
409+
self.ca = None
409410
else:
410411
uri = config.get("results", "server_rest_url")
412+
413+
# If the "server_ca" config variable isn't defined, we expect to verify
414+
# using a registered CA.
415+
self.ca = config.get("results", "server_ca", fallback=None)
411416
self.uri = f"{uri}/upload/{{name}}"
412417
self.headers.update({"Authorization": f"Bearer {token}"})
413418

@@ -430,7 +435,11 @@ def push(self, tarball: Path, tarball_md5: str) -> requests.Response:
430435
tar_uri = self.uri.format(name=tarball.name)
431436
with tarball.open("rb") as f:
432437
return requests.put(
433-
tar_uri, data=f, headers=self.headers, params=self.params
438+
tar_uri,
439+
data=f,
440+
headers=self.headers,
441+
params=self.params,
442+
verify=self.ca,
434443
)
435444

436445

0 commit comments

Comments
 (0)