Skip to content

Instantly share code, notes, and snippets.

@01000101
Last active May 13, 2018 02:06
Show Gist options
  • Select an option

  • Save 01000101/f73b7eb8a1a25c9a50c0dd9a411d5b06 to your computer and use it in GitHub Desktop.

Select an option

Save 01000101/f73b7eb8a1a25c9a50c0dd9a411d5b06 to your computer and use it in GitHub Desktop.
Example script for testing OpenStack Keystone SAML 2.0 ECP authentication with Python libraries
'''
Example script for testing OpenStack Keystone SAML 2.0 ECP authentication
This script expects the following OS environment variables to be defined:
OS_AUTH_URL
OS_USERNAME
OS_PASSWORD
OS_PROJECT_ID
OS_PROJECT_NAME
OS_PROTOCOL
OS_IDENTITY_PROVIDER
OS_IDENTITY_PROVIDER_URL
'''
__author__ = "Joshua Cornutt"
__license__ = "ISC"
__version__ = "1.0.0"
__maintainer__ = "Joshua Cornutt"
__email__ = "joshua@joscor.com"
__status__ = "Development"
import logging
import sys
from os import environ
# Keystone
from keystoneauth1 import session
from keystoneauth1.identity import v3
from keystoneclient.contrib.auth.v3.saml2 import Saml2UnscopedToken
# OpenStack clients
# from keystoneclient.v3 import client as keystone_client
from novaclient import client as nova_client
from neutronclient.v2_0 import client as neutron_client
DEBUG = False
# Logging to STDOUT
logging.basicConfig(
level=logging.DEBUG if DEBUG else logging.INFO,
format='{%(filename)s:%(lineno)d} %(levelname)s - %(message)s',
handlers=[logging.StreamHandler(sys.stdout)])
def get_unscoped_token():
'''Requests an unscoped Keystone authentication token'''
# Prepare the SAML 2.0 ECP connections
auth = Saml2UnscopedToken(
# OpenStack Keystone v3 authentication endpoint
environ['OS_AUTH_URL'],
# OpenStack Identity Provider ID
# Test using `openstack identity provider show <name>`
environ['OS_IDENTITY_PROVIDER'],
# SAML 2.0 Assertion Consumer Service (ACS) URL
# SSP example: https://my-idp-fqdn/saml2/idp/SSOService.php
environ['OS_IDENTITY_PROVIDER_URL'],
environ['OS_USERNAME'],
environ['OS_PASSWORD'])
# This overrides the default "saml2" protocol to match our named protocol
# Most documentation / guides use the name 'mapped' here
auth.PROTOCOL = environ['OS_PROTOCOL']
# Get an unscoped token (this initiates SAML 2.0 ECP flow)
return auth.get_auth_ref(session.Session()).auth_token
def get_scoped_token(token_unscoped):
'''Requests a project-scoped Keystone authentication token'''
return v3.Token(
auth_url=environ['OS_AUTH_URL'],
token=token_unscoped,
project_id=environ['OS_PROJECT_ID'],
project_name=environ['OS_PROJECT_NAME'],
unscoped=False)
def main():
'''Script entry point'''
# Request an unscoped token (via SAML 2.0 ECP)
token_unscoped = get_unscoped_token()
# Exchange the unscoped token for a project-scoped token
token_scoped = get_scoped_token(token_unscoped)
# Init a session with the scoped token
sess = session.Session(auth=token_scoped)
# Init the various OpenStack clients
# keystone = keystone_client.Client(
# session=sess, debug=DEBUG, version=(3,), endpoint_type='public')
nova = nova_client.Client(
2, session=sess, endpoint_type='public')
neutron = neutron_client.Client(
session=sess, endpoint_type='public')
# Use the OpenStack clients
servers = nova.servers.list()
logging.info('[Nova] Servers: %s' % servers)
networks = neutron.list_networks()
logging.info('[Neutron] Networks: %s' % networks)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment