diff --git a/keystone/.gitignore b/keystone/.gitignore
deleted file mode 100644
index f432e90..0000000
--- a/keystone/.gitignore
+++ /dev/null
@@ -1,8 +0,0 @@
-# ---> Vim
-[._]*.s[a-w][a-z]
-[._]s[a-w][a-z]
-*.un~
-Session.vim
-.netrwhist
-*~
-
diff --git a/keystone/Dockerfile b/keystone/Dockerfile
index d757a54..1634dee 100644
--- a/keystone/Dockerfile
+++ b/keystone/Dockerfile
@@ -13,16 +13,36 @@ RUN set -x \
&& apt-get -y update \
&& apt-get -y install \
&& apt-get -y install keystone python-openstackclient \
+ && apt-get -y install libapache2-mod-shib2 \
&& apt-get -y clean
# set admin token TODO: make this a secret
# in volume of met env
COPY keystone.conf /etc/keystone/keystone.conf
+COPY apache-keystone.conf /etc/apache2/sites-available/keystone.conf
+
+COPY shibboleth2.xml /etc/shibboleth/shibboleth2.xml
+COPY attribute-map.xml /etc/shibboleth/attribute-map.xml
+COPY attribute-policy.xml /etc/shibboleth/attribute-policy.xml
+
+COPY sso_callback_template.html /etc/keystone/sso_callback_template.html
+
+RUN mkdir /var/run/shibboleth
+
+COPY run.sh /etc/run.sh
+
RUN mkdir /etc/keystone/fernet-keys
RUN chown keystone: /etc/keystone/fernet-keys
+RUN a2enmod shib2
+
COPY bootstrap.sh /etc/bootstrap.sh
-CMD apachectl -DFOREGROUND
+# Testing only!!!
+RUN mkdir -p /var/www/html/secure
+RUN apt-get -y install php libapache2-mod-php
+COPY test.php /var/www/html/secure/test.php
+
+CMD /etc/run.sh
diff --git a/keystone/apache-keystone.conf b/keystone/apache-keystone.conf
new file mode 100644
index 0000000..99e0111
--- /dev/null
+++ b/keystone/apache-keystone.conf
@@ -0,0 +1,126 @@
+LoadModule ssl_module modules/mod_ssl.so
+
+Listen 5000
+Listen 35357
+
+
+ AuthType shibboleth
+ ShibRequestSetting requireSession 1
+ require valid-user
+
+
+Alias "/secure" "/var/www/html/secure"
+
+
+ ServerName https://merlin.hpc.rug.nl:5000
+ SSLEngine on
+ SSLCertificateFile "/certs/merlin.hpc.rug.nl.crt"
+ SSLCertificateKeyFile "/certs/merlin.hpc.rug.nl.key"
+ UseCanonicalName On
+ WSGIScriptAlias / /usr/bin/keystone-wsgi-public
+ WSGIDaemonProcess keystone-public processes=5 threads=1 user=keystone group=keystone display-name=%{GROUP}
+ WSGIProcessGroup keystone-public
+ WSGIApplicationGroup %{GLOBAL}
+ WSGIPassAuthorization On
+ LimitRequestBody 114688
+
+ # Added for federation.
+ WSGIScriptAliasMatch ^(/v3/OS-FEDERATION/identity_providers/.*?/protocols/.*?/auth)$ /usr/local/bin/keystone-wsgi-public/$1
+
+ = 2.4>
+ ErrorLogFormat "%{cu}t %M"
+
+
+ ErrorLog /var/log/apache2/keystone.log
+ CustomLog /var/log/apache2/keystone_access.log combined
+
+
+ = 2.4>
+ Require all granted
+
+
+ Order allow,deny
+ Allow from all
+
+
+
+
+ SetHandler shib
+
+
+
+ ShibRequestSetting requireSession 1
+ AuthType shibboleth
+ ShibExportAssertion Off
+ Require valid-user
+
+
+ ShibRequireSession On
+ ShibRequireAll On
+
+
+
+
+ AuthType shibboleth
+ Require valid-user
+ ShibRequestSetting requireSession 1
+ ShibRequireSession On
+ ShibExportAssertion Off
+
+
+ AuthType shibboleth
+ Require valid-user
+
+
+
+
+
+ ServerName https://merlin.hpc.rug.nl:35357
+ SSLEngine on
+ SSLCertificateFile "/certs/merlin.hpc.rug.nl.crt"
+ SSLCertificateKeyFile "/certs/merlin.hpc.rug.nl.key"
+ UseCanonicalName On
+ WSGIScriptAlias / /usr/bin/keystone-wsgi-admin
+ WSGIDaemonProcess keystone-admin processes=5 threads=1 user=keystone group=keystone display-name=%{GROUP}
+ WSGIProcessGroup keystone-admin
+ WSGIApplicationGroup %{GLOBAL}
+ WSGIPassAuthorization On
+ LimitRequestBody 114688
+
+ = 2.4>
+ ErrorLogFormat "%{cu}t %M"
+
+
+ ErrorLog /var/log/apache2/keystone.log
+ CustomLog /var/log/apache2/keystone_access.log combined
+
+
+ = 2.4>
+ Require all granted
+
+
+ Order allow,deny
+ Allow from all
+
+
+
+
+Alias /identity /usr/bin/keystone-wsgi-public
+
+ SetHandler wsgi-script
+ Options +ExecCGI
+
+ WSGIProcessGroup keystone-public
+ WSGIApplicationGroup %{GLOBAL}
+ WSGIPassAuthorization On
+
+
+Alias /identity_admin /usr/bin/keystone-wsgi-admin
+
+ SetHandler wsgi-script
+ Options +ExecCGI
+
+ WSGIProcessGroup keystone-admin
+ WSGIApplicationGroup %{GLOBAL}
+ WSGIPassAuthorization On
+
diff --git a/keystone/attribute-map.xml b/keystone/attribute-map.xml
new file mode 100644
index 0000000..c641cca
--- /dev/null
+++ b/keystone/attribute-map.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/keystone/attribute-policy.xml b/keystone/attribute-policy.xml
new file mode 100644
index 0000000..055567d
--- /dev/null
+++ b/keystone/attribute-policy.xml
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/keystone/keystone.conf b/keystone/keystone.conf
index ae08a24..2e85c6a 100644
--- a/keystone/keystone.conf
+++ b/keystone/keystone.conf
@@ -1,6 +1,7 @@
[DEFAULT]
verbose = true
+log_file = /var/log/keystone/keystone.log
[database]
connection = mysql+pymysql://keystone:keystone@mariadb/keystone
@@ -8,5 +9,15 @@ connection = mysql+pymysql://keystone:keystone@mariadb/keystone
[token]
provider = fernet
+[auth]
+methods = password,token,mapped,openid,saml2
+
+[federation]
+trusted_dashboard = http://merlin.hpc.rug.nl/horizon/auth/websso/
+sso_calback_template = /etc/keystone/sso_calback_template.html
+
+[mapped]
+remote_id_attribute = Shib-Identity-Provider
+
[identity]
default_domain_id = default
diff --git a/keystone/routers.py b/keystone/routers.py
new file mode 100644
index 0000000..419dd4e
--- /dev/null
+++ b/keystone/routers.py
@@ -0,0 +1,252 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import functools
+
+from keystone.common import json_home
+from keystone.common import wsgi
+from keystone.federation import controllers
+
+
+build_resource_relation = functools.partial(
+ json_home.build_v3_extension_resource_relation,
+ extension_name='OS-FEDERATION', extension_version='1.0')
+
+build_parameter_relation = functools.partial(
+ json_home.build_v3_extension_parameter_relation,
+ extension_name='OS-FEDERATION', extension_version='1.0')
+
+IDP_ID_PARAMETER_RELATION = build_parameter_relation(parameter_name='idp_id')
+PROTOCOL_ID_PARAMETER_RELATION = build_parameter_relation(
+ parameter_name='protocol_id')
+SP_ID_PARAMETER_RELATION = build_parameter_relation(parameter_name='sp_id')
+
+
+class Routers(wsgi.RoutersBase):
+ """API Endpoints for the Federation extension.
+
+ The API looks like::
+
+ PUT /OS-FEDERATION/identity_providers/{idp_id}
+ GET /OS-FEDERATION/identity_providers
+ GET /OS-FEDERATION/identity_providers/{idp_id}
+ DELETE /OS-FEDERATION/identity_providers/{idp_id}
+ PATCH /OS-FEDERATION/identity_providers/{idp_id}
+
+ PUT /OS-FEDERATION/identity_providers/
+ {idp_id}/protocols/{protocol_id}
+ GET /OS-FEDERATION/identity_providers/
+ {idp_id}/protocols
+ GET /OS-FEDERATION/identity_providers/
+ {idp_id}/protocols/{protocol_id}
+ PATCH /OS-FEDERATION/identity_providers/
+ {idp_id}/protocols/{protocol_id}
+ DELETE /OS-FEDERATION/identity_providers/
+ {idp_id}/protocols/{protocol_id}
+
+ PUT /OS-FEDERATION/mappings
+ GET /OS-FEDERATION/mappings
+ PATCH /OS-FEDERATION/mappings/{mapping_id}
+ GET /OS-FEDERATION/mappings/{mapping_id}
+ DELETE /OS-FEDERATION/mappings/{mapping_id}
+
+ GET /OS-FEDERATION/projects
+ GET /OS-FEDERATION/domains
+
+ PUT /OS-FEDERATION/service_providers/{sp_id}
+ GET /OS-FEDERATION/service_providers
+ GET /OS-FEDERATION/service_providers/{sp_id}
+ DELETE /OS-FEDERATION/service_providers/{sp_id}
+ PATCH /OS-FEDERATION/service_providers/{sp_id}
+
+ GET /OS-FEDERATION/identity_providers/{idp_id}/
+ protocols/{protocol_id}/auth
+ POST /OS-FEDERATION/identity_providers/{idp_id}/
+ protocols/{protocol_id}/auth
+ GET /auth/OS-FEDERATION/identity_providers/
+ {idp_id}/protocols/{protocol_id}/websso
+ ?origin=https%3A//horizon.example.com
+ POST /auth/OS-FEDERATION/identity_providers/
+ {idp_id}/protocols/{protocol_id}/websso
+ ?origin=https%3A//horizon.example.com
+
+
+ POST /auth/OS-FEDERATION/saml2
+ POST /auth/OS-FEDERATION/saml2/ecp
+ GET /OS-FEDERATION/saml2/metadata
+
+ GET /auth/OS-FEDERATION/websso/{protocol_id}
+ ?origin=https%3A//horizon.example.com
+
+ POST /auth/OS-FEDERATION/websso/{protocol_id}
+ ?origin=https%3A//horizon.example.com
+
+ """
+
+ def _construct_url(self, suffix):
+ return "/OS-FEDERATION/%s" % suffix
+
+ def append_v3_routers(self, mapper, routers):
+ auth_controller = controllers.Auth()
+ idp_controller = controllers.IdentityProvider()
+ protocol_controller = controllers.FederationProtocol()
+ mapping_controller = controllers.MappingController()
+ project_controller = controllers.ProjectAssignmentV3()
+ domain_controller = controllers.DomainV3()
+ saml_metadata_controller = controllers.SAMLMetadataV3()
+ sp_controller = controllers.ServiceProvider()
+
+ # Identity Provider CRUD operations
+
+ self._add_resource(
+ mapper, idp_controller,
+ path=self._construct_url('identity_providers/{idp_id}'),
+ get_action='get_identity_provider',
+ put_action='create_identity_provider',
+ patch_action='update_identity_provider',
+ delete_action='delete_identity_provider',
+ rel=build_resource_relation(resource_name='identity_provider'),
+ path_vars={
+ 'idp_id': IDP_ID_PARAMETER_RELATION,
+ })
+ self._add_resource(
+ mapper, idp_controller,
+ path=self._construct_url('identity_providers'),
+ get_action='list_identity_providers',
+ rel=build_resource_relation(resource_name='identity_providers'))
+
+ # Protocol CRUD operations
+
+ self._add_resource(
+ mapper, protocol_controller,
+ path=self._construct_url('identity_providers/{idp_id}/protocols/'
+ '{protocol_id}'),
+ get_action='get_protocol',
+ put_action='create_protocol',
+ patch_action='update_protocol',
+ delete_action='delete_protocol',
+ rel=build_resource_relation(
+ resource_name='identity_provider_protocol'),
+ path_vars={
+ 'idp_id': IDP_ID_PARAMETER_RELATION,
+ 'protocol_id': PROTOCOL_ID_PARAMETER_RELATION,
+ })
+ self._add_resource(
+ mapper, protocol_controller,
+ path=self._construct_url('identity_providers/{idp_id}/protocols'),
+ get_action='list_protocols',
+ rel=build_resource_relation(
+ resource_name='identity_provider_protocols'),
+ path_vars={
+ 'idp_id': IDP_ID_PARAMETER_RELATION,
+ })
+
+ # Mapping CRUD operations
+
+ self._add_resource(
+ mapper, mapping_controller,
+ path=self._construct_url('mappings/{mapping_id}'),
+ get_action='get_mapping',
+ put_action='create_mapping',
+ patch_action='update_mapping',
+ delete_action='delete_mapping',
+ rel=build_resource_relation(resource_name='mapping'),
+ path_vars={
+ 'mapping_id': build_parameter_relation(
+ parameter_name='mapping_id'),
+ })
+ self._add_resource(
+ mapper, mapping_controller,
+ path=self._construct_url('mappings'),
+ get_action='list_mappings',
+ rel=build_resource_relation(resource_name='mappings'))
+
+ # Service Providers CRUD operations
+
+ self._add_resource(
+ mapper, sp_controller,
+ path=self._construct_url('service_providers/{sp_id}'),
+ get_action='get_service_provider',
+ put_action='create_service_provider',
+ patch_action='update_service_provider',
+ delete_action='delete_service_provider',
+ rel=build_resource_relation(resource_name='service_provider'),
+ path_vars={
+ 'sp_id': SP_ID_PARAMETER_RELATION,
+ })
+
+ self._add_resource(
+ mapper, sp_controller,
+ path=self._construct_url('service_providers'),
+ get_action='list_service_providers',
+ rel=build_resource_relation(resource_name='service_providers'))
+
+ self._add_resource(
+ mapper, domain_controller,
+ path=self._construct_url('domains'),
+ new_path='/auth/domains',
+ get_action='list_domains_for_user',
+ rel=build_resource_relation(resource_name='domains'))
+ self._add_resource(
+ mapper, project_controller,
+ path=self._construct_url('projects'),
+ new_path='/auth/projects',
+ get_action='list_projects_for_user',
+ rel=build_resource_relation(resource_name='projects'))
+
+ # Auth operations
+ self._add_resource(
+ mapper, auth_controller,
+ path=self._construct_url('identity_providers/{idp_id}/'
+ 'protocols/{protocol_id}/auth'),
+ get_post_action='federated_authentication',
+ rel=build_resource_relation(
+ resource_name='identity_provider_protocol_auth'),
+ path_vars={
+ 'idp_id': IDP_ID_PARAMETER_RELATION,
+ 'protocol_id': PROTOCOL_ID_PARAMETER_RELATION,
+ })
+ self._add_resource(
+ mapper, auth_controller,
+ path='/auth' + self._construct_url('saml2'),
+ post_action='create_saml_assertion',
+ rel=build_resource_relation(resource_name='saml2'))
+ self._add_resource(
+ mapper, auth_controller,
+ path='/auth' + self._construct_url('saml2/ecp'),
+ post_action='create_ecp_assertion',
+ rel=build_resource_relation(resource_name='ecp'))
+ self._add_resource(
+ mapper, auth_controller,
+ path='/auth' + self._construct_url('websso/{protocol_id}'),
+ get_post_action='federated_sso_auth',
+ rel=build_resource_relation(resource_name='websso'),
+ path_vars={
+ 'protocol_id': PROTOCOL_ID_PARAMETER_RELATION,
+ })
+ self._add_resource(
+ mapper, auth_controller,
+ path='/auth' + self._construct_url(
+ 'identity_providers/{idp_id}/protocols/{protocol_id}/websso'),
+ get_post_action='federated_idp_specific_sso_auth',
+ rel=build_resource_relation(resource_name='identity_providers'),
+ path_vars={
+ 'idp_id': IDP_ID_PARAMETER_RELATION,
+ 'protocol_id': PROTOCOL_ID_PARAMETER_RELATION,
+ })
+
+ # Keystone-Identity-Provider metadata endpoint
+ self._add_resource(
+ mapper, saml_metadata_controller,
+ path=self._construct_url('saml2/metadata'),
+ get_action='get_metadata',
+ rel=build_resource_relation(resource_name='metadata'))
diff --git a/keystone/rules.json b/keystone/rules.json
new file mode 100644
index 0000000..0e406a6
--- /dev/null
+++ b/keystone/rules.json
@@ -0,0 +1,20 @@
+[
+ {
+ "local": [
+ {
+ "group_ids": "{1}",
+ "user": {
+ "name": "{0}"
+ }
+ }
+ ],
+ "remote": [
+ {
+ "type": "REMOTE_USER"
+ },
+ {
+ "type": "openstackGroupEntitlements"
+ }
+ ]
+ }
+]
diff --git a/keystone/run.sh b/keystone/run.sh
new file mode 100755
index 0000000..593b3d5
--- /dev/null
+++ b/keystone/run.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+# start nova compute service
+
+chown keystone: /etc/keystone/fernet-keys
+chmod 700 /etc/keystone/fernet-keys
+
+# Start apache
+a2enmod ssl
+apachectl -DFOREGROUND &
+
+chown _shibd: /etc/shibboleth/sp*.pem
+
+shibd -f -F &
+
+# If any process fails, kill the rest.
+# This insures the container stops and systemd will restart it.
+
+wait -n
+pkill -P $$
+
diff --git a/keystone/shibboleth2.xml b/keystone/shibboleth2.xml
new file mode 100644
index 0000000..908dfd1
--- /dev/null
+++ b/keystone/shibboleth2.xml
@@ -0,0 +1,114 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SAML2
+
+
+
+ SAML2 Local
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/keystone/sso_callback_template.html b/keystone/sso_callback_template.html
new file mode 100644
index 0000000..c6997dc
--- /dev/null
+++ b/keystone/sso_callback_template.html
@@ -0,0 +1,22 @@
+
+
+
+ Keystone WebSSO redirect
+
+
+
+
+
+
\ No newline at end of file
diff --git a/keystone/test.php b/keystone/test.php
new file mode 100644
index 0000000..28cd932
--- /dev/null
+++ b/keystone/test.php
@@ -0,0 +1,4 @@
+
+Shibboleth test
+
+