Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
TIDO-505 Update base image (#3)
* Update Shib SP base image
* Update CentOS7 repos and test infrastructure
* Replace CentOS7 sample app image with official PHP image
* Replace ldap,shib idp with simplesamlphp idp
* Replace testing image and add selenium standalone image
* Test should run in headless mode
* Streamline test/release/clean
* Update Quickstart
dmartinez committed Aug 27, 2024
1 parent 87bd640 commit c7212de
Showing 121 changed files with 315 additions and 543,186 deletions.
8 changes: 4 additions & 4 deletions Dockerfile
@@ -1,9 +1,9 @@
FROM tier/shibboleth_sp
FROM i2incommon/shibboleth_sp:3.4.1_05152024_rocky9_multiarch

LABEL version="0.0.1"
LABEL version="${VERSION}"

RUN yum update -y && \
yum clean all
RUN dnf update -y && \
dnf 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
55 changes: 55 additions & 0 deletions Makefile
@@ -0,0 +1,55 @@
# This is the main interface into the repository for building the image of the Shibboleth SP reverse proxy.
#
# All targets assume they're running on a Linux or macOS host with Bash and Docker installed.
# Any other dependencies should be satisfied by containers.
#

.DEFAULT_GOAL := help

DEBUG = [DEBUG]
INFO = [INFO]
SUCCESS = [INFO]

VERSION := $(shell cat VERSION.txt)

compose := docker compose

.PHONY: all
all: build

.PHONY: build
build: ## Build the Docker image
$(compose) build proxy
@echo "$(SUCCESS) Successfully built!"

.PHONY: clean
clean: ## Remove build artifacts
$(compose) down --rmi all
@echo "$(SUCCESS) All clean!"

.PHONY: help
help: ## Display this help (default)
@echo "Targets:"
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort \
| awk 'BEGIN {FS = ":.*?## "}; {printf " %-17s%s\n", $$1, $$2}'

.PHONY: release
release: ## Build the Docker image with the tagged version for release
VERSION=${VERSION} $(compose) build proxy
@docker images --format "{{.Repository}}:{{.Tag}}" | grep '^shib-proxy:' | \
while read -r line; do \
tag=$$(echo $$line | awk -F: '{print $$2}'); \
if [ "$$tag" != "$(VERSION)" ]; then \
echo "${INFO} Removing tag - $$tag"; \
docker rmi shib-proxy:$$tag; \
fi \
done
@echo "$(SUCCESS) Successfully built!"

.PHONY: test
test: ## Run the tests on the proxy Docker image
$(compose) up -d selenium-firefox
@echo "${INFO} Waiting for services to come up..."
@sleep 30
$(compose) up test
$(compose) down
66 changes: 32 additions & 34 deletions README.md
@@ -5,15 +5,8 @@ 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
proxy in front of a web application. The proxy can authenticate a visitor using
SAML.

IMPORTANT: To prevent visitors from spoofing the HTTP headers, you
MUST ensure that your web application *only* allows incoming requests
@@ -25,47 +18,52 @@ HTTP headers:

## 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
To try the container in a test environment the first thing to do is 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
Now, there are two ways to do testing:
- **Automated**

Run
```
make test
```

- **Manual**

1. Run
```
docker compose up -d proxy
```

2. In a web browser, visit https://sptest.example.edu. 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.
3. In the IdP login form, use `user1` for the username, and
`user1pass` 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:
4. After logging in, you should see a PHP information page. Under the
"Headers" heading, yous should see the following, letting you know you successsfully authenticated using the proxy:

| 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 |
| Header | Value |
|--------------------|--------------------------------|
| Referer | "http://idp.example.edu:8080/" |
| X-Forwarded-Host | "sptest.example.edu" |

6. When finished, shut down the services from `docker-compose.yml`:
```
docker-compose down
```
5. 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,
`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
1 change: 1 addition & 0 deletions VERSION.txt
@@ -0,0 +1 @@
0.0.2
15 changes: 0 additions & 15 deletions ci/build.sh

This file was deleted.

74 changes: 0 additions & 74 deletions ci/deploy.sh

This file was deleted.

4 changes: 0 additions & 4 deletions ci/login.sh

This file was deleted.

49 changes: 0 additions & 49 deletions ci/test.sh

This file was deleted.

147 changes: 79 additions & 68 deletions tests/docker-compose.yml → docker-compose.yml
@@ -1,52 +1,55 @@
version: "3"

networks:
app-proxy:
data-idp:
proxy-test:
idp-test:
proxy-net:

services:

app:
build:
context: "./containers/app"
context: "./tests/containers/app"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
networks:
- app-proxy

data:
build:
context: "./containers/ldap"
networks:
- data-idp
- proxy-net
ports:
- "80:80"

idp:
build:
context: "./containers/idp"
depends_on:
- data
image: jamedjo/test-saml-idp
networks:
data-idp:
idp-test:
proxy-net:
aliases:
- idp.example.edu
ports:
- "443:443"
- "8080:8080"
- "8443:8443"
environment:
LDAP_HOSTNAME: data
LDAP_PORT: 389
SIMPLESAMLPHP_SP_ENTITY_ID: https://sptest.example.edu/shibboleth
SIMPLESAMLPHP_SP_ASSERTION_CONSUMER_SERVICE: https://sptest.example.edu/Shibboleth.sso/SAML2/POST
healthcheck:
test: ["CMD", "curl", "-f", "--insecure", "http://localhost:8080/simplesaml/module.php/core/frontpage_welcome.php"]
volumes:
- "./tests/containers/idp/users.php:/var/www/simplesamlphp/config/authsources.php"

proxy:
build:
context: ".."
image: shib-proxy:${PROXY_IMAGE_TAG}
context: "."
image: shib-proxy:${VERSION:-latest}
ports:
- "8443:8443"
- "443:443"
networks:
proxy-net:
aliases:
- sptest.example.edu
depends_on:
- app
- idp
environment:
TIER_BEACON_OPT_OUT: 'true'
FRONT_HOSTNAME: sptest.example.edu
FRONT_HTTPS_PORT: 8443
HTTPS_PORT: 8443
FRONT_HTTPS_PORT: 443
HTTPS_PORT: 443
PROXYPASS_URL: http://app/
SAML_ENCRYPTION_CERT: |
-----BEGIN CERTIFICATE-----
@@ -115,44 +118,30 @@ services:
/oz8xKl5PKwOrvk2DH+FwaAg
-----END PRIVATE KEY-----
SAML_ENTITYID: https://sptest.example.edu/shibboleth
SAML_IDP_ENTITYID: https://idp.example.edu/idp/shibboleth
SAML_IDP_ENTITYID: http://idp.example.edu:8080/simplesaml/saml2/idp/metadata.php
SAML_IDP_METADATA_URL: http://idp.example.edu:8080/simplesaml/saml2/idp/metadata.php
SAML_IDP_METADATA: |
<EntityDescriptor entityID="https://idp.example.edu/idp/shibboleth" xmlns="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:shibmd="urn:mace:shibboleth:metadata:1.0" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<Extensions>
<shibmd:Scope regexp="false">example.edu</shibmd:Scope>
</Extensions>
<KeyDescriptor use="signing">
<ds:KeyInfo>
<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" entityID="http://idp.example.edu:8080/simplesaml/saml2/idp/metadata.php">
<md:IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<md:KeyDescriptor use="signing">
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data>
<ds:X509Certificate>MIIDXTCCAkWgAwIBAgIJALmVVuDWu4NYMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwHhcNMTYxMjMxMTQzNDQ3WhcNNDgwNjI1MTQzNDQ3WjBFMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzUCFozgNb1h1M0jzNRSCjhOBnR+uVbVpaWfXYIR+AhWDdEe5ryY+CgavOg8bfLybyzFdehlYdDRgkedEB/GjG8aJw06l0qF4jDOAw0kEygWCu2mcH7XOxRt+YAH3TVHa/Hu1W3WjzkobqqqLQ8gkKWWM27fOgAZ6GieaJBN6VBSMMcPey3HWLBmc+TYJmv1dbaO2jHhKh8pfKw0W12VM8P1PIO8gv4Phu/uuJYieBWKixBEyy0lHjyixYFCR12xdh4CA47q958ZRGnnDUGFVE1QhgRacJCOZ9bd5t9mr8KLaVBYTCJo5ERE8jymab5dPqe5qKfJsCZiqWglbjUo9twIDAQABo1AwTjAdBgNVHQ4EFgQUxpuwcs/CYQOyui+r1G+3KxBNhxkwHwYDVR0jBBgwFoAUxpuwcs/CYQOyui+r1G+3KxBNhxkwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAAiWUKs/2x/viNCKi3Y6blEuCtAGhzOOZ9EjrvJ8+COH3Rag3tVBWrcBZ3/uhhPq5gy9lqw4OkvEws99/5jFsX1FJ6MKBgqfuy7yh5s1YfM0ANHYczMmYpZeAcQf2CGAaVfwTTfSlzNLsF2lW/ly7yapFzlYSJLGoVE+OHEu8g5SlNACUEfkXw+5Eghh+KzlIN7R6Q7r2ixWNFBC/jWf7NKUfJyX8qIG5md1YUeT6GBW9Bm2/1/RiO24JTaYlfLdKK9TYb8sG5B+OLab2DImG99CJ25RkAcSobWNF5zD0O6lgOo3cEdB/ksCq3hmtlC/DlLZ/D8CJ+7VuZnS1rR2naQ==</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</md:KeyDescriptor>
<md:KeyDescriptor use="encryption">
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data>
<ds:X509Certificate>
MIIDHDCCAgSgAwIBAgIJAPEnL5jgbeVoMA0GCSqGSIb3DQEBCwUAMBoxGDAWBgNV
BAMMD2lkcC5leGFtcGxlLmVkdTAeFw0xODEwMTAyMDM1NDBaFw0yMzEwMDkyMDM1
NDBaMBoxGDAWBgNVBAMMD2lkcC5leGFtcGxlLmVkdTCCASIwDQYJKoZIhvcNAQEB
BQADggEPADCCAQoCggEBAKwTrvQhmFX3SUNgJAhQ/YV0UX56Rt53mwbiKuH+Ez83
7z6XRynBVsfzHfbWe0IpNKx5mIr84dfbGhQKQBEKzQuek7ihW3J6PIVZN1A3icZZ
B9i7gow902bT0ZfRG8QW49gl7pk3ASutPcO9Dq5Xc/AqWr3OSO/Pei0yBtTdzG3b
rm0u0gbj3P2tjt7BN77wIB+yjJsND3ITtP0MFXIJxLTlty8thwqQOAOAYcF+rhC5
znnBLsRNo0E57PtzZs8i/BpEX2uPTxpEyvlU1vtyxcKUiHtK5ZjOsDEkS2rEualr
+FILYg/Oxw1gi0+mNO1a94Ft+UoLiREztq6MQt8OK98CAwEAAaNlMGMwQgYDVR0R
BDswOYIPaWRwLmV4YW1wbGUuZWR1hiZodHRwczovL2lkcC5leGFtcGxlLmVkdS9p
ZHAvc2hpYmJvbGV0aDAdBgNVHQ4EFgQU3ZJ8oHkmlgPtZuZAxnzONccPsb8wDQYJ
KoZIhvcNAQELBQADggEBAIJ4oZKSMGpF8J3qdfjLZGkc3iVbu/eiE1MD77no0oCz
nelY0CNUBuFJk1Xv+Bv0fW0cVugtMPz4xi7zv0zkpS2IVxpPZWBosuVabUD9k+V4
iN5woJdO7e2KRGvhlWmbkmoZUvhygDe0u0vblNfLzDwFQvxHXiWG//P7SanoQrjP
dE8U21tYz+EFm6s5TvHxVhr9id8c+UacAFCpAtzUB+J8K1abx05XlKsySflkOQV9
JbM4zOy5gXSI5dY9dGUF77g0muyC+jAhIhLSt/7v3vJgvBurrxPoeBFXOU3D+siT
VZlKtYzYjJhVqXx1vKrWEE1hkpqm+iYgZe4MvgcdswY=
</ds:X509Certificate>
<ds:X509Certificate>MIIDXTCCAkWgAwIBAgIJALmVVuDWu4NYMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwHhcNMTYxMjMxMTQzNDQ3WhcNNDgwNjI1MTQzNDQ3WjBFMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzUCFozgNb1h1M0jzNRSCjhOBnR+uVbVpaWfXYIR+AhWDdEe5ryY+CgavOg8bfLybyzFdehlYdDRgkedEB/GjG8aJw06l0qF4jDOAw0kEygWCu2mcH7XOxRt+YAH3TVHa/Hu1W3WjzkobqqqLQ8gkKWWM27fOgAZ6GieaJBN6VBSMMcPey3HWLBmc+TYJmv1dbaO2jHhKh8pfKw0W12VM8P1PIO8gv4Phu/uuJYieBWKixBEyy0lHjyixYFCR12xdh4CA47q958ZRGnnDUGFVE1QhgRacJCOZ9bd5t9mr8KLaVBYTCJo5ERE8jymab5dPqe5qKfJsCZiqWglbjUo9twIDAQABo1AwTjAdBgNVHQ4EFgQUxpuwcs/CYQOyui+r1G+3KxBNhxkwHwYDVR0jBBgwFoAUxpuwcs/CYQOyui+r1G+3KxBNhxkwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAAiWUKs/2x/viNCKi3Y6blEuCtAGhzOOZ9EjrvJ8+COH3Rag3tVBWrcBZ3/uhhPq5gy9lqw4OkvEws99/5jFsX1FJ6MKBgqfuy7yh5s1YfM0ANHYczMmYpZeAcQf2CGAaVfwTTfSlzNLsF2lW/ly7yapFzlYSJLGoVE+OHEu8g5SlNACUEfkXw+5Eghh+KzlIN7R6Q7r2ixWNFBC/jWf7NKUfJyX8qIG5md1YUeT6GBW9Bm2/1/RiO24JTaYlfLdKK9TYb8sG5B+OLab2DImG99CJ25RkAcSobWNF5zD0O6lgOo3cEdB/ksCq3hmtlC/DlLZ/D8CJ+7VuZnS1rR2naQ==</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</KeyDescriptor>
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://idp.example.edu/idp/profile/SAML2/Redirect/SSO"/>
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://idp.example.edu/idp/profile/SAML2/POST/SSO"/>
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign" Location="https://idp.example.edu/idp/profile/SAML2/POST-SimpleSign/SSO"/>
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="https://idp.example.edu/idp/profile/SAML2/SOAP/ECP"/>
</IDPSSODescriptor>
</EntityDescriptor>
</md:KeyDescriptor>
<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="http://idp.example.edu:8080/simplesaml/saml2/idp/SingleLogoutService.php"/>
<md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</md:NameIDFormat>
<md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="http://idp.example.edu:8080/simplesaml/saml2/idp/SSOService.php"/>
</md:IDPSSODescriptor>
</md:EntityDescriptor>
SAML_SIGNING_CERT: |
-----BEGIN CERTIFICATE-----
MIID/TCCAmWgAwIBAgIJAJZqOL69C6nRMA0GCSqGSIb3DQEBCwUAMB0xGzAZBgNV
@@ -270,18 +259,40 @@ services:
ZMmUvRJr8jzCCPD8DrHf85GAACRPoVsBDLD3oXTLcY8Frum1npH57H6Eaa/Jmuk5
UdDJprIEgUhY47jK1O+IKtxnTQPnqotqWC5Lk4Rhnr62APxhkl9jraI=
-----END RSA PRIVATE KEY-----
networks:
app-proxy:
proxy-test:
aliases:
- sptest.example.edu
healthcheck:
test: ["CMD", "curl", "-f", "--insecure", "https://localhost:443"]

selenium-firefox:
image: selenium/standalone-firefox:120.0-20231122
depends_on:
- app
- idp
- proxy
networks:
- proxy-net
ports:
- "4444:4444"
- "7900:7900"
shm_size: "2g"
environment:
SE_OPTS: "--log-level SEVERE"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:4444/wd/hub/status"]

test:
build:
context: "./containers/test"
context: "./tests/containers/test"
networks:
- idp-test
- proxy-test
- proxy-net
command: [ "python", "/selenium/test_script.py" ]
depends_on:
selenium-firefox:
condition: service_healthy
proxy:
condition: service_healthy
app:
condition: service_healthy
idp:
condition: service_healthy
volumes:
- "./tests/containers/test:/selenium"
16 changes: 4 additions & 12 deletions tests/containers/app/Dockerfile
@@ -1,12 +1,4 @@
# Application Container
FROM centos:7

RUN yum -y update && \
yum install -y httpd php && \
yum clean all

COPY container_files/httpd.conf /etc/httpd/conf/httpd.conf
COPY container_files/app.conf /etc/httpd/conf.d/app.conf
COPY container_files/html/ /var/www/html/

CMD ["httpd", "-D", "FOREGROUND"]
FROM php:8
COPY index.php /usr/src/test-app/
WORKDIR /usr/src/test-app
CMD [ "php", "-S", "0.0.0.0:80" ]
3 changes: 0 additions & 3 deletions tests/containers/app/container_files/app.conf

This file was deleted.

1 change: 0 additions & 1 deletion tests/containers/app/container_files/html/index.php

This file was deleted.

353 changes: 0 additions & 353 deletions tests/containers/app/container_files/httpd.conf

This file was deleted.

15 changes: 15 additions & 0 deletions tests/containers/app/index.php
@@ -0,0 +1,15 @@
<?php

header('Content-type: application/json');

$headers = apache_request_headers();

$data = array(
"headers" => $headers,
);

$json = json_encode($data);

echo $json;

?>
19 changes: 0 additions & 19 deletions tests/containers/idp/Dockerfile

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

0 comments on commit c7212de

Please sign in to comment.