Skip to content

Commit

Permalink
add Linux packages and container bootstrapping for controller and router
Browse files Browse the repository at this point in the history
  • Loading branch information
qrkourier committed Apr 4, 2024
1 parent 9db4a30 commit 4b3c25d
Show file tree
Hide file tree
Showing 42 changed files with 1,660 additions and 86 deletions.
1 change: 1 addition & 0 deletions .github/workflows/fablab-db-creation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ jobs:
build:
name: Build and Run
runs-on: ubuntu-latest
if: github.repository_owner == 'openziti'
steps:
- name: Checkout ziti
uses: actions/checkout@v4
Expand Down
11 changes: 7 additions & 4 deletions .github/workflows/publish-docker-images.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,14 @@ jobs:
uses: docker/build-push-action@v5
with:
builder: ${{ steps.buildx.outputs.name }}
context: ${{ github.workspace }}/dist/docker-images/ziti-controller/
context: ${{ github.workspace }}/
file: ${{ github.workspace }}/dist/docker-images/ziti-controller/Dockerfile
platforms: linux/amd64,linux/arm64
tags: ${{ steps.tagprep_ctrl.outputs.DOCKER_TAGS }}
build-args: |
ZITI_CLI_TAG=${{ env.ZITI_CLI_TAG }}
ZITI_CLI_IMAGE=${{ env.ZITI_CLI_IMAGE }}
DOCKER_BUILD_DIR=./dist/docker-images/ziti-controller
push: true

- name: Set Up Container Image Tags for Router Container
Expand All @@ -116,19 +118,20 @@ jobs:
if [[ "${{ github.ref }}" == "refs/heads/main" ]]; then
DOCKER_TAGS+=",${IMAGE_REPO}:latest"
fi
echo "DEBUG: DOCKER_TAGS=${DOCKER_TAGS}"
echo DOCKER_TAGS="${DOCKER_TAGS}" >> $GITHUB_OUTPUT
echo DOCKER_TAGS="${DOCKER_TAGS}" | tee -a $GITHUB_OUTPUT
- name: Build & Push Multi-Platform Router Container Image to Hub
uses: docker/build-push-action@v5
with:
builder: ${{ steps.buildx.outputs.name }}
context: ${{ github.workspace }}/dist/docker-images/ziti-router/
context: ${{ github.workspace }}/
file: ${{ github.workspace }}/dist/docker-images/ziti-router/Dockerfile
platforms: linux/amd64,linux/arm64
tags: ${{ steps.tagprep_router.outputs.DOCKER_TAGS }}
build-args: |
ZITI_CLI_TAG=${{ env.ZITI_CLI_TAG }}
ZITI_CLI_IMAGE=${{ env.ZITI_CLI_IMAGE }}
DOCKER_BUILD_DIR=./dist/docker-images/ziti-router
push: true

- name: Set Up Container Image Tags for Go Tunneler Container
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/publish-linux-packages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ jobs:
matrix:
package_name:
- openziti
- openziti-controller
- openziti-router
arch:
- goreleaser: amd64
gox: amd64
Expand Down
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
# Release 0.34.2

## What's New

* Deployments Alpha
* Linux packages provide systemd services for controller and router. Both depend on existing package `openziti` which provides the `ziti` command line tool.
* `openziti-controller` provides `ziti-controller.service`
* `openziti-router` provides `ziti-router.service`
* Container images for controller and router now share the bootstrapping logic with the packages, so they
support the same configuration options.

# Release 0.34.1

## What's New
Expand Down
4 changes: 4 additions & 0 deletions dist/cloudfront/get.openziti.io/routes.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,7 @@
- get: /zdew/
raw: /openziti/desktop-edge-win/main/release-streams/
file: latest.json

- get: /dist/
raw: /openziti/ziti/{{GITHUB_SHA}}/dist/
file: /docker-images/ziti-router/compose.yml
39 changes: 39 additions & 0 deletions dist/dist-packages/linux/nfpm-openziti-controller.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# nfpm configuration file
#
# check https://nfpm.goreleaser.com/configuration for detailed usage
#
name: openziti-controller
arch: ${GOARCH}
platform: linux
version: ${ZITI_VERSION}
prerelease: ${ZITI_REV}
maintainer: ${ZITI_MAINTAINER}
description: >
Provides a system service for running an OpenZiti Controller
vendor: ${ZITI_VENDOR}
homepage: ${ZITI_HOMEPAGE}
license: Apache-2.0
# Contents to add to the package.
contents:
- dst: /lib/systemd/system/
src: ./dist/dist-packages/linux/openziti-controller/ziti-controller.service

