Skip to content

Commit

Permalink
feat: enable mtls by default by using smallstep as local pki
Browse files Browse the repository at this point in the history
Signed-off-by: Reuben Miller <reuben.d.miller@gmail.com>
  • Loading branch information
reubenmiller committed Oct 3, 2024
1 parent afd896e commit bda2c0e
Show file tree
Hide file tree
Showing 10 changed files with 130 additions and 4 deletions.
8 changes: 7 additions & 1 deletion images/child-device-container/child.dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,16 @@ RUN apk add --no-cache \
&& curl -1sLf 'https://dl.cloudsmith.io/public/thinedge/community/config.alpine.txt?distro=alpine&codename=v3.8' >> /etc/apk/repositories \
&& apk add --no-cache \
tedge-apk-plugin \
&& echo "tedge ALL = (ALL) NOPASSWD: /usr/bin/tedge, /usr/bin/tedge-write /etc/*, /etc/tedge/sm-plugins/[a-zA-Z0-9]*, /bin/sync, /bin/kill" > /etc/sudoers.d/tedge
tedge-pki-smallstep-client \
&& echo "tedge ALL = (ALL) NOPASSWD: /usr/bin/tedge, /usr/bin/tedge-write /etc/*, /etc/tedge/sm-plugins/[a-zA-Z0-9]*, /bin/sync, /bin/kill" > /etc/sudoers.d/tedge \
&& echo "tedge ALL = (ALL) NOPASSWD: /usr/bin/step-ca-admin.sh, /usr/bin/enroll.sh, /usr/sbin/update-ca-certificates" > /etc/sudoers.d/step-ca \
# Allow tedge user to control this folder
&& mkdir -p /etc/step-ca \
&& chown -R tedge:tedge /etc/step-ca

USER tedge
COPY child-device-container/config/tedge-configuration-plugin.toml /etc/tedge/plugins/
COPY common/utils/enroll/enroll.sh /usr/bin/
COPY child-device-container/entrypoint.sh /app/
COPY common/utils/workflows/firmware_update.toml /etc/tedge/operations/
ENV TEDGE_MQTT_CLIENT_HOST=tedge
Expand Down
9 changes: 9 additions & 0 deletions images/child-device-container/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
#!/bin/sh
set -e

# Enroll device with mtls
PROVISION_PASSWORD_FILE=/tmp/provisioner-password
if [ -n "$PROVISION_PASSWORD" ]; then
printf -- '%s' "$PROVISION_PASSWORD" > "$PROVISION_PASSWORD_FILE"
chmod 600 "$PROVISION_PASSWORD_FILE"
fi
(cd /tmp && sudo /usr/bin/enroll.sh --no-inherit-env --provisioner-password-file "$PROVISION_PASSWORD_FILE")
rm -f "$PROVISION_PASSWORD_FILE"

