Openstack Keystone VOMS module¶
VOMS Introduction¶
The VOMS service can issue x509 proxies based on RFC 3820 (https://www.ietf.org/rfc/rfc3820.txt) by using the -rfc option in the comandline. Instead of using plain x509 certificates this proxy can be used to authenticate against a properly configured Keystone server.
User documentation¶
If you do not intend to install it, but rather authenticate against a VOMS service that is VOMS enabled, check the following link.
Usage¶
In order to get a token, you must post a JSON request in the body containing the following:
{
"auth": {
"voms": "true"
}
}
It is important to note here a difference between a VOMS backed keystone installation and a vanilla Keystone.
In a normal keystone installation there are two types of possible request: unscoped and scoped. The unscoped requests works without specifying a tenantName in the auth dictionary when making the request, whereas a scoped request needs of such field. The request above is an uscoped request, and the following is a scoped request:
{
"auth": {
"voms": "true",
"tenantNane": "dteam",
}
}
The particularity of the VOMS backend is that the user might not know to which tenant he is mapped to (because the mapping is made internally), thus the tenant name must be set to the VO name or the VOMS FQAN that he wants to use to authenticate.
Deploying a VOMS Authentication in Keystone¶
If you are a resource provider willing to deploy a VOMS-enabled keystone service, check the following documentation:
Keystone VOMS Overview¶
This VOMS authentication module assumes that Keystone is working behind an httpd server as a WSGI service with OpenSSL enabled. It only works with the V2 API of Keystone, since the V3 is still a work in progress.
This module asumes that Keystone has support for external authentication as implemented in the Pluggable Identity Authentication Handlers Blueprint.
SSL info is obtained from the request environment. The authentication module uses the voms library to check if the VOMS proxy is valid and if it is allowed in this server. The mapping between a VO, VO group and a keystone tenant is made in a configurable JSON file.
The mapped local tenant must exist in advance for a user to be authenticated. If the mapped tenant doest not exist, the authentication will fail. The same applies for the user, with the particularity that the backend is able to autocreate new users if the autocreate_users is enabled in the configuration file. This option is disabled by default, but if you want to let all the users from a VO to get into your infrastructre you should consider enabling it. Once a user has been granted access, you can manage it as you will do with any other user in keystone (i.e. disable/enable, grant/revoke roles, etc.).
In order to get an unscoped token, you must POST to /tokens, with the following JSON document document in the request:
{
"auth": {
"voms": "true"
}
}
This request should return you your an unscoped token. Next step is the discovery of your tenant (that may differ from the VO name). You have to use a GET request to /tenants passing the ID of your unscoped token (that you obtained before) in the X-Auth-Token header.
For further details, check the Test it! section.
Requirements¶
The Keystone VOMS authentication module requires some additional packages to be installed. Moreover, it requires that you run Keystone as a WSGI proccess behind an HTTP server (Apache will be used in this documentation, but any webserver could make it).
Required packages¶
EUgridPMA CA certificates¶
You must have EUgridPMA certificates installed on its standard location (/etc/grid-security/certificates) and the fetch-crl package properly working so as have the CRLs up to date:
wget -q -O - https://dist.eugridpma.info/distribution/igtf/current/GPG-KEY-EUGridPMA-RPM-3 | apt-key add -
echo "deb http://repository.egi.eu/sw/production/cas/1/current egi-igtf core" > /etc/apt/sources.list.d/egi-cas.list
sudo aptitude update
sudo aptitude install ca-policy-egi-core
Grab and install the fetch-crl package. Version 3 does not work properly, so get version 2.8.5 instead:
wget http://ftp.de.debian.org/debian/pool/main/f/fetch-crl/fetch-crl_2.8.5-2_all.deb
sudo dpkg -i fetch-crl_2.8.5-2_all.deb
sudo fetch-crl
VOMS libraries¶
You must install the VOMS libraries. Please install the libvomsapi1 package in Debian/Ubuntu or voms package in RedHat/Fedora/ScientificLinux/etc.
Apache Installation and Configuration¶
You need keystone working under Apache WSGI with mod_ssl enabled. To do so, install the packages, and enable the relevant modules:
sudo aptitude install apache2 libapache2-mod-wsgi
sudo a2enmod ssl
Then configure your Apache server like this (we assume that you have the CA certificates installed in the default location, otherwise you should adapt it to your needs). Either enable the default-ssl site (a2ensite default-ssl) and modify its configuration file (normally in /etc/apache2/sites-enabled/default-ssl) or create a new configuration file for your keystone installation /etc/apache2/sites-enabled/keystone:
WSGIDaemonProcess keystone user=keystone group=nogroup processes=3 threads=10
Listen 5000
<VirtualHost _default_:5000>
LogLevel warn
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/ssl_access.log combined
SSLEngine on
SSLCertificateFile /etc/ssl/certs/ssl.cert
SSLCertificateKeyFile /etc/ssl/private/ssl.key
SSLCACertificatePath /etc/grid-security/certificates
SSLCARevocationPath /etc/grid-security/certificates
SSLVerifyClient optional
SSLVerifyDepth 10
SSLProtocol all -SSLv2
SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW
SSLOptions +StdEnvVars +ExportCertData
WSGIScriptAlias / /usr/lib/cgi-bin/keystone/main
WSGIProcessGroup keystone
</VirtualHost>
Listen 35357
<VirtualHost _default_:35357>
LogLevel warn
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/ssl_access.log combined
SSLEngine on
SSLCertificateFile /etc/ssl/certs/hostcert.pem
SSLCertificateKeyFile /etc/ssl/private/hostkey.pem
SSLCACertificatePath /etc/grid-security/certificates
SSLCARevocationPath /etc/grid-security/certificates
SSLVerifyClient optional
SSLVerifyDepth 10
SSLProtocol all -SSLv2
SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW
SSLOptions +StdEnvVars +ExportCertData
WSGIScriptAlias / /usr/lib/cgi-bin/keystone/admin
WSGIProcessGroup keystone
</VirtualHost>
To run keystone as a WSGI app you should create a WSGI script as the one included in the Github Keystone repository. Copy this script to /usr/lib/cgi-bin/keystone/keystone.py and create the following links:
sudo mkdir -p /usr/lib/cgi-bin/keystone
sudo cp httpd/keystone.py /usr/lib/cgi-bin/keystone/keystone.py
sudo ln /usr/lib/cgi-bin/keystone/keystone.py /usr/lib/cgi-bin/keystone/main
sudo ln /usr/lib/cgi-bin/keystone/keystone.py /usr/lib/cgi-bin/keystone/admin
sudo service apache2 restart
You should adjust the keystone.py file so that the configuration file points to your keystone configuration file if it is not in the default location (/etc/keystone/keystone.conf).
Also, do not forget to set the variable OPENSSL_ALLOW_PROXY_CERTS to 1 in your Apache environment (/etc/apache2/envvars in Debian/Ubuntu) so that X.509 proxy certificates are accepted by OpenSSL.
With the above configuration, and assuming that the Keystone host is keystone.example.org the endpoints will be as follow:
- https://keystone.example.org:5000/ will be public and private endpoints, thus the Keystone URL will be https://keystone.example.org:5000/v2.0
- https://keystone.example.org:35357/ will be administration endpoint, thus the Keystone URL will be https://keystone.example.org:35357/v2.0
DB Backend¶
You should take into account that the default SQL backend used by keystone is SQLite, which does not support multithreading. You should switch to any other backend, such as MySQL.
SQL Token driver¶
Since you are running Keystone as a WSGI service, you have to ensure that you are using the SQL backend for the token storage, so as to make it possible to share them between the diferent WSGI processes. Check that the keystone conf file /etc/keystone/keystone.conf contains a [token] section as follows:
[token]
driver = keystone.token.backends.sql.Token
Catalog¶
Your have to adjust your keystone catalog so that the identity backend points to to the correct URLS as explained above. With the above configuration, these URLs will be:
- public URL: https://keystone.example.org:5000/v2.0
- admin URL: https://keystone.example.org:35357/v2.0
- internal URL: https://keystone.example.org:5000/v2.0
If you are using the SQL backend for storing your catalog, you should adjust it manually to reflect the new endpoints.
PKI Tokens¶
In order for the PKI tokens to work, you have to ensure that the keystone WSGI processes, that will run as the user keystone in the example above, have access to the configuration files. If you get this error:
[error] ERROR:root:Command 'openssl' returned non-zero exit status 3
[error] Traceback (most recent call last):
[error] File "/usr/lib/python2.7/dist-packages/keystone/common/wsgi.py", line 229, in __call__
[error] result = method(context, **params)
[error] File "/usr/lib/python2.7/dist-packages/keystone/token/controllers.py", line 151, in authenticate
[error] CONF.signing.keyfile)
[error] File "/usr/lib/python2.7/dist-packages/keystone/common/cms.py", line 140, in cms_sign_token
[error] output = cms_sign_text(text, signing_cert_file_name, signing_key_file_name)
[error] File "/usr/lib/python2.7/dist-packages/keystone/common/cms.py", line 135, in cms_sign_text
[error] raise subprocess.CalledProcessError(retcode, "openssl")
[error] CalledProcessError: Command 'openssl' returned non-zero exit status 3
This may be that your keystone process cannot access the following file: /etc/keystone/ssl/private/signing_key.pem so please ensure that the keystone user can access that file.
Installation¶
This module assumes that keystone is at least running the Grizzly version, since it needs some latest additions that are not available in any prior release. You can fetch the ubuntu packages and install it from the Grizzly Trunk testing PPA.
Install the Keystone VOMS module¶
Install from the Python Package Index¶
You can install it directly from PyPI:
pip install keystone_voms
Install from PPA¶
You can install the latest version from a private PPA:
sudo add-apt-repository ppa:aloga/keystone-voms
sudo aptitude update
sudo aptitude install python-keystone-voms
Install from source¶
With a running Grizzly installation, simply install this egg. In the upper-level directory run python setup.py install:
git clone git://github.com/IFCA/keystone-voms.git -b stable/grizzly
cd keystone-voms
sudo python setup.py install
Enable the Keystone VOMS module¶
The authentication module is a WSGI middleware that performs the authentication and passes the authenticated user down to keystone. Add the VOMS filter to your configuration file /etc/keystone/keystone.conf
[filter:voms]
paste.filter_factory = keystone_voms:VomsAuthNMiddleware.factory
Then add this filter to the public_api pipeline:
[pipeline:public_api]
pipeline = sizelimit stats_monitoring url_normalize token_auth admin_token_auth xml_body json_body voms debug ec2_extension user_crud_extension public_service
Note that you may have a different pipeline. You don’t need to replace your pipeline with the above, but just add the voms filter after the json_body entry.
Configuration¶
Allowed VOs¶
For each allowed VO, you need a subdirectory in /etc/grid-security/vomsdir/ that contains the .lsc files of all truted VOMS servers for the given VO. The LSC files must be named as the fully qualified host name of the VOMS server with an .lsc extension, and they contain:
- First line: subject DN of the VOMS server host certificate.
- Second line: subject DN of the CA that issued the VOMS server host certificate.
So, for example, for the dteam VO the first should be:
$ cat /etc/grid-security/vomsdir/dteam/voms.hellasgrid.gr.lsc
/C=GR/O=HellasGrid/OU=hellasgrid.gr/CN=voms.hellasgrid.gr
/C=GR/O=HellasGrid/OU=Certification Authorities/CN=HellasGrid CA 2006
The dteam VO has two VOMS servers (see link above) so another file for the second server needs to be present as well:
$ cat /etc/grid-security/vomsdir/dteam/voms2.hellasgrid.gr.lsc
/C=GR/O=HellasGrid/OU=hellasgrid.gr/CN=voms2.hellasgrid.gr
/C=GR/O=HellasGrid/OU=Certification Authorities/CN=HellasGrid CA 2006
For more details, please check the following page How to configure VOMS LSC files.
VO to local tenant mapping¶
The VO and VO group mapping to the local tenants is made in the JSON file /etc/keystone/voms.json. It is based on the VO name and VOMS proxy fqan:
{
"voname": {
"tenant": "local_tenant"
}
}
For example for the dteam VO, it could be configured as:
{
"dteam": {
"tenant": "dteam"
},
"/dteam/NGI_IBERGRID": {
"tenant": "dteam_ibergrid"
}
}
If there are no matching FQANS but there is a VO name definition, the user will authenticate, therefore, a user making the following request:
{
"auth": {
"voms": "true",
"tenantNane": "/dteam/NGI_IBERGRID",
}
}
against the following configuration:
{
"dteam": {
"tenant": "dteam"
}
}
will be sucessfully authenticated, because no FQAN matched, but the VO did.
VOMS configuration options¶
There are several new options in /etc/keystone/keystone.conf that are used to configure the VOMS identity behaviour. The default values should be OK for most installations. These are under the [voms] section:
[voms]
vomsdir_path = /etc/grid-security/vomsdir
ca_path = /etc/grid-security/certificates
voms_policy = /etc/keystone/voms.json
vomsapi_lib = libvomsapi.so.1
autocreate_users = False
- vomsdir_path: Path storing the .lsc files.
- ca_path: Path where the CAs and CRLs are stored.
- voms_policy: JSON file containing the VO/tenant/role mapping.
- vomsapi_lib: Path to the voms library to use.
- autocreate_users: Whether we should create the users for the trusted VOs on the fly.
Test it!¶
Once you have everything configured you can test it requesting a token using a valid VOMS proxy.
First get a valid VOMS proxy:
$ voms-proxy-init -voms <VOMS> -rfc
Then, get a unscoped token:
$ curl --cert $X509_USER_PROXY -d '{"auth":{"voms": true}}' \
-H "Content-type: application/json" https://<keystone_host>/v2.0/tokens
This will give you something like:
{
"access": {
"token": {
"expires": "2011-08-10T17:45:22.838440",
"id": "0eed0ced-4667-4221-a0b2-24c91f242b0b"
}
}
}
Use the token ID that you obtained, to get a list of the tenants that you are allowed to access:
$ curl -H "X-Auth-Token:0eed0ced-4667-4221-a0b2-24c91f242b0b" \
http://localhost:35357/v2.0/tenants
If this is sucessful, you should get something like:
{
"tenants_links": [],
"tenants": [
{
"description": "Some Tenant",
"enabled": true,
"id": "999f045cb1ff4684a15ebb334af61461",
"name": "TenantName"
}
]
}
Identify the tenant, and request a scoped token:
$ curl --cert $X509_USER_PROXY \
-d '{"auth":{"voms": true, "tenantName": "TenantName"}}' \
-H "Content-type: application/json" https://<keystone_host>/v2.0/tokens
Finally, you should obtain your token:
{
"access": {
(...)
},
"serviceCatalog": [
(...)
],
"token": {
"expires": "2013-07-30T12:16:23Z",
"id": "ccb739df861e76a5a9039d21ec040a91",
"issued_at": "2013-07-29T12:16:23.625426",
"tenant": {
"description": "Some Tenant",
"enabled": true,
"id": "999f045cb1ff4684a15ebb334af61461",
"name": "TenantName"
}
},
"user": {
(...)
}
}
}
Troubleshooting¶
Apache complains about issuer of certificate¶
You get something like:
Certificate Verification: Error (20): unable to get local issuer certificate
You probably missed to set the OPENSSL_ALLOW_PROXY_CERTS variable on the Apache environment
Error 14: Signature error¶
You have to check double check that the vomsdir_path and ca_path configuration options (that default to /etc/grid-security/vomsdir and /etc/grid-security/certificates respectively) point to the correct path. Also ensure that the .lsc files have the right contents and that the CLRs are up to date.