- dst: /opt/openziti/etc/controller
type: dir
file_info:
mode: 0755

- dst: /opt/openziti/etc/controller/
src: ./dist/dist-packages/linux/openziti-controller/env
type: config|noreplace

- dst: /opt/openziti/etc/controller/
src: ./dist/dist-packages/linux/openziti-controller/bootstrap.bash

- dst: /opt/openziti/etc/controller/
src: ./dist/dist-packages/linux/openziti-controller/entrypoint.bash
depends:
- openziti # ziti CLI

scripts:
postinstall: ./dist/dist-packages/linux/openziti-controller/postinstall.bash
41 changes: 41 additions & 0 deletions dist/dist-packages/linux/nfpm-openziti-router.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# nfpm configuration file
#
# check https://nfpm.goreleaser.com/configuration for detailed usage
#
name: openziti-router
arch: ${GOARCH}
platform: linux
version: ${ZITI_VERSION}
prerelease: ${ZITI_REV}
maintainer: ${ZITI_MAINTAINER}
description: >
Provides a system service for running an OpenZiti Router
vendor: ${ZITI_VENDOR}
homepage: ${ZITI_HOMEPAGE}
license: Apache-2.0
# Contents to add to the package.
contents:
- dst: /lib/systemd/system/
src: ./dist/dist-packages/linux/openziti-router/ziti-router.service

- dst: /opt/openziti/etc/router
type: dir
file_info:
mode: 0755

- dst: /opt/openziti/etc/router/
src: ./dist/dist-packages/linux/openziti-router/env
type: config|noreplace

- dst: /opt/openziti/etc/router/
src: ./dist/dist-packages/linux/openziti-router/bootstrap.bash

- dst: /opt/openziti/etc/router/
src: ./dist/dist-packages/linux/openziti-router/entrypoint.bash

scripts:
postinstall: ./dist/dist-packages/linux/openziti-router/postinstall.bash
preremove: ./dist/dist-packages/linux/openziti-router/preremove.bash

depends:
- openziti # ziti CLI
8 changes: 1 addition & 7 deletions dist/dist-packages/linux/nfpm-openziti.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ name: openziti
arch: ${GOARCH}
platform: linux
version: ${ZITI_VERSION}
prerelease: ${ZITI_REV}
maintainer: ${ZITI_MAINTAINER}
description: >
The openziti package provides the ziti executable binary as a command line
Expand All @@ -23,10 +24,3 @@ contents:
type: symlink
replaces:
- ziti-cli

# packager-neutral scripts may be overridden by packager-specific scripts
# scripts:
# preinstall: ./scripts/preinstall.sh
# postinstall: ./scripts/postinstall.sh
# preremove: ./scripts/preremove.sh
# postremove: ./scripts/postremove.sh
208 changes: 208 additions & 0 deletions dist/dist-packages/linux/openziti-controller/bootstrap.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
#
# bootstrap the OpenZiti Controller with PKI, config file, and database
#


#
# defaults
#