# start agent
exec /usr/bin/tedge-agent
8 changes: 8 additions & 0 deletions images/child-device-systemd/child.dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ RUN echo "running" \
tedge-agent \
tedge-apt-plugin \
tedge-inventory-plugin \
# Local PKI service for easy child device registration
tedge-pki-smallstep-client \
# Disable mosquitto as it is not needed on a child device
&& systemctl disable mosquitto.service \
&& systemctl mask mosquitto.service \
Expand All @@ -61,6 +63,12 @@ COPY common/utils/configure-device/scripts.d/* /usr/share/configure-device/scrip
COPY common/utils/configure-device/configure-device.service /lib/systemd/system/
RUN systemctl enable configure-device.service

# add mtls enablement script. Store script under /usr/bin so it can also be manually called
COPY common/utils/enroll/enroll.sh /usr/bin/
RUN ln -sf /usr/bin/enroll.sh /usr/share/configure-device/scripts.d/70_enable_mtls
# COPY common/utils/enroll/enroll.service /usr/lib/systemd/system/
# RUN systemctl enable enroll.service

COPY child-device-systemd/config/system.toml /etc/tedge/
COPY child-device-systemd/config/tedge.toml /etc/tedge/
COPY common/utils/workflows/firmware_update.toml /etc/tedge/operations/
Expand Down
1 change: 1 addition & 0 deletions images/common/config/sudoers.d/step-ca
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
tedge ALL = (ALL) NOPASSWD: /usr/bin/step-ca-admin.sh, /usr/bin/step-ca, /usr/sbin/update-ca-certificates
3 changes: 2 additions & 1 deletion images/common/utils/configure-device/runner.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ if [ $# -ge 2 ]; then
fi

_NEWLINE=$(printf '\n')
find "$RUN_PARTS" -type f -name "$NAME_FILTER" -perm 755 | while IFS="$_NEWLINE" read -r file
# Use -L to allow scripts to be a symlink, but this requires the results to be sorted afterwards
find -L "$RUN_PARTS" -type f -name "$NAME_FILTER" -perm 755 | sort | while IFS="$_NEWLINE" read -r file
do
echo "Executing script: $file" >&2
set +e
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
set -ex

systemctl enable tedge-agent
systemctl restart tedge-agent
systemctl start tedge-agent
68 changes: 68 additions & 0 deletions images/common/utils/enroll/enroll.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#!/bin/sh
set -e

INHERIT_ENV=${INHERIT_ENV:-1}

OLD_PWD="$(pwd)"
cd /etc

while [ $# -gt 0 ]; do
case "$1" in
--inherit-env)
INHERIT_ENV=1
;;
--no-inherit-env)
INHERIT_ENV=0
;;
--provisioner-password-file)
PROVISION_PASSWORD_FILE="$2"
shift
;;
esac
shift
done

if [ "$INHERIT_ENV" = 1 ]; then
# Create env file from PID 1
# (as this is the old service which inherits the container environment variables)
echo "Loading environment from PID 1"
tr '\0' '\n' </proc/1/environ \
| grep -v "^\(_\|HOME\|PATH\|TERM\|HOSTNAME\|PWD\|SHLVL\)=" | tee > /etc/container.env

# Load env
# shellcheck disable=SC1091
. /etc/container.env
fi


PROVISION_PASSWORD="${PROVISION_PASSWORD:-}"
PROVISION_PASSWORD_FILE=${PROVISION_PASSWORD_FILE:-/etc/provisioner_password}
if [ -n "$PROVISION_PASSWORD" ]; then
printf -- '%s' "$PROVISION_PASSWORD" > "$PROVISION_PASSWORD_FILE"
chmod 600 "$PROVISION_PASSWORD_FILE"
fi

enroll_device() {
# Enable downloading of root cert (this can be trusted when running in a controlled container env)
if [ -f "$PROVISION_PASSWORD_FILE" ]; then
/usr/bin/step-ca-admin.sh enroll "$(hostname)" \
--ca-url https://tedge:8443 \
--allow-insecure-root \
--provisioner-password-file "$PROVISION_PASSWORD_FILE"
else
/usr/bin/step-ca-admin.sh enroll "$(hostname)" \
--ca-url https://tedge:8443 \
--allow-insecure-root
fi
}

while :; do
if enroll_device; then
echo "Enrollment was successful"
exit 0
fi
sleep 2
done

# restore previous working directory
cd "$OLD_PWD"
19 changes: 19 additions & 0 deletions images/common/utils/init-pki/init-pki.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/bin/sh
set -e
#
# Initialize the local pki
#

# Create env file from PID 1
# (as this is the old service which inherits the container environment variables)
echo "Loading environment from PID 1"
tr '\0' '\n' </proc/1/environ \
| grep -v "^\(_\|HOME\|PATH\|TERM\|HOSTNAME\|PWD\|SHLVL\)=" | tee > /etc/container.env

# Load and export env
set -a
# shellcheck disable=SC1091
. /etc/container.env
set +a

step-ca-init.sh
11 changes: 11 additions & 0 deletions images/debian-systemd/debian-systemd.dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ RUN echo "running" \
&& DEBIAN_FRONTEND=noninteractive apt-get -y --no-install-recommends install \
tedge-inventory-plugin \
c8y-command-plugin \
# Local PKI service for easy child device registration
tedge-pki-smallstep-ca \
&& systemctl disable c8y-firmware-plugin.service \
&& systemctl mask c8y-firmware-plugin.service

Expand All @@ -83,6 +85,15 @@ COPY common/config/sshd_config /etc/ssh/sshd_config
COPY common/optional-installer.sh .
RUN ./optional-installer.sh

# Device bootstrap (to run one-off commands on first boot)
COPY common/utils/configure-device/runner.sh /usr/share/configure-device/
COPY common/utils/configure-device/configure-device.service /lib/systemd/system/
RUN mkdir -p /usr/share/configure-device/scripts.d/ \
&& systemctl enable configure-device.service

# Configure device hooks
COPY common/utils/init-pki/init-pki.sh /usr/share/configure-device/scripts.d/30_init-pki

# Copy bootstrap script hooks
COPY common/config/bootstrap /etc/bootstrap

Expand Down
5 changes: 4 additions & 1 deletion images/debian-systemd/docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ services:
- DEVICE_ID=${DEVICE_ID:-}
- C8Y_BASEURL=${C8Y_BASEURL:-}
- C8Y_USER=${C8Y_USER:-}
- PROVISION_PASSWORD=${PROVISION_PASSWORD:-dummy}
volumes:
- etc:/etc

Expand All @@ -43,7 +44,7 @@ services:
child01:
<<: *child-container
environment:
- TEDGE_MQTT_DEVICE_TOPIC_ID=device/child01//
- PROVISION_PASSWORD=${PROVISION_PASSWORD:-dummy}
hostname: child01
volumes:
- child01_etc:/etc
Expand All @@ -52,6 +53,8 @@ services:
child02:
<<: *child-device-systemd
hostname: child02
environment:
- PROVISION_PASSWORD=${PROVISION_PASSWORD:-dummy}
volumes:
- child02_etc:/etc
- child02_logs:/var/log/tedge
Expand Down

0 comments on commit bda2c0e

Please sign in to comment.