Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
127 changed files
with
544,413 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
FROM tier/shibboleth_sp | ||
|
||
LABEL version="0.0.1" | ||
|
||
RUN yum update -y && \ | ||
yum clean all | ||
|
||
COPY container_files/httpd/httpd.conf /etc/httpd/conf/httpd.conf | ||
COPY container_files/httpd/proxy.conf /etc/httpd/conf.d/proxy.conf | ||
COPY container_files/httpd/shib.conf /etc/httpd/conf.d/shib.conf | ||
COPY container_files/httpd/ssl.conf /etc/httpd/conf.d/ssl.conf | ||
COPY container_files/httpd/vhost.conf /etc/httpd/conf.d/vhost.conf | ||
COPY container_files/httpd/00-mpm.conf /etc/httpd/conf.modules.d/00-mpm.conf | ||
|
||
COPY container_files/shibboleth/attribute-map.xml /etc/shibboleth/attribute-map.xml | ||
COPY container_files/shibboleth/shibboleth2.xml.tpl /etc/shibboleth/shibboleth2.xml.tpl | ||
|
||
COPY container_files/system/supervisord.conf /etc/supervisor/supervisord.conf | ||
|
||
COPY --chown=root:root container_files/proxy-entrypoint.sh /usr/local/bin/proxy-entrypoint.sh | ||
RUN chmod 755 /usr/local/bin/proxy-entrypoint.sh | ||
ENTRYPOINT [ "/usr/local/bin/proxy-entrypoint.sh" ] | ||
|
||
# From base image | ||
CMD [ "/usr/local/bin/startup.sh" ] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,133 @@ | ||
# docker-shib-proxy | ||
A SAML-authenticating HTTPS reverse proxy using Shibboleth | ||
|
||
|
||
## Introduction | ||
|
||
This repository builds a Docker container image that acts as an HTTPS reverse | ||
proxy in front of a web application. The proxy authenticates a visitor using | ||
SAML, and passes the username and group memberships to the web application as | ||
HTTP headers: | ||
|
||
* `X-Forwarded-User`: Contains the `eppn` attribute value for the | ||
user | ||
|
||
* `X-Forwarded-Groups`: Contains the `isMemberOf` attribute values for the | ||
user, separated by semicolons | ||
|
||
IMPORTANT: To prevent visitors from spoofing the HTTP headers, you | ||
MUST ensure that your web application *only* allows incoming requests | ||
from the reverse proxy, or otherwise that it doesn't accept the headers above | ||
from any clients _except_ the reverse proxy. A typical configuration would be | ||
to run the proxy as a sidecar container to your web application, such that all | ||
HTTP(S) requests must flow through the proxy. | ||
|
||
|
||
## Quick Start | ||
|
||
To try the container in a test environment: | ||
|
||
1. Change to the `tests` directory, and bring up the `proxy` service and its | ||
dependencies from `docker-compose.yml`: | ||
``` | ||
cd tests | ||
docker-compose up -d proxy | ||
``` | ||
|
||
2. Update `/etc/hosts` to add `idp.example.edu` and | ||
`sptest.example.edu` as aliases for `localhost`: | ||
``` | ||
# /etc/hosts | ||
127.0.0.1 localhost idp.example.edu sp.example.edu | ||
``` | ||
|
||
3. In a web browser, visit https://sptest.example.edu:8443. You should be | ||
redirected to the test IdP at https://idp.example.edu. | ||
|
||
4. In the IdP login form, use `banderson` for the username, and | ||
`password` for the password. | ||
|
||
5. After logging in, you should see a PHP information page. Under the | ||
"HTTP Headers Information" heading, yous should see the following | ||
headers set: | ||
|
||
| Header | Value | | ||
|--------------------|------------------------------------------------------------------------------------| | ||
| X-Forwarded-User | banderson@example.edu | | ||
| X-Forwarded-Groups | cn=developers,ou=Groups,dc=internet2,dc=edu;cn=users,ou=Groups,dc=internet2,dc=edu | | ||
|
||
6. When finished, shut down the services from `docker-compose.yml`: | ||
``` | ||
docker-compose down | ||
``` | ||
|
||
|
||
## Configuration | ||
|
||
The container expects several environment variables at runtime. See | ||
`tests/docker-compose.yml` for a working example. In a production environment, | ||
these variables would be set by your orchestration system (for example, AWS | ||
Elastic Container Service or Kubernetes), and sensitive information (such as | ||
private keys) would be stored securely (for example, using AWS Systems Manager | ||
Parameter Store, AWS Secrets Manager, or HashiCorp Vault). | ||
|
||
### Required Variables | ||
|
||
_(Note: To establish trust with the IdP, you must either specify | ||
`SAML_IDP_METADATA`, or specify `SAML_IDP_METADATA_URL` and | ||
`SAML_IDP_SIGNING_CERT`.)_ | ||
|
||
* `FRONT_HTTPS_PORT`: Set this to the canonical front-end HTTPS port, to ensure | ||
that URLs are constructed correctly. (This may be different from `HTTPS_PORT`, | ||
if the proxy is behind a load balancer or another HTTPS proxy.) | ||
|
||
* `FRONT_HOSTNAME`: Set this to the canonical, fully-qualified domain name for | ||
the proxy, for example "app.example.edu". (This may be different from the | ||
proxy's hostname, if the proxy is behind a load balancer or another HTTPS | ||
proxy.) | ||
|
||
* `HTTPS_PORT`: The port on which the proxy should listen for HTTPS connections | ||
|
||
* `SAML_ENCRYPTION_CERT`: A base-64 encoded SAML encryption certificate, | ||
beginning with "-----BEGIN CERTIFICATE-----" | ||
|
||
* `SAML_ENCRYPTION_KEY`: The base-64 encoded private key for | ||
`SAML_ENCRYPTION_CERT`, beginning with "-----BEGIN PRIVATE KEY-----" | ||
|
||
* `SAML_ENTITYID`: The SAML entity ID for the proxy, for example | ||
"https://app-proxy.example.edu/shibboleth" | ||
|
||
* `SAML_IDP_ENTITYID`: The SAML entity ID for a trusted SAML identity provider | ||
or SAML proxy, for example "https://idp.example.edu/idp/shibboleth" | ||
|
||
* `SAML_IDP_METADATA` (Optional): SAML metadata for `SAML_IDP_ENTITYID`; should | ||
include a single `<EntityDescriptor>` element. Required if | ||
`SAML_IDP_METADATA_URL` is not set. | ||
|
||
* `SAML_IDP_METADATA_URL` (Optional): URL from which to retrieve the IdP | ||
metadata file. Required if `SAML_IDP_METADATA` is not set. | ||
|
||
* `SAML_IDP_SIGNING_CERT` (Optional): The base-64 encoded SAML signing | ||
certificate used to verify the IdP metadata signature, beginning with | ||
"-----BEGIN CERTIFICATE-----". Required if `SAML_IDP_METADATA_URL` is set. | ||
|
||
* `SAML_SIGNING_CERT`: A base-64 encoded SAML signing certificate | ||
beginning with "-----BEGIN CERTIFICATE-----" | ||
|
||
* `SAML_SIGNING_KEY`: The base-64 encoded private key for | ||
`SAML_SIGNING_CERT`, beginning with "-----BEGIN PRIVATE KEY-----" | ||
|
||
* `TLS_CERT`: A base-64 encoded TLS server certificate used for HTTPS | ||
connections, beginning with "-----BEGIN CERTIFICATE-----" | ||
|
||
* `TLS_PRIVATE_KEY`: The base-64 encoded private key for `TLS_CERT`, beginning | ||
with "-----BEGIN RSA PRIVATE KEY-----" | ||
|
||
### Optional Variables | ||
|
||
* `HTTPD_ARGS`: Additional arguments to be passed to `httpd` by `supervisord`. | ||
If the proxy is behind a load balancer or another HTTP proxy, set this to | ||
"-DProxied" | ||
|
||
* `TIER_BEACON_OPT_OUT`: Opt out of reporting telemetry to Internet2 (from | ||
the `tier/shibboleth_sp` base container image). Set to "true" or "false". |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
#!/usr/bin/env bash | ||
|
||
echo "[INFO] $0 started at `date`" | ||
|
||
# Read the commit hash | ||
read -r commit_hash<<<$(git rev-parse --short HEAD) | ||
echo "[INFO] Commit hash: \"$commit_hash\"" | ||
|
||
image_name=shib-proxy | ||
|
||
# Build the container image | ||
echo "[INFO] Building the container image" | ||
docker build -t $image_name:$commit_hash . | ||
|
||
echo "[INFO] $0 finished at `date`" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
#!/usr/bin/env bash | ||
|
||
echo "[INFO] $0 started at `date`" | ||
|
||
# Read the commit hash | ||
read -r commit_hash<<<$(git rev-parse --short HEAD) | ||
echo "[INFO] Commit hash: \"$commit_hash\"" | ||
|
||
image_name=shib-proxy | ||
|
||
# Read the version | ||
read -r version<<<$(docker inspect --format='{{.Config.Labels.version}}' $image_name:$commit_hash) | ||
if [[ "$version" == "" ]]; then | ||
echo "[ERROR] Unable to inspect version label for image $image_name:$commit_hash" | ||
exit 1 | ||
fi | ||
echo "[INFO] Version: \"$version\"" | ||
read -r major minor patch<<<$(echo $version | tr . ' ') | ||
echo "[DEBUG] major.minor.patch=\"$major.$minor.$patch\"" | ||
|
||
# Tag the image | ||
echo "[INFO] Tagging the container image" | ||
docker tag $image_name:$commit_hash ${ECR_HOSTNAME}/${image_name}:$major.$minor.$patch | ||
docker tag $image_name:$commit_hash ${ECR_HOSTNAME}/${image_name}:$major.$minor | ||
docker tag $image_name:$commit_hash ${ECR_HOSTNAME}/${image_name}:$major | ||
|
||
# Push the image to a registry if REPOSITORY_BASE is defined | ||
if [ -z "$ECR_HOSTNAME" ]; then | ||
echo "[ERROR] Unable to push image (ECR_HOSTNAME not specified)" | ||
else | ||
echo "[DEBUG] ECR_HOSTNAME=\"$ECR_HOSTNAME\"" | ||
docker push ${ECR_HOSTNAME}/${image_name}:latest | ||
docker push ${ECR_HOSTNAME}/${image_name}:$major.$minor.$patch | ||
docker push ${ECR_HOSTNAME}/${image_name}:$major.$minor | ||
docker push ${ECR_HOSTNAME}/${image_name}:$major | ||
fi | ||
|
||
echo "[INFO] $0 finished at `date`" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
#!/usr/bin/env bash | ||
|
||
echo "Logging in to ECR repository" | ||
$(aws ecr get-login --no-include-email) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
#!/usr/bin/env bash | ||
|
||
# Run automated tests | ||
# | ||
# Example: | ||
# | ||
# ci/test.sh | ||
# | ||
# Returns 0 if tests pass, or 1 if tests fail. | ||
|
||
echo "[INFO] $0 started at `date`" | ||
|
||
# Read the commit hash | ||
read -r commit_hash<<<$(git rev-parse --short HEAD) | ||
echo "[INFO] Commit hash: \"$commit_hash\"" | ||
|
||
image_name=shib-proxy | ||
|
||
# Bring up the proxy and its dependencies | ||
cd tests | ||
export PROXY_IMAGE_TAG="$commit_hash" | ||
docker-compose up -d proxy | ||
|
||
# Wait for the idp | ||
echo "[INFO] Waiting for idp" | ||
timeout --foreground 30 bash -c 'until printf "" 2>>/dev/null >>/dev/tcp/$0/$1; do sleep 1; done' idp 443 | ||
|
||
# Wait for the proxy | ||
echo "[INFO] Waiting for proxy" | ||
timeout --foreground 30 bash -c 'until printf "" 2>>/dev/null >>/dev/tcp/$0/$1; do sleep 1; done' proxy 8443 | ||
|
||
# Run the test container and store the exit code | ||
docker-compose run test python3 /tests/test.py | ||
if [ $? -eq 0 ] | ||
then | ||
echo "[INFO] Tests passed!" | ||
set rc=0 | ||
else | ||
echo "[ERROR] Tests failed!" | ||
set rc=1 | ||
fi | ||
|
||
# Shut down all containers | ||
docker-compose down | ||
|
||
echo "[INFO] $0 finished at `date`" | ||
|
||
# Exit with the return code from the test container | ||
exit $rc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# Select the MPM module which should be used by uncommenting exactly | ||
# one of the following LoadModule lines: | ||
|
||
# prefork MPM: Implements a non-threaded, pre-forking web server | ||
# See: http://httpd.apache.org/docs/2.4/mod/prefork.html | ||
# | ||
# LoadModule mpm_prefork_module modules/mod_mpm_prefork.so | ||
|
||
# worker MPM: Multi-Processing Module implementing a hybrid | ||
# multi-threaded multi-process web server | ||
# See: http://httpd.apache.org/docs/2.4/mod/worker.html | ||
# (Recommended for Shibboleth SP; see: | ||
# https://wiki.shibboleth.net/confluence/display/SP3/Apache) | ||
|
||
LoadModule mpm_worker_module modules/mod_mpm_worker.so | ||
|
||
# event MPM: A variant of the worker MPM with the goal of consuming | ||
# threads only for connections with active processing | ||
# See: http://httpd.apache.org/docs/2.4/mod/event.html | ||
# | ||
#LoadModule mpm_event_module modules/mod_mpm_event.so |
Oops, something went wrong.