function makePki() {
#
# create root and intermediate CA
#

# used by "ziti pki create server" as DNS SAN
if [ -z "${ZITI_CTRL_ADVERTISED_ADDRESS:-}" ]; then
echo "ERROR: ZITI_CTRL_ADVERTISED_ADDRESS must be set, i.e., the FQDN by which all devices will reach the"\
"controller and verify the server certificate" >&2
return 1
fi

if [ "$ZITI_CA_FILE" == "$ZITI_INTERMEDIATE_FILE" ]; then
echo "ERROR: ZITI_CA_FILE and ZITI_INTERMEDIATE_FILE must be different" >&2
return 1
fi

ZITI_CA_CERT="${ZITI_PKI_ROOT}/${ZITI_CA_FILE}/certs/${ZITI_CA_FILE}.cert"
if [ ! -s "${ZITI_CA_CERT}" ]; then
ziti pki create ca \
--pki-root "${ZITI_PKI_ROOT}" \
--ca-file "${ZITI_CA_FILE}"
fi

ZITI_PKI_SIGNER_CERT="${ZITI_PKI_ROOT}/${ZITI_INTERMEDIATE_FILE}/certs/${ZITI_INTERMEDIATE_FILE}.cert"
ZITI_PKI_SIGNER_KEY="${ZITI_PKI_ROOT}/${ZITI_INTERMEDIATE_FILE}/keys/${ZITI_INTERMEDIATE_FILE}.key"
if [[ ! -s "$ZITI_PKI_SIGNER_CERT" && ! -s "$ZITI_PKI_SIGNER_KEY" ]]; then
ziti pki create intermediate \
--pki-root "${ZITI_PKI_ROOT}" \
--ca-name "${ZITI_CA_FILE}" \
--intermediate-file "${ZITI_INTERMEDIATE_FILE}"
elif [[ ! -s "$ZITI_PKI_SIGNER_CERT" || ! -s "$ZITI_PKI_SIGNER_KEY" ]]; then
echo "ERROR: $ZITI_PKI_SIGNER_CERT and $ZITI_PKI_SIGNER_KEY must both exist or neither exist as non-empty files" >&2
return 1
fi

#
# create server and client keys
#

if [ "$ZITI_SERVER_FILE" == "$ZITI_CLIENT_FILE" ]; then
echo "ERROR: ZITI_SERVER_FILE and ZITI_CLIENT_FILE must be different" >&2
return 1
fi

ZITI_PKI_CTRL_KEY="${ZITI_PKI_ROOT}/${ZITI_INTERMEDIATE_FILE}/keys/${ZITI_SERVER_FILE}.key"
if ! [ -s "$ZITI_PKI_CTRL_KEY" ]; then
ziti pki create key \
--pki-root "${ZITI_PKI_ROOT}" \
--ca-name "${ZITI_INTERMEDIATE_FILE}" \
--key-file "${ZITI_SERVER_FILE}"
fi

# use the server key for both client and server certs until "ziti create config controller" supports separate keys for
# each
# CLIENT_KEY_FILE="${ZITI_PKI_ROOT}/${ZITI_INTERMEDIATE_FILE}/keys/${ZITI_CLIENT_FILE}.key"
# if ! [ -s "$CLIENT_KEY_FILE" ]; then
# ziti pki create key \
# --pki-root "${ZITI_PKI_ROOT}" \
# --ca-name "${ZITI_INTERMEDIATE_FILE}" \
# --key-file "${ZITI_CLIENT_FILE}"
# fi

#
# create server and client certs
#

# server cert
ZITI_PKI_CTRL_SERVER_CERT="${ZITI_PKI_ROOT}/${ZITI_INTERMEDIATE_FILE}/certs/${ZITI_SERVER_FILE}.chain.pem"
if [[ "${ZITI_AUTO_RENEW_CERTS}" == true || ! -s "$ZITI_PKI_CTRL_SERVER_CERT" ]]; then
ziti pki create server \
--pki-root "${ZITI_PKI_ROOT}" \
--ca-name "${ZITI_INTERMEDIATE_FILE}" \
--key-file "${ZITI_SERVER_FILE}" \
--server-file "${ZITI_SERVER_FILE}" \
--dns "${ZITI_CTRL_ADVERTISED_ADDRESS}" \
--allow-overwrite
fi

# client cert
# use the server key for both client and server certs until "ziti create config controller" supports separate keys for
# each
ZITI_PKI_CTRL_CERT="${ZITI_PKI_ROOT}/${ZITI_INTERMEDIATE_FILE}/certs/${ZITI_CLIENT_FILE}.cert"
if [[ "${ZITI_AUTO_RENEW_CERTS}" == true || ! -s "$ZITI_PKI_CTRL_CERT" ]]; then
ziti pki create client \
--pki-root "${ZITI_PKI_ROOT}" \
--ca-name "${ZITI_INTERMEDIATE_FILE}" \
--key-file "${ZITI_SERVER_FILE}" \
--client-file "${ZITI_CLIENT_FILE}" \
--allow-overwrite
fi

}

