forked from SUNET/soc-ops
First sekelton for shib-proxy.
This commit is contained in:
parent
f4d620ba4d
commit
f24f201d46
13 changed files with 787 additions and 0 deletions
0
global/overlay/etc/puppet/soc/facts.d/.empty
Normal file
0
global/overlay/etc/puppet/soc/facts.d/.empty
Normal file
154
global/overlay/etc/puppet/soc/files/sso/acme-dns-auth.py
Executable file
154
global/overlay/etc/puppet/soc/files/sso/acme-dns-auth.py
Executable file
|
@ -0,0 +1,154 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import requests
|
||||||
|
import sys
|
||||||
|
|
||||||
|
### EDIT THESE: Configuration values ###
|
||||||
|
|
||||||
|
# URL to acme-dns instance
|
||||||
|
ACMEDNS_URL = "https://acme-d.sunet.se"
|
||||||
|
# Path for acme-dns credential storage
|
||||||
|
STORAGE_PATH = "/etc/letsencrypt/acmedns.json"
|
||||||
|
# Whitelist for address ranges to allow the updates from
|
||||||
|
# Example: ALLOW_FROM = ["192.168.10.0/24", "::1/128"]
|
||||||
|
ALLOW_FROM = []
|
||||||
|
# Force re-registration. Overwrites the already existing acme-dns accounts.
|
||||||
|
FORCE_REGISTER = False
|
||||||
|
|
||||||
|
### DO NOT EDIT BELOW THIS POINT ###
|
||||||
|
### HERE BE DRAGONS ###
|
||||||
|
|
||||||
|
DOMAIN = os.environ["CERTBOT_DOMAIN"]
|
||||||
|
if DOMAIN.startswith("*."):
|
||||||
|
DOMAIN = DOMAIN[2:]
|
||||||
|
VALIDATION_DOMAIN = "_acme-challenge."+DOMAIN
|
||||||
|
VALIDATION_TOKEN = os.environ["CERTBOT_VALIDATION"]
|
||||||
|
|
||||||
|
|
||||||
|
class AcmeDnsClient(object):
|
||||||
|
"""
|
||||||
|
Handles the communication with ACME-DNS API
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, acmedns_url):
|
||||||
|
self.acmedns_url = acmedns_url
|
||||||
|
|
||||||
|
def register_account(self, allowfrom):
|
||||||
|
"""Registers a new ACME-DNS account"""
|
||||||
|
|
||||||
|
if allowfrom:
|
||||||
|
# Include whitelisted networks to the registration call
|
||||||
|
reg_data = {"allowfrom": allowfrom}
|
||||||
|
res = requests.post(self.acmedns_url+"/register",
|
||||||
|
data=json.dumps(reg_data))
|
||||||
|
else:
|
||||||
|
res = requests.post(self.acmedns_url+"/register")
|
||||||
|
if res.status_code == 201:
|
||||||
|
# The request was successful
|
||||||
|
return res.json()
|
||||||
|
else:
|
||||||
|
# Encountered an error
|
||||||
|
msg = ("Encountered an error while trying to register a new acme-dns "
|
||||||
|
"account. HTTP status {}, Response body: {}")
|
||||||
|
print(msg.format(res.status_code, res.text))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
def update_txt_record(self, account, txt):
|
||||||
|
"""Updates the TXT challenge record to ACME-DNS subdomain."""
|
||||||
|
update = {"subdomain": account['subdomain'], "txt": txt}
|
||||||
|
headers = {"X-Api-User": account['username'],
|
||||||
|
"X-Api-Key": account['password'],
|
||||||
|
"Content-Type": "application/json"}
|
||||||
|
res = requests.post(self.acmedns_url+"/update",
|
||||||
|
headers=headers,
|
||||||
|
data=json.dumps(update))
|
||||||
|
if res.status_code == 200:
|
||||||
|
# Successful update
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
msg = ("Encountered an error while trying to update TXT record in "
|
||||||
|
"acme-dns. \n"
|
||||||
|
"------- Request headers:\n{}\n"
|
||||||
|
"------- Request body:\n{}\n"
|
||||||
|
"------- Response HTTP status: {}\n"
|
||||||
|
"------- Response body: {}")
|
||||||
|
s_headers = json.dumps(headers, indent=2, sort_keys=True)
|
||||||
|
s_update = json.dumps(update, indent=2, sort_keys=True)
|
||||||
|
s_body = json.dumps(res.json(), indent=2, sort_keys=True)
|
||||||
|
print(msg.format(s_headers, s_update, res.status_code, s_body))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
class Storage(object):
|
||||||
|
def __init__(self, storagepath):
|
||||||
|
self.storagepath = storagepath
|
||||||
|
self._data = self.load()
|
||||||
|
|
||||||
|
def load(self):
|
||||||
|
"""Reads the storage content from the disk to a dict structure"""
|
||||||
|
data = dict()
|
||||||
|
filedata = ""
|
||||||
|
try:
|
||||||
|
with open(self.storagepath, 'r') as fh:
|
||||||
|
filedata = fh.read()
|
||||||
|
except IOError as e:
|
||||||
|
if os.path.isfile(self.storagepath):
|
||||||
|
# Only error out if file exists, but cannot be read
|
||||||
|
print("ERROR: Storage file exists but cannot be read")
|
||||||
|
sys.exit(1)
|
||||||
|
try:
|
||||||
|
data = json.loads(filedata)
|
||||||
|
except ValueError:
|
||||||
|
if len(filedata) > 0:
|
||||||
|
# Storage file is corrupted
|
||||||
|
print("ERROR: Storage JSON is corrupted")
|
||||||
|
sys.exit(1)
|
||||||
|
return data
|
||||||
|
|
||||||
|
def save(self):
|
||||||
|
"""Saves the storage content to disk"""
|
||||||
|
serialized = json.dumps(self._data)
|
||||||
|
try:
|
||||||
|
with os.fdopen(os.open(self.storagepath,
|
||||||
|
os.O_WRONLY | os.O_CREAT, 0o600), 'w') as fh:
|
||||||
|
fh.truncate()
|
||||||
|
fh.write(serialized)
|
||||||
|
except IOError as e:
|
||||||
|
print("ERROR: Could not write storage file.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
def put(self, key, value):
|
||||||
|
"""Puts the configuration value to storage and sanitize it"""
|
||||||
|
# If wildcard domain, remove the wildcard part as this will use the
|
||||||
|
# same validation record name as the base domain
|
||||||
|
if key.startswith("*."):
|
||||||
|
key = key[2:]
|
||||||
|
self._data[key] = value
|
||||||
|
|
||||||
|
def fetch(self, key):
|
||||||
|
"""Gets configuration value from storage"""
|
||||||
|
try:
|
||||||
|
return self._data[key]
|
||||||
|
except KeyError:
|
||||||
|
return None
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# Init
|
||||||
|
client = AcmeDnsClient(ACMEDNS_URL)
|
||||||
|
storage = Storage(STORAGE_PATH)
|
||||||
|
|
||||||
|
# Check if an account already exists in storage
|
||||||
|
account = storage.fetch(DOMAIN)
|
||||||
|
if FORCE_REGISTER or not account:
|
||||||
|
# Create and save the new account
|
||||||
|
account = client.register_account(ALLOW_FROM)
|
||||||
|
storage.put(DOMAIN, account)
|
||||||
|
storage.save()
|
||||||
|
|
||||||
|
# Display the notification for the user to update the main zone
|
||||||
|
msg = "Please add the following CNAME record to your main DNS zone:\n{}"
|
||||||
|
cname = "{} CNAME {}.".format(VALIDATION_DOMAIN, account["fulldomain"])
|
||||||
|
print(msg.format(cname))
|
||||||
|
|
||||||
|
# Update the TXT record in acme-dns instance
|
||||||
|
client.update_txt_record(account, VALIDATION_TOKEN)
|
19
global/overlay/etc/puppet/soc/files/sso/apache-ssl.conf
Normal file
19
global/overlay/etc/puppet/soc/files/sso/apache-ssl.conf
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
# This file contains important security parameters. If you modify this file
|
||||||
|
# manually, Certbot will be unable to automatically provide future security
|
||||||
|
# updates. Instead, Certbot will print and log an error message with a path to
|
||||||
|
# the up-to-date file that you will need to refer to when manually updating
|
||||||
|
# this file. Contents are based on https://ssl-config.mozilla.org
|
||||||
|
|
||||||
|
SSLEngine on
|
||||||
|
|
||||||
|
# Intermediate configuration, tweak to your needs
|
||||||
|
SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
|
||||||
|
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
|
||||||
|
SSLHonorCipherOrder off
|
||||||
|
SSLSessionTickets off
|
||||||
|
|
||||||
|
SSLOptions +StrictRequire
|
||||||
|
|
||||||
|
# Add vhost name to log entries:
|
||||||
|
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" vhost_combined
|
||||||
|
LogFormat "%v %h %l %u %t \"%r\" %>s %b" vhost_common
|
22
global/overlay/etc/puppet/soc/files/sso/attribute-map.xml
Normal file
22
global/overlay/etc/puppet/soc/files/sso/attribute-map.xml
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
<Attributes xmlns="urn:mace:shibboleth:2.0:attribute-map" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
|
||||||
|
<!--
|
||||||
|
SWAMID standard attribute-map.xml for SAML 2.0
|
||||||
|
==============================================
|
||||||
|
The mappings are agreed to within the Shibboleth community or directly LDAP attribute names.
|
||||||
|
|
||||||
|
Version: 2017-01-04
|
||||||
|
|
||||||
|
REMEMBER to notify SWAMID saml-admins list when updating this file!
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!-- eduPerson attributes until version 201310 -->
|
||||||
|
<Attribute name="urn:oid:1.3.6.1.4.1.5923.1.1.1.6" id="eppn">
|
||||||
|
<AttributeDecoder xsi:type="ScopedAttributeDecoder"/>
|
||||||
|
</Attribute>
|
||||||
|
<Attribute name="urn:oid:1.3.6.1.4.1.5923.1.1.1.11" id="assurance"/>
|
||||||
|
|
||||||
|
<!-- Attribute to extract SWAMID Assurance Profiles -->
|
||||||
|
<Attribute name="urn:oasis:names:tc:SAML:attribute:assurance-certification" id="Assurance-Certification"/>
|
||||||
|
|
||||||
|
</Attributes>
|
82
global/overlay/etc/puppet/soc/files/sso/attribute-policy.xml
Normal file
82
global/overlay/etc/puppet/soc/files/sso/attribute-policy.xml
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
<afp:AttributeFilterPolicyGroup
|
||||||
|
xmlns="urn:mace:shibboleth:2.0:afp:mf:basic"
|
||||||
|
xmlns:saml="urn:mace:shibboleth:2.0:afp:mf:saml"
|
||||||
|
xmlns:basic="urn:mace:shibboleth:2.0:afp:mf:basic"
|
||||||
|
xmlns:afp="urn:mace:shibboleth:2.0:afp"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
|
||||||
|
<!-- Shared rule for affiliation values. -->
|
||||||
|
<afp:PermitValueRule id="eduPersonAffiliationValues" xsi:type="OR">
|
||||||
|
<Rule xsi:type="AttributeValueString" value="faculty"/>
|
||||||
|
<Rule xsi:type="AttributeValueString" value="student"/>
|
||||||
|
<Rule xsi:type="AttributeValueString" value="staff"/>
|
||||||
|
<Rule xsi:type="AttributeValueString" value="alum"/>
|
||||||
|
<Rule xsi:type="AttributeValueString" value="member"/>
|
||||||
|
<Rule xsi:type="AttributeValueString" value="affiliate"/>
|
||||||
|
<Rule xsi:type="AttributeValueString" value="employee"/>
|
||||||
|
<Rule xsi:type="AttributeValueString" value="library-walk-in"/>
|
||||||
|
</afp:PermitValueRule>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Shared rule for all "scoped" attributes, but you'll have to manually apply it inside
|
||||||
|
an AttributeRule for each attribute you want to check.
|
||||||
|
-->
|
||||||
|
<afp:PermitValueRule id="ScopingRules" xsi:type="AND">
|
||||||
|
<Rule xsi:type="NOT">
|
||||||
|
<Rule xsi:type="AttributeValueRegex" regex="@"/>
|
||||||
|
</Rule>
|
||||||
|
<Rule xsi:type="saml:AttributeScopeMatchesShibMDScope"/>
|
||||||
|
</afp:PermitValueRule>
|
||||||
|
|
||||||
|
<afp:AttributeFilterPolicy>
|
||||||
|
<!-- This policy is in effect in all cases. -->
|
||||||
|
<afp:PolicyRequirementRule xsi:type="ANY"/>
|
||||||
|
|
||||||
|
<!-- Filter out undefined affiliations and ensure only one primary. -->
|
||||||
|
<afp:AttributeRule attributeID="affiliation">
|
||||||
|
<afp:PermitValueRule xsi:type="AND">
|
||||||
|
<RuleReference ref="eduPersonAffiliationValues"/>
|
||||||
|
<RuleReference ref="ScopingRules"/>
|
||||||
|
</afp:PermitValueRule>
|
||||||
|
</afp:AttributeRule>
|
||||||
|
<afp:AttributeRule attributeID="unscoped-affiliation">
|
||||||
|
<afp:PermitValueRuleReference ref="eduPersonAffiliationValues"/>
|
||||||
|
</afp:AttributeRule>
|
||||||
|
<afp:AttributeRule attributeID="primary-affiliation">
|
||||||
|
<afp:PermitValueRuleReference ref="eduPersonAffiliationValues"/>
|
||||||
|
</afp:AttributeRule>
|
||||||
|
|
||||||
|
<afp:AttributeRule attributeID="subject-id">
|
||||||
|
<afp:PermitValueRuleReference ref="ScopingRules"/>
|
||||||
|
</afp:AttributeRule>
|
||||||
|
|
||||||
|
<afp:AttributeRule attributeID="pairwise-id">
|
||||||
|
<afp:PermitValueRuleReference ref="ScopingRules"/>
|
||||||
|
</afp:AttributeRule>
|
||||||
|
|
||||||
|
<afp:AttributeRule attributeID="eppn">
|
||||||
|
<!-- Disabled scope check since the proxy does it for us and the proxies metadata doesn't include scopes from our customers.
|
||||||
|
<afp:PermitValueRuleReference ref="ScopingRules"/>
|
||||||
|
-->
|
||||||
|
</afp:AttributeRule>
|
||||||
|
|
||||||
|
<afp:AttributeRule attributeID="targeted-id">
|
||||||
|
<afp:PermitValueRuleReference ref="ScopingRules"/>
|
||||||
|
</afp:AttributeRule>
|
||||||
|
|
||||||
|
<!-- Require NameQualifier/SPNameQualifier match IdP and SP entityID respectively. -->
|
||||||
|
<afp:AttributeRule attributeID="persistent-id">
|
||||||
|
<afp:PermitValueRule xsi:type="saml:NameIDQualifierString"/>
|
||||||
|
</afp:AttributeRule>
|
||||||
|
|
||||||
|
<!-- Enforce that the values of schacHomeOrganization are a valid Scope. -->
|
||||||
|
<afp:AttributeRule attributeID="schacHomeOrganization">
|
||||||
|
<afp:PermitValueRule xsi:type="saml:AttributeValueMatchesShibMDScope" />
|
||||||
|
</afp:AttributeRule>
|
||||||
|
|
||||||
|
<!-- Catch-all that passes everything else through unmolested. -->
|
||||||
|
<afp:AttributeRule attributeID="*" permitAny="true"/>
|
||||||
|
|
||||||
|
</afp:AttributeFilterPolicy>
|
||||||
|
|
||||||
|
</afp:AttributeFilterPolicyGroup>
|
33
global/overlay/etc/puppet/soc/files/sso/md-signer2.crt
Normal file
33
global/overlay/etc/puppet/soc/files/sso/md-signer2.crt
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
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
|
||||||
|
-----END CERTIFICATE-----
|
0
global/overlay/etc/puppet/soc/manifests/.empty
Normal file
0
global/overlay/etc/puppet/soc/manifests/.empty
Normal file
176
global/overlay/etc/puppet/soc/manifests/sso.pp
Normal file
176
global/overlay/etc/puppet/soc/manifests/sso.pp
Normal file
|
@ -0,0 +1,176 @@
|
||||||
|
## Copy from CNAAS, modifications for Sunet CERT
|
||||||
|
#
|
||||||
|
# General SSO documentation: https://wiki.sunet.se/x/sZGLBg
|
||||||
|
#
|
||||||
|
# @param hostname FQDN of the host this is running on.
|
||||||
|
#
|
||||||
|
# @param email Support email used in error messages etc.
|
||||||
|
#
|
||||||
|
# @param service_endpoint Location of service to reverse proxy for.
|
||||||
|
#
|
||||||
|
# @param groups
|
||||||
|
# List of user groups from sso_groups in global/overlay/etc/hiera/data/common.yaml. The
|
||||||
|
# default is a non-existing placeholder group, added to make the Apache config valid.
|
||||||
|
#
|
||||||
|
# @param passthrough List of paths to disable SAML protection for, e.g. API paths.
|
||||||
|
#
|
||||||
|
# @param x_remote_user
|
||||||
|
# If true, EPPN is put in the HTTP header X-Remote-User instead of REMOTE_USER.
|
||||||
|
#
|
||||||
|
# @param single_user
|
||||||
|
# If true, EPPN is discarded and X-Remote-User is set to "cnaas-user". This is useful in
|
||||||
|
# cases where the service we reverse proxy for can't create new accounts automatically.
|
||||||
|
# We use this only for Graylog at the time of writing.
|
||||||
|
#
|
||||||
|
# @param swamid_testing Set this to true if your SP is registered in swamid-testing.
|
||||||
|
#
|
||||||
|
# @param front_clients
|
||||||
|
# Hiera field, defined at common.yaml, with the the frontend IP prefixes that require access
|
||||||
|
# to port 443. Defaults to empty string.
|
||||||
|
#
|
||||||
|
class cnaas::sso(
|
||||||
|
$hostname,
|
||||||
|
$email,
|
||||||
|
$service_endpoint,
|
||||||
|
$groups = ['PLACEHOLDER'],
|
||||||
|
$passthrough = [],
|
||||||
|
$x_remote_user = false,
|
||||||
|
$swamid_testing = false,
|
||||||
|
$single_user = false,
|
||||||
|
$front_clients = '',
|
||||||
|
$translog = 'INFO',
|
||||||
|
$certbot = true,
|
||||||
|
) {
|
||||||
|
|
||||||
|
file { '/opt/sso':
|
||||||
|
ensure => directory,
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Apache files
|
||||||
|
#
|
||||||
|
|
||||||
|
file { '/opt/sso/apache':
|
||||||
|
ensure => directory,
|
||||||
|
}
|
||||||
|
|
||||||
|
file { '/opt/sso/apache/site.conf':
|
||||||
|
ensure => file,
|
||||||
|
content => template('soc/sso/apache-site.conf.erb'),
|
||||||
|
}
|
||||||
|
|
||||||
|
# SSL defaults copied from certbot:
|
||||||
|
# https://github.com/certbot/certbot/blob/master/certbot-apache/certbot_apache/_internal/tls_configs/current-options-ssl-apache.conf
|
||||||
|
file { '/opt/sso/apache/ssl.conf':
|
||||||
|
ensure => file,
|
||||||
|
content => file('soc/sso/apache-ssl.conf'),
|
||||||
|
}
|
||||||
|
|
||||||
|
file { '/opt/sso/apache/groups.txt':
|
||||||
|
ensure => file,
|
||||||
|
content => template('soc/sso/apache-groups.txt.erb')
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Shibboleth files
|
||||||
|
#
|
||||||
|
|
||||||
|
file { '/opt/sso/shibboleth':
|
||||||
|
ensure => directory,
|
||||||
|
}
|
||||||
|
|
||||||
|
file { '/opt/sso/shibboleth/shibboleth2.xml':
|
||||||
|
ensure => file,
|
||||||
|
content => template('soc/sso/shibboleth2.xml.erb'),
|
||||||
|
}
|
||||||
|
|
||||||
|
file { '/opt/sso/shibboleth/shibd.logger':
|
||||||
|
ensure => file,
|
||||||
|
content => template('soc/sso/shibd.logger.erb'),
|
||||||
|
}
|
||||||
|
|
||||||
|
file { '/opt/sso/shibboleth/attribute-map.xml':
|
||||||
|
ensure => file,
|
||||||
|
content => file('soc/sso/attribute-map.xml'),
|
||||||
|
}
|
||||||
|
|
||||||
|
file { '/opt/sso/shibboleth/md-signer2.crt':
|
||||||
|
ensure => file,
|
||||||
|
content => file('soc/sso/md-signer2.crt'),
|
||||||
|
}
|
||||||
|
sunet::snippets::secret_file { '/opt/sso/shibboleth/sp-key.pem':
|
||||||
|
hiera_key => 'sso_sp_key'
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Certbot
|
||||||
|
#
|
||||||
|
|
||||||
|
if $certbot {
|
||||||
|
package { ['certbot', 'python3-requests']:
|
||||||
|
ensure => 'latest',
|
||||||
|
}
|
||||||
|
|
||||||
|
file { '/etc/letsencrypt/acme-dns-auth.py':
|
||||||
|
ensure => file,
|
||||||
|
content => file('cnaas/sso/acme-dns-auth.py'),
|
||||||
|
mode => '0744',
|
||||||
|
}
|
||||||
|
|
||||||
|
file { '/etc/letsencrypt/renewal-hooks/deploy/soc-sso-reload':
|
||||||
|
ensure => file,
|
||||||
|
mode => '0700',
|
||||||
|
content => "#!/bin/sh -eu\ndocker exec sso service apache2 reload",
|
||||||
|
}
|
||||||
|
|
||||||
|
sunet::scriptherder::cronjob { 'le_renew':
|
||||||
|
cmd => '/bin/echo "Keeping this cronjob, but disabled to avoid scriptherder complainign about unknown check"',
|
||||||
|
special => 'daily',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Docker
|
||||||
|
#
|
||||||
|
|
||||||
|
exec {"Create Docker network \"sso\" to talk to service":
|
||||||
|
# We OR with true to ignore errors, since the network often already exists.
|
||||||
|
# We specify a subnet so that services which have the option/requirement can
|
||||||
|
# specify this subnet as source of trusted proxies. This is used in Graylog,
|
||||||
|
# for example; see setting "trusted_proxies".
|
||||||
|
command => 'docker network create sso --subnet 172.29.0.0/24 || true'
|
||||||
|
}
|
||||||
|
|
||||||
|
file { '/opt/sso/docker-compose.yml':
|
||||||
|
ensure => file,
|
||||||
|
mode => '0600',
|
||||||
|
content => template('soc/sso/docker-compose.yml.erb'),
|
||||||
|
}
|
||||||
|
|
||||||
|
sunet::docker_compose_service { 'sso':
|
||||||
|
description => '',
|
||||||
|
compose_file => '/opt/sso/docker-compose.yml',
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# NFT Rules
|
||||||
|
#
|
||||||
|
|
||||||
|
if 'wg0' in $facts['networking']['interfaces'].keys {
|
||||||
|
if $front_clients != '' {
|
||||||
|
$front_clients_exposed = hiera_array($front_clients,[])
|
||||||
|
sunet::nftables::docker_expose { 'clients_https' :
|
||||||
|
allow_clients => $front_clients_exposed,
|
||||||
|
port => 443,
|
||||||
|
iif => 'wg0',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sunet::nftables::docker_expose { 'apache_sso_https' :
|
||||||
|
allow_clients => ['0.0.0.0/0'],
|
||||||
|
port => 443,
|
||||||
|
iif => 'ens3',
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
<%- scope.call_function('safe_hiera',['sso_groups']).each do | group, users | -%>
|
||||||
|
<%= group %>: <% users.each.with_index do | user, i | %><%= user %><%= ' ' if i < (users.size - 1) %><% end %>
|
||||||
|
<%- end -%>
|
|
@ -0,0 +1,63 @@
|
||||||
|
<IfModule mod_ssl.c>
|
||||||
|
<VirtualHost *:443>
|
||||||
|
# The ServerName directive sets the request scheme, hostname and port that
|
||||||
|
# the server uses to identify itself. This is used when creating
|
||||||
|
# redirection URLs. In the context of virtual hosts, the ServerName
|
||||||
|
# specifies what hostname must appear in the request's Host: header to
|
||||||
|
# match this virtual host. For the default virtual host (this file) this
|
||||||
|
# value is not decisive as it is used as a last resort host regardless.
|
||||||
|
# However, you must set it for any further virtual host explicitly.
|
||||||
|
|
||||||
|
ServerName <%= @hostname %>
|
||||||
|
ServerAdmin <%= @email %>
|
||||||
|
|
||||||
|
# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
|
||||||
|
# error, crit, alert, emerg.
|
||||||
|
# It is also possible to configure the loglevel for particular
|
||||||
|
# modules, e.g.
|
||||||
|
#LogLevel info ssl:warn
|
||||||
|
|
||||||
|
ErrorLog ${APACHE_LOG_DIR}/error.log
|
||||||
|
CustomLog ${APACHE_LOG_DIR}/access.log combined
|
||||||
|
|
||||||
|
# For most configuration files from conf-available/, which are
|
||||||
|
# enabled or disabled at a global level, it is possible to
|
||||||
|
# include a line for only one particular virtual host. For example the
|
||||||
|
# following line enables the CGI configuration for this host only
|
||||||
|
# after it has been globally disabled with "a2disconf".
|
||||||
|
#Include conf-available/serve-cgi-bin.conf
|
||||||
|
|
||||||
|
<Location />
|
||||||
|
AuthType shibboleth
|
||||||
|
ShibRequestSetting requireSession On
|
||||||
|
|
||||||
|
<%- if @x_remote_user -%>
|
||||||
|
RequestHeader set X-Remote-User %{REMOTE_USER}s
|
||||||
|
<%- elsif @single_user -%>
|
||||||
|
RequestHeader set X-Remote-User soc-user
|
||||||
|
<%- else -%>
|
||||||
|
ShibUseHeaders On
|
||||||
|
<%- end -%>
|
||||||
|
|
||||||
|
AuthGroupFile /etc/apache2/groups.txt
|
||||||
|
Require group <% @groups.each.with_index do |group, i| %><%= group %><%= ' ' if i < (@groups.size - 1) %><% end %>
|
||||||
|
</Location>
|
||||||
|
<%- @passthrough.each do |path| -%>
|
||||||
|
|
||||||
|
<Location <%= path %>>
|
||||||
|
AuthType None
|
||||||
|
Require all granted
|
||||||
|
</Location>
|
||||||
|
<%- end -%>
|
||||||
|
|
||||||
|
ProxyPass "/" "<%= @service_endpoint %>/"
|
||||||
|
ProxyPassReverse "/" "<%= @service_endpoint %>/"
|
||||||
|
UseCanonicalName On
|
||||||
|
ProxyPreserveHost On
|
||||||
|
|
||||||
|
ServerAlias <%= @hostname %>
|
||||||
|
SSLCertificateFile /etc/letsencrypt/live/<%= @hostname %>/fullchain.pem
|
||||||
|
SSLCertificateKeyFile /etc/letsencrypt/live/<%= @hostname %>/privkey.pem
|
||||||
|
Include /etc/apache2/ssl.conf
|
||||||
|
</VirtualHost>
|
||||||
|
</IfModule>
|
|
@ -0,0 +1,23 @@
|
||||||
|
version: "3"
|
||||||
|
services:
|
||||||
|
sso:
|
||||||
|
container_name: sso
|
||||||
|
image: "docker.sunet.se/apache-shib"
|
||||||
|
ports:
|
||||||
|
- "443:443"
|
||||||
|
networks:
|
||||||
|
- sso
|
||||||
|
volumes:
|
||||||
|
- /etc/letsencrypt:/etc/letsencrypt
|
||||||
|
- ./apache/site.conf:/etc/apache2/sites-enabled/site.conf
|
||||||
|
- ./apache/ssl.conf:/etc/apache2/ssl.conf
|
||||||
|
- ./apache/groups.txt:/etc/apache2/groups.txt
|
||||||
|
- ./shibboleth/shibboleth2.xml:/etc/shibboleth/shibboleth2.xml
|
||||||
|
- ./shibboleth/shibd.logger:/etc/shibboleth/shibd.logger
|
||||||
|
- ./shibboleth/attribute-map.xml:/etc/shibboleth/attribute-map.xml
|
||||||
|
- ./shibboleth/md-signer2.crt:/etc/shibboleth/md-signer2.crt
|
||||||
|
- ./shibboleth/sp-cert.pem:/etc/shibboleth/sp-cert.pem
|
||||||
|
- ./shibboleth/sp-key.pem:/etc/shibboleth/sp-key.pem
|
||||||
|
networks:
|
||||||
|
sso:
|
||||||
|
external: true
|
140
global/overlay/etc/puppet/soc/templates/sso/shibboleth2.xml.erb
Normal file
140
global/overlay/etc/puppet/soc/templates/sso/shibboleth2.xml.erb
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
<SPConfig xmlns="urn:mace:shibboleth:3.0:native:sp:config"
|
||||||
|
xmlns:conf="urn:mace:shibboleth:3.0:native:sp:config"
|
||||||
|
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
|
||||||
|
xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
|
||||||
|
xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"
|
||||||
|
clockSkew="180">
|
||||||
|
|
||||||
|
<!--
|
||||||
|
By default, in-memory StorageService, ReplayCache, ArtifactMap, and SessionCache
|
||||||
|
are used. See example-shibboleth2.xml for samples of explicitly configuring them.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!-- The ApplicationDefaults element is where most of Shibboleth's SAML bits are defined. -->
|
||||||
|
<ApplicationDefaults entityID="https://<%= @hostname %>"
|
||||||
|
REMOTE_USER="eppn subject-id"
|
||||||
|
metadataAttributePrefix="Meta-">
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Controls session lifetimes, address checks, cookie handling, and the protocol handlers.
|
||||||
|
You MUST supply an effectively unique handlerURL value for each of your applications.
|
||||||
|
The value defaults to /Shibboleth.sso, and should be a relative path, with the SP computing
|
||||||
|
a relative value based on the virtual host. Using handlerSSL="true", the default, will force
|
||||||
|
the protocol to be https. You should also set cookieProps to "https" for SSL-only sites.
|
||||||
|
Note that while we default checkAddress to "false", this has a negative impact on the
|
||||||
|
security of your site. Stealing sessions via cookie theft is much easier with this disabled.
|
||||||
|
-->
|
||||||
|
<Sessions lifetime="28800" timeout="3600" relayState="ss:mem"
|
||||||
|
checkAddress="false" handlerSSL="true" cookieProps="https">
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Configures SSO for a default IdP. To allow for >1 IdP, remove
|
||||||
|
entityID property and adjust discoveryURL to point to discovery service.
|
||||||
|
If you use this, you have to remove the SessionInitiator below.
|
||||||
|
<SSO entityID="https://swamididp.example.org
|
||||||
|
discoveryProtocol="SAMLDS" discoveryURL="https://ds.example.org/DS/WAYF">
|
||||||
|
SAML2 SAML1
|
||||||
|
</SSO>
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!-- SAML and local-only logout. -->
|
||||||
|
|
||||||
|
<Logout>SAML2 Local</Logout>
|
||||||
|
<SessionInitiator type="Chaining" Location="/DS/Login" id="swamid-ds-default" relayState="cookie">
|
||||||
|
<SessionInitiator type="SAML2" defaultACSIndex="1" acsByIndex="false" template="bindingTemplate.html"/>
|
||||||
|
<SessionInitiator type="Shib1" defaultACSIndex="5"/>
|
||||||
|
<%- if @swamid_testing -%>
|
||||||
|
<SessionInitiator type="SAMLDS" URL="https://ds-test.swamid.se/role/idp.ds"/>
|
||||||
|
<%- else -%>
|
||||||
|
<SessionInitiator type="SAMLDS" URL="https://service.seamlessaccess.org/ds"/>
|
||||||
|
<%- end -%>
|
||||||
|
</SessionInitiator>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
md:AssertionConsumerService locations handle specific SSO protocol bindings,
|
||||||
|
such as SAML 2.0 POST or SAML 1.1 Artifact. The isDefault and index attributes
|
||||||
|
are used when sessions are initiated to determine how to tell the IdP where and
|
||||||
|
how to return the response.
|
||||||
|
-->
|
||||||
|
<md:AssertionConsumerService Location="/SAML2/POST" index="1"
|
||||||
|
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
|
||||||
|
conf:ignoreNoPassive="true"/>
|
||||||
|
|
||||||
|
<!-- Extension service that generates "approximate" metadata based on SP configuration. -->
|
||||||
|
<Handler type="MetadataGenerator" Location="/Metadata" signing="false"/>
|
||||||
|
|
||||||
|
<!-- Status reporting service. -->
|
||||||
|
<Handler type="Status" Location="/Status" acl="127.0.0.1 ::1"/>
|
||||||
|
|
||||||
|
<!-- Session diagnostic service. -->
|
||||||
|
<Handler type="Session" Location="/Session" showAttributeValues="false"/>
|
||||||
|
|
||||||
|
<!-- JSON feed of discovery information. -->
|
||||||
|
<Handler type="DiscoveryFeed" Location="/DiscoFeed"/>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
md:ArtifactResolutionService locations resolve artifacts issued when using the
|
||||||
|
SAML 2.0 HTTP-Artifact binding on outgoing messages, generally uses SOAP.
|
||||||
|
-->
|
||||||
|
<md:ArtifactResolutionService Location="/Artifact/SOAP" index="1"
|
||||||
|
Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP"/>
|
||||||
|
|
||||||
|
</Sessions>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Allows overriding of error template information/filenames. You can
|
||||||
|
also add attributes with values that can be plugged into the templates.
|
||||||
|
-->
|
||||||
|
<Errors supportContact="<%= @email %>"
|
||||||
|
helpLocation="/about.html"
|
||||||
|
styleSheet="/shibboleth-sp/main.css"/>
|
||||||
|
|
||||||
|
<!-- Example of remotely supplied batch of signed metadata. -->
|
||||||
|
|
||||||
|
<!-- SWAMID Metadata -->
|
||||||
|
<%- if @swamid_testing -%>
|
||||||
|
<MetadataProvider
|
||||||
|
type="XML"
|
||||||
|
url="https://mds.swamid.se/md/swamid-testing-idp-1.0.xml"
|
||||||
|
backingFilePath="swamid-testing-idp-1.0.xml" reloadInterval="300">
|
||||||
|
<MetadataFilter type="Signature" certificate="md-signer2.crt"/>
|
||||||
|
</MetadataProvider>
|
||||||
|
<%- elsif @satosa -%>
|
||||||
|
<MetadataProvider
|
||||||
|
type="XML"
|
||||||
|
path="frontend.xml"/>
|
||||||
|
<%- else -%>
|
||||||
|
<MetadataProvider
|
||||||
|
type="XML"
|
||||||
|
url="http://mds.swamid.se/md/swamid-idp.xml"
|
||||||
|
backingFilePath="swamid-idp.xml" reloadInterval="300">
|
||||||
|
<MetadataFilter type="Signature" certificate="md-signer2.crt"/>
|
||||||
|
</MetadataProvider>
|
||||||
|
<%- end -%>
|
||||||
|
|
||||||
|
<!-- Example of locally maintained metadata. -->
|
||||||
|
<!--
|
||||||
|
<MetadataProvider type="XML" file="partner-metadata.xml"/>
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!-- Map to extract attributes from SAML assertions. -->
|
||||||
|
<AttributeExtractor type="XML" validate="true" reloadChanges="false" path="attribute-map.xml"/>
|
||||||
|
|
||||||
|
<!-- Use a SAML query if no attributes are supplied during SSO. -->
|
||||||
|
<AttributeResolver type="Query" subjectMatch="true"/>
|
||||||
|
|
||||||
|
<!-- Default filtering policy for recognized attributes, lets other data pass. -->
|
||||||
|
<AttributeFilter type="XML" validate="true" path="attribute-policy.xml"/>
|
||||||
|
|
||||||
|
<!-- Simple file-based resolver for using a single keypair. -->
|
||||||
|
<CredentialResolver type="File" key="sp-key.pem" certificate="sp-cert.pem"/>
|
||||||
|
|
||||||
|
</ApplicationDefaults>
|
||||||
|
|
||||||
|
<!-- Policies that determine how to process and authenticate runtime messages. -->
|
||||||
|
<SecurityPolicyProvider type="XML" validate="true" path="security-policy.xml"/>
|
||||||
|
|
||||||
|
<!-- Low-level configuration about protocols and bindings available for use. -->
|
||||||
|
<ProtocolProvider type="XML" validate="true" reloadChanges="false" path="protocols.xml"/>
|
||||||
|
|
||||||
|
</SPConfig>
|
72
global/overlay/etc/puppet/soc/templates/sso/shibd.logger.erb
Normal file
72
global/overlay/etc/puppet/soc/templates/sso/shibd.logger.erb
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
# set overall behavior
|
||||||
|
log4j.rootCategory=INFO, shibd_log, warn_log
|
||||||
|
|
||||||
|
# fairly verbose for DEBUG, so generally leave at INFO
|
||||||
|
log4j.category.XMLTooling.XMLObject=INFO
|
||||||
|
log4j.category.XMLTooling.KeyInfoResolver=INFO
|
||||||
|
log4j.category.Shibboleth.IPRange=INFO
|
||||||
|
log4j.category.Shibboleth.PropertySet=INFO
|
||||||
|
|
||||||
|
# raise for low-level tracing of SOAP client HTTP/SSL behavior
|
||||||
|
log4j.category.XMLTooling.libcurl=INFO
|
||||||
|
|
||||||
|
# useful categories to tune independently:
|
||||||
|
#
|
||||||
|
# tracing of SAML messages and security policies
|
||||||
|
#log4j.category.OpenSAML.MessageDecoder=DEBUG
|
||||||
|
#log4j.category.OpenSAML.MessageEncoder=DEBUG
|
||||||
|
#log4j.category.OpenSAML.SecurityPolicyRule=DEBUG
|
||||||
|
#log4j.category.XMLTooling.SOAPClient=DEBUG
|
||||||
|
# interprocess message remoting
|
||||||
|
#log4j.category.Shibboleth.Listener=DEBUG
|
||||||
|
# mapping of requests to applicationId
|
||||||
|
#log4j.category.Shibboleth.RequestMapper=DEBUG
|
||||||
|
# high level session cache operations
|
||||||
|
#log4j.category.Shibboleth.SessionCache=DEBUG
|
||||||
|
# persistent storage and caching
|
||||||
|
#log4j.category.XMLTooling.StorageService=DEBUG
|
||||||
|
|
||||||
|
# logs XML being signed or verified if set to DEBUG
|
||||||
|
log4j.category.XMLTooling.Signature.Debugger=INFO, sig_log
|
||||||
|
log4j.additivity.XMLTooling.Signature.Debugger=false
|
||||||
|
log4j.ownAppenders.XMLTooling.Signature.Debugger=true
|
||||||
|
|
||||||
|
# the tran log blocks the "default" appender(s) at runtime
|
||||||
|
# Level should be left at INFO for this category
|
||||||
|
log4j.category.Shibboleth-TRANSACTION=<%= @translog %>, tran_log
|
||||||
|
log4j.additivity.Shibboleth-TRANSACTION=false
|
||||||
|
log4j.ownAppenders.Shibboleth-TRANSACTION=true
|
||||||
|
|
||||||
|
# uncomment to suppress particular event types
|
||||||
|
#log4j.category.Shibboleth-TRANSACTION.AuthnRequest=WARN
|
||||||
|
#log4j.category.Shibboleth-TRANSACTION.Login=WARN
|
||||||
|
#log4j.category.Shibboleth-TRANSACTION.Logout=WARN
|
||||||
|
|
||||||
|
# define the appenders
|
||||||
|
|
||||||
|
log4j.appender.shibd_log=org.apache.log4j.RollingFileAppender
|
||||||
|
log4j.appender.shibd_log.fileName=/var/log/shibboleth/shibd.log
|
||||||
|
log4j.appender.shibd_log.maxFileSize=1000000
|
||||||
|
log4j.appender.shibd_log.maxBackupIndex=10
|
||||||
|
log4j.appender.shibd_log.layout=org.apache.log4j.PatternLayout
|
||||||
|
log4j.appender.shibd_log.layout.ConversionPattern=%d{%Y-%m-%d %H:%M:%S} %p %c %x: %m%n
|
||||||
|
|
||||||
|
log4j.appender.warn_log=org.apache.log4j.RollingFileAppender
|
||||||
|
log4j.appender.warn_log.fileName=/var/log/shibboleth/shibd_warn.log
|
||||||
|
log4j.appender.warn_log.maxFileSize=1000000
|
||||||
|
log4j.appender.warn_log.maxBackupIndex=10
|
||||||
|
log4j.appender.warn_log.layout=org.apache.log4j.PatternLayout
|
||||||
|
log4j.appender.warn_log.layout.ConversionPattern=%d{%Y-%m-%d %H:%M:%S} %p %c %x: %m%n
|
||||||
|
log4j.appender.warn_log.threshold=WARN
|
||||||
|
|
||||||
|
log4j.appender.tran_log=org.apache.log4j.RollingFileAppender
|
||||||
|
log4j.appender.tran_log.fileName=/var/log/shibboleth/transaction.log
|
||||||
|
log4j.appender.tran_log.maxFileSize=1000000
|
||||||
|
log4j.appender.tran_log.maxBackupIndex=20
|
||||||
|
log4j.appender.tran_log.layout=org.apache.log4j.PatternLayout
|
||||||
|
log4j.appender.tran_log.layout.ConversionPattern=%d{%Y-%m-%d %H:%M:%S}|%c|%m%n
|
||||||
|
|
||||||
|
log4j.appender.sig_log=org.apache.log4j.FileAppender
|
||||||
|
log4j.appender.sig_log.fileName=/var/log/shibboleth/signature.log
|
||||||
|
log4j.appender.sig_log.layout=org.apache.log4j.PatternLayout
|
||||||
|
log4j.appender.sig_log.layout.ConversionPattern=%m
|
Loading…
Add table
Reference in a new issue