Skip to content

[7.17] Build shibboleth-idp for testing purposes (#91216) #91293

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions x-pack/qa/saml-idp-tests/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import org.elasticsearch.gradle.Architecture

Project idpFixtureProject = xpackProject("test:idp-fixture")

apply plugin: 'elasticsearch.internal-java-rest-test'
Expand All @@ -13,17 +11,17 @@ dependencies {
testFixtures.useFixture ":x-pack:test:idp-fixture"

String outputDir = "${project.buildDir}/generated-resources/${project.name}"
def copyIdpFiles = tasks.register("copyIdpFiles", Copy) {
def copyIdpFiles = tasks.register("copyIdpFiles", Sync) {
from idpFixtureProject.files('idp/shibboleth-idp/credentials/idp-browser.pem', 'idp/shibboleth-idp/metadata/idp-metadata.xml',
'idp/shibboleth-idp/credentials/sp-signing.key', 'idp/shibboleth-idp/credentials/sp-signing.crt');
into outputDir
outputs.upToDateWhen { false } //ensure this copy is always done to prevent stale configuration
}

def setupPorts = tasks.register("setupPorts") {
dependsOn copyIdpFiles, idpFixtureProject.postProcessFixture
// Don't attempt to get ephemeral ports when Docker is not available
// Also, shibboleth fixture is not available on aarch64
onlyIf { idpFixtureProject.postProcessFixture.state.skipped == false && Architecture.current() == Architecture.X64 }
onlyIf { idpFixtureProject.postProcessFixture.state.skipped == false }
doLast {
String portString = idpFixtureProject.postProcessFixture.ext."test.fixtures.shibboleth-idp.tcp.4443"
int ephemeralPort = Integer.valueOf(portString)
Expand All @@ -43,7 +41,7 @@ project.sourceSets.javaRestTest.output.dir(outputDir, builtBy: [copyIdpFiles])

tasks.named("javaRestTest").configure {
dependsOn setupPorts
onlyIf { idpFixtureProject.postProcessFixture.state.skipped == false && Architecture.current() == Architecture.X64 }
onlyIf { idpFixtureProject.postProcessFixture.state.skipped == false }
}

testClusters.matching { it.name == "javaRestTest" }.configureEach {
Expand Down
16 changes: 7 additions & 9 deletions x-pack/test/idp-fixture/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -137,22 +137,20 @@ services:
- ./openldap/certs:/container/service/slapd/assets/certs

shibboleth-idp:
image: "unicon/shibboleth-idp:3.4.2"
build:
context: .
dockerfile: ./idp/Dockerfile
depends_on:
- openldap
environment:
- JETTY_MAX_HEAP=64m
- JETTY_BROWSER_SSL_KEYSTORE_PASSWORD=secret
- JETTY_BACKCHANNEL_SSL_KEYSTORE_PASSWORD=secret
ports:
- "4443"
- 4443
expose:
- 4443
links:
- openldap:openldap
volumes:
- ./idp/shibboleth-idp/conf:/opt/shibboleth-idp/conf
- ./idp/shibboleth-idp/credentials:/opt/shibboleth-idp/credentials
- ./idp/shibboleth-idp/metadata:/opt/shibboleth-idp/metadata
- ./idp/shib-jetty-base/start.d/ssl.ini:/opt/shib-jetty-base/start.d/ssl.ini
restart: always #ensure ephemeral port mappings are properly updated

oidc-provider:
image: "c2id/c2id-server-demo:12.16.1"
Expand Down
92 changes: 92 additions & 0 deletions x-pack/test/idp-fixture/idp/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
FROM openjdk:11.0.16-jre AS javabase

ENV JAVA_HOME=/usr/local/openjdk-11

# below is mostly a fork from https://github.com/Unicon/shibboleth-idp-dockerized/blob/master/Dockerfile
# building entire image to allow for easier upgrades since published image has not been updated for years
ENV jetty_version=9.3.27.v20190418 \
jetty_hash=7c7c80dd1c9f921771e2b1a05deeeec652d5fcaa \
idp_version=3.4.3 \
idp_hash=eb86bc7b6366ce2a44f97cae1b014d307b84257e3149469b22b2d091007309db \
dta_hash=2f547074b06952b94c35631398f36746820a7697 \
slf4j_version=1.7.25 \
slf4j_hash=da76ca59f6a57ee3102f8f9bd9cee742973efa8a \
logback_version=1.2.3 \
logback_classic_hash=7c4f3c474fb2c041d8028740440937705ebb473a \
logback_core_hash=864344400c3d4d92dfeb0a305dc87d953677c03c \
logback_access_hash=e8a841cb796f6423c7afd8738df6e0e4052bf24a

ENV JETTY_HOME=/opt/jetty-home \
JETTY_BASE=/opt/shib-jetty-base \
PATH=$PATH:$JAVA_HOME/bin \
JETTY_BROWSER_SSL_KEYSTORE_PASSWORD=secret \
JETTY_BACKCHANNEL_SSL_KEYSTORE_PASSWORD=secret

# Manually override the jetty keystore otherwise it will attempt to download and fail
RUN mkdir -p /opt/shib-jetty-base/modules
COPY ./idp/jetty-custom/ssl.mod /opt/shib-jetty-base/modules/ssl.mod
COPY ./idp/jetty-custom/keystore /opt/shib-jetty-base/etc/keystore

# Download Jetty, verify the hash, and install, initialize a new base
RUN wget -q https://repo.maven.apache.org/maven2/org/eclipse/jetty/jetty-distribution/$jetty_version/jetty-distribution-$jetty_version.tar.gz \
&& echo "$jetty_hash jetty-distribution-$jetty_version.tar.gz" | sha1sum -c - \
&& tar -zxvf jetty-distribution-$jetty_version.tar.gz -C /opt \
&& ln -s /opt/jetty-distribution-$jetty_version/ /opt/jetty-home

# Config Jetty
RUN mkdir -p /opt/shib-jetty-base/modules /opt/shib-jetty-base/lib/ext /opt/shib-jetty-base/lib/logging /opt/shib-jetty-base/resources \
&& cd /opt/shib-jetty-base \
&& touch start.ini \
&& java -jar ../jetty-home/start.jar --add-to-startd=http,https,deploy,ext,annotations,jstl,rewrite

# Download Shibboleth IdP, verify the hash, and install
RUN wget -q https://shibboleth.net/downloads/identity-provider/archive/$idp_version/shibboleth-identity-provider-$idp_version.tar.gz \
&& echo "$idp_hash shibboleth-identity-provider-$idp_version.tar.gz" | sha256sum -c - \
&& tar -zxvf shibboleth-identity-provider-$idp_version.tar.gz -C /opt \
&& ln -s /opt/shibboleth-identity-provider-$idp_version/ /opt/shibboleth-idp

# Download the library to allow SOAP Endpoints, verify the hash, and place
RUN wget -q https://build.shibboleth.net/nexus/content/repositories/releases/net/shibboleth/utilities/jetty9/jetty9-dta-ssl/1.0.0/jetty9-dta-ssl-1.0.0.jar \
&& echo "$dta_hash jetty9-dta-ssl-1.0.0.jar" | sha1sum -c - \
&& mv jetty9-dta-ssl-1.0.0.jar /opt/shib-jetty-base/lib/ext/

# Download the slf4j library for Jetty logging, verify the hash, and place
RUN wget -q https://repo.maven.apache.org/maven2/org/slf4j/slf4j-api/$slf4j_version/slf4j-api-$slf4j_version.jar \
&& echo "$slf4j_hash slf4j-api-$slf4j_version.jar" | sha1sum -c - \
&& mv slf4j-api-$slf4j_version.jar /opt/shib-jetty-base/lib/logging/

# Download the logback_classic library for Jetty logging, verify the hash, and place
RUN wget -q https://repo.maven.apache.org/maven2/ch/qos/logback/logback-classic/$logback_version/logback-classic-$logback_version.jar \
&& echo "$logback_classic_hash logback-classic-$logback_version.jar" | sha1sum -c - \
&& mv logback-classic-$logback_version.jar /opt/shib-jetty-base/lib/logging/

# Download the logback-core library for Jetty logging, verify the hash, and place
RUN wget -q https://repo.maven.apache.org/maven2/ch/qos/logback/logback-core/$logback_version/logback-core-$logback_version.jar \
&& echo "$logback_core_hash logback-core-$logback_version.jar" | sha1sum -c - \
&& mv logback-core-$logback_version.jar /opt/shib-jetty-base/lib/logging/

# Download the logback-access library for Jetty logging, verify the hash, and place
RUN wget -q https://repo.maven.apache.org/maven2/ch/qos/logback/logback-access/$logback_version/logback-access-$logback_version.jar \
&& echo "$logback_access_hash logback-access-$logback_version.jar" | sha1sum -c - \
&& mv logback-access-$logback_version.jar /opt/shib-jetty-base/lib/logging/

## Copy local files
COPY idp/shib-jetty-base/ /opt/shib-jetty-base/
COPY idp/shibboleth-idp/ /opt/shibboleth-idp/
COPY idp/bin/ /usr/local/bin/

# Setting owner ownership and permissions
RUN useradd jetty -U -s /bin/false \
&& chown -R root:jetty /opt \
&& chmod -R 640 /opt \
&& chown -R root:jetty /opt/shib-jetty-base \
&& chmod -R 640 /opt/shib-jetty-base \
&& chmod -R 750 /opt/shibboleth-idp/bin

RUN chmod 750 /usr/local/bin/run-jetty.sh /usr/local/bin/init-idp.sh
RUN chmod +x /opt/jetty-home/bin/jetty.sh

# Opening 4443 (browser TLS), 8443 (mutual auth TLS)
EXPOSE 4443 8443

CMD ["run-jetty.sh"]
27 changes: 27 additions & 0 deletions x-pack/test/idp-fixture/idp/bin/init-idp.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/bin/bash

cd /opt/shibboleth-idp/bin

echo "Please complete the following for your IdP environment:"
./ant.sh -Didp.target.dir=/opt/shibboleth-idp-tmp -Didp.src.dir=/opt/shibboleth-idp/ install

find /opt/shibboleth-idp-tmp/ -type d -exec chmod 750 {} \;

mkdir -p /ext-mount/customized-shibboleth-idp/conf/
chmod -R 750 /ext-mount/customized-shibboleth-idp/

# Copy the essential and routinely customized config to out Docker mount.
cd /opt/shibboleth-idp-tmp
cp -r credentials/ /ext-mount/customized-shibboleth-idp/
cp -r metadata/ /ext-mount/customized-shibboleth-idp/
cp conf/{attribute-resolver*.xml,attribute-filter.xml,cas-protocol.xml,idp.properties,ldap.properties,metadata-providers.xml,relying-party.xml,saml-nameid.*} /ext-mount/customized-shibboleth-idp/conf/

# Copy the basic UI components, which are routinely customized
cp -r views/ /ext-mount/customized-shibboleth-idp/
mkdir /ext-mount/customized-shibboleth-idp/webapp/
cp -r edit-webapp/css/ /ext-mount/customized-shibboleth-idp/webapp/
cp -r edit-webapp/images/ /ext-mount/customized-shibboleth-idp/webapp/
rm -r /ext-mount/customized-shibboleth-idp/views/user-prefs.js

echo "A basic Shibboleth IdP config and UI has been copied to ./customized-shibboleth-idp/ (assuming the default volume mapping was used)."
echo "Most files, if not being customized can be removed from what was exported/the local Docker image and baseline files will be used."
13 changes: 13 additions & 0 deletions x-pack/test/idp-fixture/idp/bin/run-jetty.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/sh

#set -x

if [ -e "/opt/shibboleth-idp/ext-conf/idp-secrets.properties" ]; then
export JETTY_BACKCHANNEL_SSL_KEYSTORE_PASSWORD=`gawk 'match($0,/^jetty.backchannel.sslContext.keyStorePassword=\s?(.*)\s?$/, a) {print a[1]}' /opt/shibboleth-idp/ext-conf/idp-secrets.properties`
export JETTY_BROWSER_SSL_KEYSTORE_PASSWORD=`gawk 'match($0,/^jetty\.sslContext\.keyStorePassword=\s?(.*)\s?$/, a) {print a[1]}' /opt/shibboleth-idp/ext-conf/idp-secrets.properties`
fi

export JETTY_ARGS="jetty.sslContext.keyStorePassword=$JETTY_BROWSER_SSL_KEYSTORE_PASSWORD jetty.backchannel.sslContext.keyStorePassword=$JETTY_BACKCHANNEL_SSL_KEYSTORE_PASSWORD"
sed -i "s/^-Xmx.*$/-Xmx$JETTY_MAX_HEAP/g" /opt/shib-jetty-base/start.ini

exec /opt/jetty-home/bin/jetty.sh run
Binary file added x-pack/test/idp-fixture/idp/jetty-custom/keystore
Binary file not shown.
102 changes: 102 additions & 0 deletions x-pack/test/idp-fixture/idp/jetty-custom/ssl.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#
# SSL Keystore module
#

[name]
ssl

[depend]
server

[xml]
etc/jetty-ssl.xml
etc/jetty-ssl-context.xml

[files]
# keystore originally sourced from https://github.com/eclipse/jetty.project/raw/jetty-9.3.x/jetty-server/src/main/config/etc/keystore
/opt/shib-jetty-base/etc/keystore

[ini-template]
### TLS(SSL) Connector Configuration

## Connector host/address to bind to
# jetty.ssl.host=0.0.0.0

## Connector port to listen on
# jetty.ssl.port=8443

## Connector idle timeout in milliseconds
# jetty.ssl.idleTimeout=30000

## Connector socket linger time in seconds (-1 to disable)
# jetty.ssl.soLingerTime=-1

## Number of acceptors (-1 picks default based on number of cores)
# jetty.ssl.acceptors=-1

## Number of selectors (-1 picks default based on number of cores)
# jetty.ssl.selectors=-1

## ServerSocketChannel backlog (0 picks platform default)
# jetty.ssl.acceptorQueueSize=0

## Thread priority delta to give to acceptor threads
# jetty.ssl.acceptorPriorityDelta=0

## Whether request host names are checked to match any SNI names
# jetty.ssl.sniHostCheck=true

## max age in seconds for a Strict-Transport-Security response header (default -1)
# jetty.ssl.stsMaxAgeSeconds=31536000

## include subdomain property in any Strict-Transport-Security header (default false)
# jetty.ssl.stsIncludeSubdomains=true

### SslContextFactory Configuration
## Note that OBF passwords are not secure, just protected from casual observation
## See http://www.eclipse.org/jetty/documentation/current/configuring-security-secure-passwords.html

## Keystore file path (relative to $jetty.base)
# jetty.sslContext.keyStorePath=etc/keystore

## Truststore file path (relative to $jetty.base)
# jetty.sslContext.trustStorePath=etc/keystore

## Keystore password
# jetty.sslContext.keyStorePassword=OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4

## Keystore type and provider
# jetty.sslContext.keyStoreType=JKS
# jetty.sslContext.keyStoreProvider=

## KeyManager password
# jetty.sslContext.keyManagerPassword=OBF:1u2u1wml1z7s1z7a1wnl1u2g

## Truststore password
# jetty.sslContext.trustStorePassword=OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4

## Truststore type and provider
# jetty.sslContext.trustStoreType=JKS
# jetty.sslContext.trustStoreProvider=

## whether client certificate authentication is required
# jetty.sslContext.needClientAuth=false

## Whether client certificate authentication is desired
# jetty.sslContext.wantClientAuth=false

## Whether cipher order is significant (since java 8 only)
# jetty.sslContext.useCipherSuitesOrder=true

## To configure Includes / Excludes for Cipher Suites or Protocols see tweak-ssl.xml example at
## https://www.eclipse.org/jetty/documentation/current/configuring-ssl.html#configuring-sslcontextfactory-cipherSuites

## Set the size of the SslSession cache
# jetty.sslContext.sslSessionCacheSize=-1

## Set the timeout (in seconds) of the SslSession cache timeout
# jetty.sslContext.sslSessionTimeout=-1

## Allow SSL renegotiation
# jetty.sslContext.renegotiationAllowed=true
# jetty.sslContext.renegotiationLimit=5
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">

<Configure id="Server" class="org.eclipse.jetty.server.Server">

<!-- ============================================================= -->
<!-- TLS context factory with optional client auth -->
<!-- and no container trust (delegate to application) -->
<!-- for backchannel (SOAP) communication to IdP -->
<!-- ============================================================= -->
<New id="shibContextFactory" class="net.shibboleth.utilities.jetty9.DelegateToApplicationSslContextFactory">
<Set name="KeyStorePath"><Property name="jetty.backchannel.sslContext.keyStorePath" /></Set>
<Set name="KeyStoreType"><Property name="jetty.backchannel.sslContext.keyStoreType" /></Set>
<Set name="KeyStorePassword"><Property name="jetty.backchannel.sslContext.keyStorePassword" /></Set>
<!-- This is a tweak to work around a bug in Jetty when using the PKCS12 keystore type. -->
<Set name="TrustStoreType"><Property name="jetty.backchannel.sslContext.keyStoreType" /></Set>
<Set name="EndpointIdentificationAlgorithm"></Set>
<Set name="renegotiationAllowed">false</Set>
<Set name="useCipherSuitesOrder">true</Set>
<Set name="excludeProtocols">
<Array type="String">
<Item>SSL</Item>
<Item>SSLv2</Item>
<Item>SSLv3</Item>
</Array>
</Set>
<Set name="IncludeCipherSuites">
<Array type="String">
<Item>TLS_ECDHE.*</Item>
<Item>TLS_RSA.*</Item>
</Array>
</Set>
<Set name="ExcludeCipherSuites">
<Array type="String">
<Item>.*NULL.*</Item>
<Item>.*RC4.*</Item>
<Item>.*MD5.*</Item>
<Item>.*DES.*</Item>
<Item>.*DSS.*</Item>
</Array>
</Set>
</New>

<New id="shibHttpConfig" class="org.eclipse.jetty.server.HttpConfiguration">
<Arg><Ref refid="httpConfig"/></Arg>
<Call name="addCustomizer">
<Arg>
<New class="org.eclipse.jetty.server.SecureRequestCustomizer">
<Arg type="boolean"><Property name="jetty.ssl.sniHostCheck" default="true"/></Arg>
</New>
</Arg>
</Call>
</New>

<!-- ============================================================= -->
<!-- IdP SOAP protocol connector -->
<!-- ============================================================= -->
<Call id="shibConnector" name="addConnector">
<Arg>
<New class="org.eclipse.jetty.server.ServerConnector">
<Arg name="server"><Ref refid="Server" /></Arg>
<Arg name="acceptors" type="int"><Property name="jetty.ssl.acceptors" default="-1"/></Arg>
<Arg name="selectors" type="int"><Property name="jetty.ssl.selectors" default="-1"/></Arg>
<Arg name="factories">
<Array type="org.eclipse.jetty.server.ConnectionFactory">
<Item>
<New class="org.eclipse.jetty.server.SslConnectionFactory">
<Arg name="next">http/1.1</Arg>
<Arg name="sslContextFactory"><Ref refid="shibContextFactory"/></Arg>
</New>
</Item>
<Item>
<New class="org.eclipse.jetty.server.HttpConnectionFactory">
<Arg name="config"><Ref refid="shibHttpConfig"/></Arg>
</New>
</Item>
</Array>
</Arg>
<Set name="host"><Property name="jetty.backchannel.host" default="0.0.0.0" /></Set>
<Set name="port"><Property name="jetty.backchannel.port" default="8443"/></Set>
<Set name="idleTimeout"><Property name="jetty.ssl.timeout" default="30000"/></Set>
<Set name="soLingerTime"><Property name="jetty.ssl.soLingerTime" default="-1"/></Set>
<Set name="acceptorPriorityDelta"><Property name="jetty.ssl.acceptorPriorityDelta" default="0"/></Set>
<Set name="selectorPriorityDelta"><Property name="jetty.ssl.selectorPriorityDelta" default="0"/></Set>
<Set name="acceptQueueSize"><Property name="jetty.ssl.acceptQueueSize" default="0"/></Set>
</New>
</Arg>
</Call>

</Configure>
Loading