function makeConfig() {
#
# create config file
#

# enforce first argument is a non-empty string that does not begin with "--" (long option prefix)
if [[ -n "${1:-}" && ! "${1}" =~ ^-- ]]; then
local ZITI_CTRL_CONFIG_FILE="${1}"
shift
else
echo "ERROR: no config file path provided" >&2
return 1
fi
shopt -u nocasematch # toggle on case-sensitive comparison

# used by "ziti create config controller" as advertised address
if [ -z "${ZITI_CTRL_ADVERTISED_ADDRESS:-}" ]; then
echo "ERROR: ZITI_CTRL_ADVERTISED_ADDRESS must be set, i.e., the FQDN by which all devices will reach the"\
" controller and verify the server certificate" >&2
return 1
fi

# set the path to the root CA cert
export ZITI_PKI_CTRL_CA="${ZITI_PKI_ROOT}/${ZITI_CA_FILE}/certs/${ZITI_CA_FILE}.cert"

# set the URI of the edge-client API (uses same TCP port); e.g., ztAPI: ziti.example.com:1280
export ZITI_CTRL_EDGE_ADVERTISED_ADDRESS="${ZITI_CTRL_ADVERTISED_ADDRESS}" \
ZITI_CTRL_EDGE_ADVERTISED_PORT="${ZITI_CTRL_ADVERTISED_PORT}"

# export the vars that were assigned inside this script to set the path to the server and client certs and their common
# private key, and the intermediate (signer) CA cert and key
export ZITI_PKI_CTRL_SERVER_CERT \
ZITI_PKI_CTRL_CERT \
ZITI_PKI_CTRL_KEY \
ZITI_PKI_SIGNER_CERT \
ZITI_PKI_SIGNER_KEY \
ZITI_CTRL_ADVERTISED_ADDRESS \
ZITI_CTRL_ADVERTISED_PORT \
ZITI_CTRL_BIND_ADDRESS \
ZITI_CTRL_EDGE_BIND_ADDRESS

if [[ ! -s "${ZITI_CTRL_CONFIG_FILE}" || "${1:-}" == --force ]]; then
ziti create config controller \
--output "${ZITI_CTRL_CONFIG_FILE}"
fi

}

function makeDatabase() {

#
# create default admin in database
#

if [ -s "${ZITI_CTRL_DATABASE_FILE}" ]; then
return 0
fi

# if the database file is in a subdirectory, create the directory so that "ziti controller edge init" can load the
# controller config.yml which contains a check to ensure the directory exists
DB_DIR="$(dirname "${ZITI_CTRL_DATABASE_FILE}")"
if ! [ "$DB_DIR" == "." ]; then
mkdir -p "$DB_DIR"
fi

: "${ZITI_PWD:=$(< "/run/credentials/${UNIT_NAME:-ziti-controller.service}/ZITI_PWD")}"
if [ -n "${ZITI_PWD}" ]; then
ziti controller edge init "${ZITI_CTRL_CONFIG_FILE}" \
--username "${ZITI_USER}" \
--password "${ZITI_PWD}"
else
echo "ERROR: need admin password; use LoadCredential in"\
" /lib/systemd/system/ziti-controller.service or set env var ZITI_PWD with at least 5 characters" >&2
return 1
fi

}

function bootstrap() {

if [ -n "${1:-}" ]; then
local ZITI_CTRL_CONFIG_FILE="${1}"
echo "DEBUG: using config file path: $(realpath "${ZITI_CTRL_CONFIG_FILE}")" >&2
else
echo "ERROR: no config file path provided" >&2
return 1
fi

# make PKI unless it exists
if [ "${ZITI_BOOTSTRAP_PKI}" == true ]; then
makePki
fi

# make config file unless it exists, set force to overwrite every startup
if [ "${ZITI_BOOTSTRAP_CONFIG}" == true ]; then
makeConfig "${ZITI_CTRL_CONFIG_FILE}"
elif [ "${ZITI_BOOTSTRAP_CONFIG}" == force ]; then
makeConfig "${ZITI_CTRL_CONFIG_FILE}" --force
fi

# make database unless it exists
if [ "${ZITI_BOOTSTRAP_DATABASE}" == true ]; then
makeDatabase
fi
}
Loading

0 comments on commit 4b3c25d

Please sign in to comment.