diff --git a/global/overlay/etc/puppet/soc/facts.d/.empty b/global/overlay/etc/puppet/soc/facts.d/.empty new file mode 100644 index 0000000..e69de29 diff --git a/global/overlay/etc/puppet/soc/files/sso/acme-dns-auth.py b/global/overlay/etc/puppet/soc/files/sso/acme-dns-auth.py new file mode 100755 index 0000000..6873088 --- /dev/null +++ b/global/overlay/etc/puppet/soc/files/sso/acme-dns-auth.py @@ -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) diff --git a/global/overlay/etc/puppet/soc/files/sso/apache-ssl.conf b/global/overlay/etc/puppet/soc/files/sso/apache-ssl.conf new file mode 100644 index 0000000..6f61ba9 --- /dev/null +++ b/global/overlay/etc/puppet/soc/files/sso/apache-ssl.conf @@ -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 \ No newline at end of file diff --git a/global/overlay/etc/puppet/soc/files/sso/attribute-map.xml b/global/overlay/etc/puppet/soc/files/sso/attribute-map.xml new file mode 100644 index 0000000..6555029 --- /dev/null +++ b/global/overlay/etc/puppet/soc/files/sso/attribute-map.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + diff --git a/global/overlay/etc/puppet/soc/files/sso/attribute-policy.xml b/global/overlay/etc/puppet/soc/files/sso/attribute-policy.xml new file mode 100644 index 0000000..00b1455 --- /dev/null +++ b/global/overlay/etc/puppet/soc/files/sso/attribute-policy.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/global/overlay/etc/puppet/soc/files/sso/md-signer2.crt b/global/overlay/etc/puppet/soc/files/sso/md-signer2.crt new file mode 100644 index 0000000..f182c7a --- /dev/null +++ b/global/overlay/etc/puppet/soc/files/sso/md-signer2.crt @@ -0,0 +1,33 @@ +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- diff --git a/global/overlay/etc/puppet/soc/manifests/.empty b/global/overlay/etc/puppet/soc/manifests/.empty new file mode 100644 index 0000000..e69de29 diff --git a/global/overlay/etc/puppet/soc/manifests/sso.pp b/global/overlay/etc/puppet/soc/manifests/sso.pp new file mode 100644 index 0000000..2bb9def --- /dev/null +++ b/global/overlay/etc/puppet/soc/manifests/sso.pp @@ -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', + } + +} diff --git a/global/overlay/etc/puppet/soc/templates/sso/apache-groups.txt.erb b/global/overlay/etc/puppet/soc/templates/sso/apache-groups.txt.erb new file mode 100644 index 0000000..27f779a --- /dev/null +++ b/global/overlay/etc/puppet/soc/templates/sso/apache-groups.txt.erb @@ -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 -%> diff --git a/global/overlay/etc/puppet/soc/templates/sso/apache-site.conf.erb b/global/overlay/etc/puppet/soc/templates/sso/apache-site.conf.erb new file mode 100644 index 0000000..5dfd133 --- /dev/null +++ b/global/overlay/etc/puppet/soc/templates/sso/apache-site.conf.erb @@ -0,0 +1,63 @@ + + + # 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 + + + 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 %> + + <%- @passthrough.each do |path| -%> + + > + AuthType None + Require all granted + + <%- 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 + + diff --git a/global/overlay/etc/puppet/soc/templates/sso/docker-compose.yml.erb b/global/overlay/etc/puppet/soc/templates/sso/docker-compose.yml.erb new file mode 100644 index 0000000..e1813f8 --- /dev/null +++ b/global/overlay/etc/puppet/soc/templates/sso/docker-compose.yml.erb @@ -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 diff --git a/global/overlay/etc/puppet/soc/templates/sso/shibboleth2.xml.erb b/global/overlay/etc/puppet/soc/templates/sso/shibboleth2.xml.erb new file mode 100644 index 0000000..cae74ac --- /dev/null +++ b/global/overlay/etc/puppet/soc/templates/sso/shibboleth2.xml.erb @@ -0,0 +1,140 @@ + + + + + + + + + + + + + + + SAML2 Local + + + + <%- if @swamid_testing -%> + + <%- else -%> + + <%- end -%> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <%- if @swamid_testing -%> + + + + <%- elsif @satosa -%> + + <%- else -%> + + + + <%- end -%> + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/global/overlay/etc/puppet/soc/templates/sso/shibd.logger.erb b/global/overlay/etc/puppet/soc/templates/sso/shibd.logger.erb new file mode 100644 index 0000000..815e714 --- /dev/null +++ b/global/overlay/etc/puppet/soc/templates/sso/shibd.logger.erb @@ -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