Adding support for token based authentication

Change-Id: Ibc73e46c22f1c63b2f80ff850767bdbfed3355a3
Implements: blueprint add-authentication-token-support
This commit is contained in:
John Vrbanac 2015-04-20 13:29:23 -05:00
parent bc5a607e6d
commit ddb94b51ca
5 changed files with 125 additions and 7 deletions

View File

@ -23,6 +23,7 @@ from cliff import app
from cliff import commandmanager
from keystoneclient.auth import identity
from keystoneclient import session
import six
from barbicanclient import client
from barbicanclient import version
@ -110,6 +111,10 @@ class Barbican(app.App):
metavar='<auth-project-domain-name>',
default=client.env('OS_PROJECT_DOMAIN_NAME'),
help='Defaults to env[OS_PROJECT_DOMAIN_NAME].')
parser.add_argument('--os-auth-token',
metavar='<auth-token>',
default=client.env('OS_AUTH_TOKEN'),
help='Defaults to env[OS_AUTH_TOKEN].')
parser.add_argument('--endpoint', '-E',
metavar='<barbican-url>',
default=client.env('BARBICAN_ENDPOINT'),
@ -123,6 +128,63 @@ class Barbican(app.App):
raise Exception("ERROR: argument --os-auth-url/-A: not allowed "
"with argument --no-auth/-N")
def _check_auth_arguments(self, args, api_version=None, raise_exc=False):
"""Verifies that we have the correct arguments for authentication
Supported Keystone v3 combinations:
- Project Id
- Project Name + Project Domain Name
- Project Name + Project Domain Id
Support Keystone v2 combinations:
- Tenant Id
- Tenant Name
"""
successful = True
v3_arg_combinations = [
args.os_project_id,
args.os_project_name and args.os_project_domain_name,
args.os_project_name and args.os_project_domain_id
]
v2_arg_combinations = [args.os_tenant_id, args.os_tenant_name]
# Keystone V3
if not api_version or api_version == _DEFAULT_IDENTITY_API_VERSION:
if not any(v3_arg_combinations):
msg = ('ERROR: please specify the following --os-project-id or'
'--os-project-name and --os-project-domain-name or '
'--os-project-name and --os-project-domain-id')
successful = False
# Keystone V2
else:
if not any(v2_arg_combinations):
msg = ('ERROR: please specify --os-tenant-id or'
'--os-tenant-name')
successful = False
if not successful and raise_exc:
raise Exception(msg)
return successful
def _build_kwargs_based_on_version(self, args, api_version=None):
if not api_version or api_version == _DEFAULT_IDENTITY_API_VERSION:
kwargs = {
'project_id': args.os_project_id,
'project_name': args.os_project_name,
'user_domain_id': args.os_user_domain_id,
'user_domain_name': args.os_user_domain_name,
'project_domain_id': args.os_project_id,
'project_domain_name': args.os_project_name
}
else:
kwargs = {
'tenant_name': args.os_tenant_name,
'tenant_id': args.os_tenant_id
}
# Return a dictionary with only the populated (not None) values
return dict((k, v) for (k, v) in six.iteritems(kwargs) if v)
def initialize_app(self, argv):
"""Initializes the application.
Checks if the minimal parameters are provided and creates the client
@ -132,6 +194,11 @@ class Barbican(app.App):
args = self.options
self._assert_no_auth_and_auth_url_mutually_exclusive(args.no_auth,
args.os_auth_url)
# Aliasing as we use this a number of times
api_version = args.os_identity_api_version
# TODO(jmvrbanac): Split out these conditionals into discrete functions
if args.no_auth:
if not all([args.endpoint, args.os_tenant_id or
args.os_project_id]):
@ -142,6 +209,31 @@ class Barbican(app.App):
project_id=args.os_tenant_id or
args.os_project_id,
verify=not args.insecure)
# Token-based authentication
elif args.os_auth_token:
if not args.os_auth_url:
raise Exception('ERROR: please specify --os-auth-url')
# Make sure we have the correct arguments to function
self._check_auth_arguments(args, api_version, raise_exc=True)
kwargs = self._build_kwargs_based_on_version(args, api_version)
kwargs.update({
'auth_url': args.os_auth_url,
'token': args.os_auth_token
})
if not api_version or api_version == _DEFAULT_IDENTITY_API_VERSION:
auth = identity.v3.Token(**kwargs)
else:
auth = identity.v2.Token(**kwargs)
ks_session = session.Session(auth=auth, verify=not args.insecure)
self.client = client.Client(
session=ks_session,
endpoint=args.endpoint
)
# Password-based authentication
elif all([args.os_auth_url, args.os_user_id or args.os_username,
args.os_password, args.os_tenant_name or args.os_tenant_id or
args.os_project_name or args.os_project_id]):
@ -153,8 +245,6 @@ class Barbican(app.App):
if args.os_username:
kwargs['username'] = args.os_username
api_version = args.os_identity_api_version
if not api_version or api_version == _DEFAULT_IDENTITY_API_VERSION:
if args.os_project_id:
kwargs['project_id'] = args.os_project_id

View File

@ -133,3 +133,15 @@ class TestBarbicanWithKeystonePasswordAuth(
'--os-username': 'some_user',
'--os-password': 'some_pass',
}
class TestBarbicanWithKeystoneTokenAuth(
keystone_client_fixtures.KeystoneClientFixture):
def setUp(self):
super(TestBarbicanWithKeystoneTokenAuth, self).setUp()
self.test_arguments = {
'--os-auth-token': 'some_token',
'--os-project-id': 'some_project_id',
}

View File

@ -81,8 +81,7 @@ credentials can be passed to Barbican via arguments.
$ barbican --os-auth-url <keystone-v3-url> --os-project-domain-id \
<domain id> --os-user-domain-id <user domain id> --os-username <username> \
--os-password <password> --os-project-name <project-name> --endpoint \
<barbican-endpoint> secret list
--os-password <password> --os-project-name <project-name> secret list
This can become annoying and tedious, so authentication via Keystone can
also be configured by setting environment variables. Barbican uses the same env
@ -127,6 +126,21 @@ each login:
echo "source ~/clientrc" >> ~/.bashrc
Keystone Token Authentication
-----------------------------
Barbican can be configured to use Keystone tokens for authentication. The
user's credentials can be passed to Barbican via arguments.
.. code-block:: bash
$ barbican --os-auth-url <auth_endpoint> --os-auth-token <auth_token> \
--os-project-id <project_id> secret list
Much like normal password authentication you can specify these values via
environmental variables. Refer to `Keystone V3 authentication`_ for more
information.
No Auth Mode
------------

View File

@ -1,5 +1,5 @@
Usage
=====
CLI Usage
=========
.. code-block:: bash
@ -15,6 +15,7 @@ Usage
[--os-project-name <auth-project-name>]
[--os-project-domain-id <auth-project-domain-id>]
[--os-project-domain-name <auth-project-domain-name>]
[--os-auth-token <auth-token>]
[--endpoint <barbican-url>] [--insecure]
[--os-cacert <ca-certificate>] [--os-cert <certificate>]
[--os-key <key>] [--timeout <seconds>]
@ -168,4 +169,4 @@ Secret List
| Secret href | Name | Created | Status | Content types | Algorithm | Bit length | Mode | Expiration |
+-----------------------------------------------------------------------+------+----------------------------------+--------+-------------------------------------------+-----------+------------+------+------------+
| http://localhost:9311/v1/secrets/bb3d8c20-8ea5-4bfc-9645-c8da79c8b371 | None | 2015-04-15 20:37:37.501475+00:00 | ACTIVE | {u'default': u'application/octet-stream'} | aes | 256 | cbc | None |
+-----------------------------------------------------------------------+------+----------------------------------+--------+-------------------------------------------+-----------+------------+------+------------+
+-----------------------------------------------------------------------+------+----------------------------------+--------+-------------------------------------------+-----------+------------+------+------------+

View File

@ -18,6 +18,7 @@ Contents:
installation
authentication
usage
cli_usage
reference
contributing