====== AAI integrations in Openstack Mitaka ====== Authors: Paolo Andreetto (INFN Padova) ==== Requirements ==== * CentOS Linux release 7.1 * Openstack from "Kilo" to "Mikata" release ==== Shibboleth installation ==== === Installing repositories === wget -O /etc/yum.repos.d/EGI-trustanchors.repo http://repository.egi.eu/sw/production/cas/1/current/repo-files/EGI-trustanchors.repo wget -O /etc/yum.repos.d/shibboleth.repo http://download.opensuse.org/repositories/security://shibboleth/CentOS_7/security:shibboleth.repo === Installing required modules === yum -y install ca-policy-egi-core fetch-crl shibboleth httpd mod_ssl === Starting cron service "fetch-crl-cron" === systemctl enable fetch-crl-cron && systemctl start fetch-crl-cron === Installing certificate - key and setting their permissions === Deploy the service certificate file in ///etc/shibboleth/sp-cert.pem// and the related service key file in ///etc/shibboleth/sp-key.pem//. Change the ownership and permissions for those files: chmod 400 /etc/shibboleth/sp-key.pem chmod 600 /etc/shibboleth/sp-cert.pem chown shibd.shibd /etc/shibboleth/sp-key.pem chown shibd.shibd /etc/shibboleth/sp-cert.pem ==== Shibboleth service’s configuration ==== === Downloading the attribute-map file === wget -O /etc/shibboleth/attribute-map.xml http://wiki.infn.it/_media/cn/ccr/aai/howto/attribute-map.xml === Configuring the shibboleth daemon === The file ///etc/shibboleth/shibboleth2.xml// must contain the following definitions: SAML2 SAML1 SAML2 Local /etc/shibboleth/sp-key.pem /etc/shibboleth/sp-cert.pem /etc/grid-security/certificates/INFN-CA-2015.pem /etc/grid-security/certificates/49f18420.r0 === Verifying the configuration procedure === Use the command: LD_LIBRARY_PATH=/opt/shibboleth/lib64 runuser -s /bin/bash -c 'shibd -t' -- shibd (see note below) === Starting the shibboleth daemon === systemctl enable shibd && systemctl start shibd ^ Troubleshooting ^ ^ | | if the command above reports the error: CRIT Shibboleth.Application : error building CredentialResolver: Unable to load CRL(s) from file then it is necessary to run the fetch-crl command manually: cd /etc/grid-security/certificates && fetch-crl -v | | | if the command above reports the errors: CRIT XMLTooling.Config : libcurl lacks OpenSSL-specific options, this will greatly limit functionality ERROR XMLTooling.libcurl.InputStream : error while fetching https://www.idem.garr.it/docs/conf/idem-metadata.xml: (59) Unknown cipher in list ERROR XMLTooling.libcurl.InputStream : on Red Hat 6+, make sure libcurl used is built with OpenSSL ERROR XMLTooling.ParserPool : fatal error on line 0, column 0, message: internal error in NetAccessor ERROR OpenSAML.MetadataProvider.XML : error while loading resource (https://www.idem.garr.it/docs/conf/idem-metadata.xml): XML error(s) during parsing ERROR OpenSAML.MetadataProvider.XML : metadata instance was invalid at time of acquisition CRIT OpenSAML.Metadata.Chaining : failure initializing MetadataProvider: Metadata instance was invalid at time of acquisition. even if the message is marked as critical, those errors can be ignored. On many RedHat/Fedora installation a different version of libcurl is required, the library is located in ///opt/shibboleth/lib64//. The shibboleth daemon calls the configuration script ///etc/sysconfig/shibd// in order to overwrite the system library. In case it is possible to remove the error running the command LD_LIBRARY_PATH=/opt/shibboleth/lib64 shibd -t | ==== HTTP service’s configuration ==== === Configuration of the module "apache-ssl" === if the module isn't already configured, define the following attributes: SSLCertificateFile /etc/grid-security/hostcert.pem SSLCertificateKeyFile /etc/grid-security/hostkey.pem in the configuration file for SSL apache plugin. In general the file is ''/etc/httpd/conf.d/ssl.conf''. If the dashboard has been deployed using packstack the file is ''/etc/httpd/conf.d/15-horizon_ssl_vhost.conf'' === Configuration of the service “shibbolet” for the Openstack-Dashboard === In the file ''/etc/httpd/conf.d/shib.conf'' insert the following section: AuthType shibboleth ShibRequestSetting requireSession 1 require shib-session === Configuration file of the Dashboard === Add the following instructions, if not already present, in the file ///etc/httpd/conf.d/openstack-dashboard.conf// (or ///etc/httpd/conf.d/15-horizon_ssl_vhost.conf// if packstack have been used): WSGIScriptAlias /dashboard-shib /usr/share/openstack-dashboard/openstack_dashboard/wsgi/django.wsgi In order to avoid [[https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPApacheConfig|security holes]] it is necessary to activate the [[http://httpd.apache.org/docs/2.4/mod/core.html#usecanonicalname|UseCanonicalName]] option for any virtual host or location protected by shibboleth ServerName https://cloud-areapd.pd.infn.it UseCanonicalName On === Restarting of the service ''httpd'' === systemctl restart httpd ==== Installation of the AAI integration ==== === Download the repository containing the integration packages === Repository for Kilo: wget -O /etc/yum.repos.d/openstack-security-integrations.repo http://igi-01.pd.infn.it/mrepo/CAP/openstack-security-integrations_centos7_kilo.repo Repository for Mitaka: wget -O /etc/yum.repos.d/openstack-security-integrations.repo http://igi-01.pd.infn.it/mrepo/CAP/openstack-security-integrations_centos7_mitaka.repo === Installation of the keystone plugin === yum -y install keystone-skey-auth === Installation of the dashboard wrappers === For the project Cloud Area Padovana: yum -y install openstack-auth-cap For the project Cloud Veneto: yum -y install openstack-auth-cedc === Generating the secret key === The secret key is the shared secret between Horizon and Keystone. It must be deployed by hand on both side and it can be generated with the following command: python -c "from horizon.utils import secret_key; print secret_key.generate_key(32)" The generated key must be specified, between double quotes, as the parameter "KEYSTONE_SECRET_KEY" in the file ///etc/openstack-dashboard/local_settings//: KEYSTONE_SECRET_KEY = "PeYjxbEzJZ4ZLj1AJCBvUar5fSfJOAkq" === Setting up the database === In the file ///etc/openstack-dashboard/local_settings// define the parameter for the database according to the [[https://docs.djangoproject.com/en/1.4/ref/databases/|Django requirements]]. This snippet is an example for a mysql based installation: DATABASES = { 'default': { 'ENGINE' : 'django.db.backends.mysql', 'NAME' : 'horizon_aai', 'USER' : 'horizonaai', 'PASSWORD' : '*********', 'HOST' : 'cloud-areapd.pd.infn.it', 'PORT' : '3306' } } The database must be created manually and all permissions granted before performing any further action: create database horizon_aai; grant all on horizon_aai.* to 'horizonaai'@'cloud-areapd.pd.infn.it' identified by '*********'; grant all on horizon_aai.* to 'horizonaai'@'localhost' identified by '*********'; The database can be populated with the command: runuser -s /bin/bash -c 'python /usr/share/openstack-dashboard/manage.py migrate' -- apache The creation of an admin user in the database is not required. === Setting up the notication system === The notification system must be configured according to [[https://docs.djangoproject.com/en/1.4/topics/email/|Django requirements]]. The file to be modified is ///etc/openstack-dashboard/local_settings//. Several notifications are sent directly to site administrators, their addresses must be defined in variable **MANAGERS** This snippet is an example of configuration for accessing a protected SMTP server: EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' EMAIL_HOST = '****.pd.infn.it' EMAIL_PORT = 587 EMAIL_HOST_USER = '******' EMAIL_HOST_PASSWORD = '******' SERVER_EMAIL = 'cloud@lists.pd.infn.it' MANAGERS = (('Cloud Support', 'cloud-support@lists.pd.infn.it'),) === Install notification templates === In the file ///etc/openstack-dashboard/local_settings// the following definition must be defined: NOTIFICATION_TEMPLATE_DIR = '/etc/openstack-auth-shib/notifications' === Other changes === It is necessary to force the version 3 for keystone API. In the file ///etc/openstack-dashboard/local_settings// the following definitions must be present OPENSTACK_API_VERSIONS = { "identity": 3 } OPENSTACK_HOST = "cloud-areapd.pd.infn.it" # Keystone accessible in plaintext #OPENSTACK_KEYSTONE_URL = "http://%s:5000/v3" % OPENSTACK_HOST # Keystone protected with SSL/TLS OPENSTACK_KEYSTONE_URL = "https://%s:5000/v3" % OPENSTACK_HOST OPENSTACK_SSL_CACERT = "/etc/grid-security/certificates/INFN-CA-2006.pem" In the configuration file ///etc/openstack-dashboard/local_settings// the URL for help must be defined. For the project Cloud Area Padovana: HORIZON_CONFIG = { #other definitions 'help_url': "http://www.pd.infn.it/cloud/Users_Guide/html-desktop/", } For the project Cloud Veneto: HORIZON_CONFIG = { #other definitions 'help_url': "https://cloud.cedc.csia.unipd.it/User_Guide/index.html", } Since the configuration file of the dashboard contains sensitive parameters it is necessary to change its permissions: chmod 640 /etc/openstack-dashboard/local_settings && chown root.apache /etc/openstack-dashboard/local_settings === Restarting of the service "httpd" === systemctl restart httpd ^ Troubleshooting ^ ^ | | If the log in the file ///var/log/horizon/horizon.log// reports the error: ''You have offline compression enabled but key "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" is missing from offline manifest. You may need to run "python manage.py compress"'' it is necessary to run the stylesheet compression utility manually: yum -y install python-lesscpy cd /usr/share/openstack-dashboard/ && python manage.py compress systemctl restart httpd | ^ Tips ^ ^ | | The log for Horizon can be enabled defining a new handler, a new formatter and a new logger in the LOGGING table of the file ///etc/openstack-dashboard/local_settings//:LOGGING = { 'formatters': { 'verbose': { 'format': '%(asctime)s %(process)d %(levelname)s %(name)s ' '%(message)s' }, }, # other definitions 'handlers': { # other definitions 'file': { 'level': 'DEBUG', 'class': 'logging.FileHandler', 'filename': '/var/log/horizon/horizon.log', 'formatter': 'verbose', }, } 'loggers': { # other definitions 'openstack_auth_shib': { 'handlers': ['file'], 'level': 'DEBUG', 'propagate': False, }, } then the handler //file// can be used in the loggers such as 'horizon': { 'handlers': ['file'], 'level': 'DEBUG', 'propagate': False, }. For further details about logging see the [[https://docs.python.org/2.7/library/logging.html| python documentation]] | | | If you're configuring SSL support for connections between Horizon and Keystone don't use the IP address for OPENSTACK_HOST, use the fully qualified name as reported in the host certificate | | | It's strongly recommanded to use memcached for storing session attributes, instead of signed cookies. Login cannot be correctly performed if too many data are stored in a cookie. The cache definition is specified into the file ///etc/openstack-dashboard/local_settings//:SESSION_ENGINE = 'django.contrib.sessions.backends.cache' CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', 'LOCATION': '127.0.0.1:11211', } } The memcache daemon must be running systemctl status memcached For further details refer to the [[https://docs.djangoproject.com/en/1.4/topics/http/sessions/|django session guide]] | | | It is possible to restore manually the standard Openstack logos with the following commands: cp /usr/share/openstack-dashboard/openstack_dashboard/static/dashboard/img/logo-orig.png \ /usr/share/openstack-dashboard/openstack_dashboard/static/dashboard/img/logo.png cp /usr/share/openstack-dashboard/openstack_dashboard/static/dashboard/img/logo-splash-orig.png \ /usr/share/openstack-dashboard/openstack_dashboard/static/dashboard/img/logo-splash.png cp /usr/share/openstack-dashboard/openstack_dashboard/static/dashboard/img/favicon-orig.ico \ /usr/share/openstack-dashboard/openstack_dashboard/static/dashboard/img/favicon.ico | | | If necessary the service metadata (service description, information URLs, etc.) can be customized editing the file ///etc/openstack-auth-shib/idem-template-metadata.xml// | ==== Configuration of the Keystone service ==== === Configuration of the authentication plugin "skey" === Change the "auth" section in the file ///etc/keystone/keystone.conf// in the following way: [auth] methods=sKey,password,token password=keystone.auth.plugins.password.Password token=keystone.auth.plugins.token.Token sKey = keystone_skey_auth.skey.SecretKeyAuth Create a new section in the file ///etc/keystone/keystone.conf//: [skey] secret_key = "PeYjxbEzJZ4ZLj1AJCBvUar5fSfJOAkq" The secret key defined in the keystone configuration file is the same key specified by the parameter "KEYSTONE_SECRET_KEY" in the file ///etc/openstack-dashboard/local_settings// Configure fernet tokens support in the service with the following definitions in ///etc/keystone/keystone.conf//: [token] provider = keystone.token.providers.fernet.Provider [fernet_tokens] key_repository = /etc/keystone/fernet-keys Create the fernet key repository: mkdir -p /etc/keystone/fernet-keys && chown keystone.keystone /etc/keystone/fernet-keys && chmod 750 /etc/keystone/fernet-keys keystone-manage fernet_setup --keystone-user keystone --keystone-group keystone === Restarting the keystone service === If the keystone service is running in stand-alone mode: systemctl restart openstack-keystone If the keystone service is running as a WSGI application in Apache: systemctl restart httpd ==== Configuration of the cron scripts ==== Create the configuration file ///etc/openstack-auth-shib/actions.conf// with the following definitions: USERNAME=admin TENANTNAME=admin PASSWD=**** AUTHURL=https://cloud-areapd.pd.infn.it:35357/v3/ CAFILE=/etc/grid-security/certificates/INFN-CA-2015.pem NOTIFICATION_PLAN=5,10,20 The configuration file must be readable only by root: chmod 600 /etc/openstack-auth-shib/actions.conf Create the cron file ///etc/cron.d/openstack-auth-shib-cron// with the following content: 5 0 * * * root python /usr/share/openstack-dashboard/manage.py checkexpiration --config /etc/openstack-auth-shib/actions.conf --logconf /etc/openstack-auth-shib/logging.conf 2>/dev/null 10 0 * * * root python /usr/share/openstack-dashboard/manage.py notifyexpiration --config /etc/openstack-auth-shib/actions.conf --logconf /etc/openstack-auth-shib/logging.conf 2>/dev/null 0 9 * * 1 root python /usr/share/openstack-dashboard/manage.py pendingsubscr --config /etc/openstack-auth-shib/actions.conf --logconf /etc/openstack-auth-shib/logging.conf 2>/dev/null ^ Tips ^ ^ | | Since the script accesses the database, for installations on multiple nodes which share the same backend, it's recommanded to have different crontab configurations for different nodes | | | The configuration file for the logging system of all the scripts is ///etc/openstack-auth-shib/logging.conf// | ==== The guest project ==== The guest project can be created by the cloud administrator directly with the dashboard. From the "Projects" page create a new project and set the "Guest Project" flag. Only one guest project can be created. ==== Setup for INFN-AAI testing ==== In the file ///etc/shibboleth/shibboleth2.xml// a new metadata provider in the chain must be defined: and the entityID must point to the corresponding URL SAML2 SAML1 ==== Setup for UniPD-IdP (production) ==== In the file ///etc/httpd/conf.d/shib.conf// a new location must be added: AuthType shibboleth ShibRequestSetting requireSession 1 ShibRequestSetting applicationId default ShibRequestSetting target https://cloud-areapd.pd.infn.it/dashboard-unipd/auth/login/ ShibRequestSetting entityID https://shibidp.cca.unipd.it/idp/shibboleth require shib-session A new alias must be created in the file ///etc/httpd/conf.d/openstack-dashboard.conf// (or ///etc/httpd/conf.d/15-horizon_ssl_vhost.conf// if packstack have been used): WSGIScriptAlias /dashboard-unipd /usr/share/openstack-dashboard/openstack_dashboard/wsgi/django.wsgi In the file ///etc/openstack-dashboard/local_settings// the following parameter must be defined: HORIZON_CONFIG['identity_providers'] = [ {'id' : 'unipd', 'type' : 'production', 'path' : '/dashboard-unipd/auth/login/', 'description' : 'UniPD IdP', 'logo' : '/dashboard/static/dashboard/img/logoUniPD.png'} ] Restart the daemons: systemctl restart shibd systemctl restart httpd ==== Setup for IDEM (testing) ==== The public key must be downloaded from IDEM site: wget https://www.idem.garr.it/documenti/doc_download/321-idem-metadata-signer-2019 -O /etc/shibboleth/idem_signer_2019.pem chmod 444 /etc/shibboleth/idem_signer_2019.pem In the file ///etc/shibboleth/shibboleth2.xml// the following definitions must be specified: SAML2 SAML1 In the file ///etc/httpd/conf.d/shib.conf// a new location must be added: AuthType shibboleth ShibRequestSetting requireSession 1 require shib-session A new alias must be created in the file ///etc/httpd/conf.d/openstack-dashboard.conf// (or ///etc/httpd/conf.d/15-horizon_ssl_vhost.conf// if packstack have been used): WSGIScriptAlias /dashboard-idem /usr/share/openstack-dashboard/openstack_dashboard/wsgi/django.wsgi In the file ///etc/openstack-dashboard/local_settings// the following parameter must be defined: HORIZON_CONFIG['identity_providers'] = [ {'id' : 'idem', 'type' : 'experimental', 'path' : '/dashboard-idem/auth/login/', 'description' : 'IDEM federation', 'logo' : '/dashboard/static/dashboard/img/logoIDEM.png'} ] ==== References ==== * INFN AAI Support: aai-support@lists.infn.it * UniPD SSO Support : supporto.sso@unipd.it