Skip to content

Commit

Permalink
Add stunnel container image
Browse files Browse the repository at this point in the history
  • Loading branch information
dcermak and dmpop committed Dec 6, 2024
1 parent 907652c commit 4573b11
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/bci_build/package/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1459,6 +1459,7 @@ def generate_disk_size_constraints(size_gb: int) -> str:
from .appcontainers import PCP_CONTAINERS # noqa: E402
from .appcontainers import PROMETHEUS_CONTAINERS # noqa: E402
from .appcontainers import REGISTRY_CONTAINERS # noqa: E402
from .appcontainers import STUNNEL_CONTAINERS # noqa: E402
from .appcontainers import THREE_EIGHT_NINE_DS_CONTAINERS # noqa: E402
from .appcontainers import TRIVY_CONTAINERS # noqa: E402
from .base import BASE_CONTAINERS # noqa: E402
Expand Down Expand Up @@ -1541,6 +1542,7 @@ def generate_disk_size_constraints(size_gb: int) -> str:
*GCC_CONTAINERS,
*SPACK_CONTAINERS,
*KEA_DHCP_CONTAINERS,
*STUNNEL_CONTAINERS,
)
}

Expand Down
36 changes: 36 additions & 0 deletions src/bci_build/package/appcontainers.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from bci_build.package.helpers import generate_package_version_check
from bci_build.package.versions import format_version
from bci_build.package.versions import get_pkg_version
from bci_build.registry import publish_registry


def _envsubst_pkg_name(os_version: OsVersion) -> str:
Expand Down Expand Up @@ -442,3 +443,38 @@ def _get_nginx_kwargs(os_version: OsVersion):
)
for os_version in (OsVersion.TUMBLEWEED,)
]

STUNNEL_CONTAINERS = [
ApplicationStackContainer(
name="stunnel",
os_version=os_version,
tag_version=(tag_ver := "5"),
is_latest=os_version in CAN_BE_LATEST_OS_VERSION,
from_target_image=generate_from_image_tag(os_version, "bci-micro"),
version=(stunnel_version_re := "%%stunnel_re%%"),
pretty_name="Stunnel",
package_list=["stunnel"],
replacements_via_service=[
Replacement(stunnel_version_re, package_name="stunnel")
],
extra_files={
"entrypoint.sh": (
(stunnel_dir := Path(__file__).parent / "stunnel") / "entrypoint.sh"
).read_bytes(),
"stunnel.conf": (stunnel_dir / "stunnel.conf").read_bytes(),
},
_publish_registry=publish_registry(os_version, app_collection=True),
build_stage_custom_end=generate_package_version_check(
"stunnel", tag_ver, ParseVersion.MAJOR, use_target=True
),
custom_end=f"""COPY entrypoint.sh /usr/local/bin/
COPY stunnel.conf /etc/stunnel/stunnel.conf
{DOCKERFILE_RUN} chmod 0755 /usr/local/bin/entrypoint.sh; \
chown --recursive stunnel /etc/stunnel
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
CMD ["/usr/sbin/stunnel"]
USER stunnel
""",
)
for os_version in ALL_NONBASE_OS_VERSIONS
]
80 changes: 80 additions & 0 deletions src/bci_build/package/stunnel/README.md.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# {{ image.pretty_name }} Container Image

{% include 'badges.j2' %}


## Description

Stunnel is an open-source multi-platform application that provides a universal
TLS/SSL tunneling service.


## How to use this image

By default, the Stunnel container image launches `stunnel` using a minimal
configuration file that specifies the following:
- run in foreground
- load further configuration files from `/etc/stunnel/conf.d`

Custom configuration files must be placed into the directory
`/etc/stunnel/conf.d`.

The container entry point configures TLS/SSL automatically by setting the key
and certificate to the values of the environment variables `STUNNEL_KEY` and
`STUNNEL_CERT`. If one of the environment variables is unset, then the
entrypoint defaults to `/etc/stunnel/stunnel.key` for `STUNNEL_KEY` and
`/etc/stunnel/stunnel.pem` for `STUNNEL_CERT`.

The entrypoint can set up a single service via environment variables, so that
the user doesn't have to write and mount their own configuration file. This can
be specified via the environment variables `STUNNEL_SERVICE_NAME`,
`STUNNEL_ACCEPT` and `STUNNEL_CONNECT`:

- `STUNNEL_SERVICE_NAME`: name or otherwise unique identifier of the service
(used for documentation purpose only)

- `STUNNEL_ACCEPT`: address on which new connections should be accepted. It can
be either a hostname and a port number or just a port number (in which case,
localhost is assumed to be the host)

- `STUNNEL_CONNECT`: address on which the unencrypted service is listening and
to which stunnel connects. It can be either a hostname and port number or just
a port number (in which case, localhost is assumed to be the host)


For example, to create an SSL endpoint for a webserver listening on port `8000`
on localhost, run the following command:

```bash
podman run --rm -d \
-p 8443:8443 \
-e STUNNEL_SERVICE_NAME=webserver \
-e STUNNEL_ACCEPT=0.0.0.0:8443 \
-e STUNNEL_CONNECT=0.0.0.0:8000 \
-v=path/to/server.pem:/etc/stunnel/stunnel.pem:Z \
-v=path/to/server.crt:/etc/stunnel/stunnel.crt:Z \
{{ image.pretty_reference }}
```


### Logging

Stunnel supports eight log levels, from 0 (emergency) to 7 (debug) with 5
(notice) being the default. The log level can be configured via the environment
variable `STUNNEL_DEBUG` using either the number or the log level name. For the
supported logging levels, refer to the [upstream
documentation](https://www.stunnel.org/static/stunnel.html#debug-FACILITY.-LEVEL).


### Pitfalls

The Stunnel container image is configured to launch `stunnel` as the `stunnel`
user. But by default, files mounted into a running container belong to the
`root` user. Set the file permissions of mounted files accordingly, so that
non-owners and non-group members can read them.

Stunnel's `inetd` mode is not supported in the container image, and it does not
ship a package manager for installing any services.


{% include 'licensing_and_eula.j2' %}
24 changes: 24 additions & 0 deletions src/bci_build/package/stunnel/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/bin/bash

set -eo pipefail

STUNNEL_CERT="${STUNNEL_CERT:-/etc/stunnel/stunnel.pem}"
STUNNEL_KEY="${STUNNEL_KEY:-/etc/stunnel/stunnel.key}"

if [[ -n ${STUNNEL_DEBUG} ]]; then
echo "debug = ${STUNNEL_DEBUG}" > /etc/stunnel/conf.d/000debug.conf
fi

conf="/etc/stunnel/conf.d/container-ssl.conf"
echo "cert = ${STUNNEL_CERT}" > $conf
echo "key = ${STUNNEL_KEY}" >> $conf


if [[ -n "${STUNNEL_SERVICE_NAME}" ]] && [[ -n "${STUNNEL_ACCEPT}" ]] && [[ -n "${STUNNEL_CONNECT}" ]]; then
conf="/etc/stunnel/conf.d/container.conf"
echo "[${STUNNEL_SERVICE_NAME}]" > $conf
echo "accept = ${STUNNEL_ACCEPT}" >> $conf
echo "connect = ${STUNNEL_CONNECT}" >> $conf
fi

exec "$@"
2 changes: 2 additions & 0 deletions src/bci_build/package/stunnel/stunnel.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
foreground = yes
include = /etc/stunnel/conf.d

0 comments on commit 4573b11

Please sign in to comment.