Add some bash helpers for auth stuff

Change-Id: If61ac9a050e7a115f37dbf4e74b904ac5dfd2052
This commit is contained in:
Clay Gerrard 2014-04-08 21:14:13 -07:00 committed by Tim Burke
parent ec3e2ab3a0
commit 17feec709c
3 changed files with 156 additions and 6 deletions
swiftclient
tests/unit

@ -31,14 +31,19 @@ from swiftclient.utils import config_true_value, generate_temp_url, prt_bytes
from swiftclient.multithreading import OutputManager from swiftclient.multithreading import OutputManager
from swiftclient.exceptions import ClientException from swiftclient.exceptions import ClientException
from swiftclient import __version__ as client_version from swiftclient import __version__ as client_version
from swiftclient.service import SwiftService, SwiftError, SwiftUploadObject from swiftclient.service import SwiftService, SwiftError, \
SwiftUploadObject, get_conn
from swiftclient.command_helpers import print_account_stats, \ from swiftclient.command_helpers import print_account_stats, \
print_container_stats, print_object_stats print_container_stats, print_object_stats
try:
from shlex import quote as sh_quote
except ImportError:
from pipes import quote as sh_quote
BASENAME = 'swift' BASENAME = 'swift'
commands = ('delete', 'download', 'list', 'post', commands = ('delete', 'download', 'list', 'post', 'stat', 'upload',
'stat', 'upload', 'capabilities', 'info', 'tempurl') 'capabilities', 'info', 'tempurl', 'auth')
def immediate_exit(signum, frame): def immediate_exit(signum, frame):
@ -905,6 +910,46 @@ def st_capabilities(parser, args, output_manager):
st_info = st_capabilities st_info = st_capabilities
st_auth_help = '''
Display auth related authentication variables in shell friendly format.
Commands to run to export storage url and auth token into
OS_STORAGE_URL and OS_AUTH_TOKEN:
swift auth
Commands to append to a runcom file (e.g. ~/.bashrc, /etc/profile) for
automatic authentication:
swift auth -v -U test:tester -K testing \
-A http://localhost:8080/auth/v1.0
'''.strip('\n')
def st_auth(parser, args, thread_manager):
(options, args) = parse_args(parser, args)
_opts = vars(options)
if options.verbose > 1:
if options.auth_version in ('1', '1.0'):
print('export ST_AUTH=%s' % sh_quote(options.auth))
print('export ST_USER=%s' % sh_quote(options.user))
print('export ST_KEY=%s' % sh_quote(options.key))
else:
print('export OS_IDENTITY_API_VERSION=%s' % sh_quote(
options.auth_version))
print('export OS_AUTH_VERSION=%s' % sh_quote(options.auth_version))
print('export OS_AUTH_URL=%s' % sh_quote(options.auth))
for k, v in sorted(_opts.items()):
if v and k.startswith('os_') and \
k not in ('os_auth_url', 'os_options'):
print('export %s=%s' % (k.upper(), sh_quote(v)))
else:
conn = get_conn(_opts)
url, token = conn.get_auth()
print('export OS_STORAGE_URL=%s' % sh_quote(url))
print('export OS_AUTH_TOKEN=%s' % sh_quote(token))
st_tempurl_options = '<method> <seconds> <path> <key>' st_tempurl_options = '<method> <seconds> <path> <key>'
@ -1073,7 +1118,8 @@ Positional arguments:
or object. or object.
upload Uploads files or directories to the given container. upload Uploads files or directories to the given container.
capabilities List cluster capabilities. capabilities List cluster capabilities.
tempurl Create a temporary URL tempurl Create a temporary URL.
auth Display auth related environment variables.
Examples: Examples:
%%prog download --help %%prog download --help

@ -19,8 +19,10 @@ import mock
import os import os
import tempfile import tempfile
import unittest import unittest
import textwrap
from testtools import ExpectedException from testtools import ExpectedException
import six import six
import swiftclient import swiftclient
@ -46,6 +48,11 @@ mocked_os_environ = {
'ST_USER': 'test:tester', 'ST_USER': 'test:tester',
'ST_KEY': 'testing' 'ST_KEY': 'testing'
} }
clean_os_environ = {}
environ_prefixes = ('ST_', 'OS_')
for key in os.environ:
if any(key.startswith(m) for m in environ_prefixes):
clean_os_environ[key] = ''
clean_os_environ = {} clean_os_environ = {}
environ_prefixes = ('ST_', 'OS_') environ_prefixes = ('ST_', 'OS_')
@ -1529,6 +1536,101 @@ class TestAuth(MockHttpTest):
}), }),
]) ])
def test_auth(self):
headers = {
'x-auth-token': 'AUTH_tk5b6b12',
'x-storage-url': 'https://swift.storage.example.com/v1/AUTH_test',
}
mock_resp = self.fake_http_connection(200, headers=headers)
with mock.patch('swiftclient.client.http_connection', new=mock_resp):
stdout = six.StringIO()
with mock.patch('sys.stdout', new=stdout):
argv = [
'',
'auth',
'--auth', 'https://swift.storage.example.com/auth/v1.0',
'--user', 'test:tester', '--key', 'testing',
]
swiftclient.shell.main(argv)
expected = """
export OS_STORAGE_URL=https://swift.storage.example.com/v1/AUTH_test
export OS_AUTH_TOKEN=AUTH_tk5b6b12
"""
self.assertEquals(textwrap.dedent(expected).lstrip(),
stdout.getvalue())
def test_auth_verbose(self):
with mock.patch('swiftclient.client.http_connection') as mock_conn:
stdout = six.StringIO()
with mock.patch('sys.stdout', new=stdout):
argv = [
'',
'auth',
'--auth', 'https://swift.storage.example.com/auth/v1.0',
'--user', 'test:tester', '--key', 'te$tin&',
'--verbose',
]
swiftclient.shell.main(argv)
expected = """
export ST_AUTH=https://swift.storage.example.com/auth/v1.0
export ST_USER=test:tester
export ST_KEY='te$tin&'
"""
self.assertEquals(textwrap.dedent(expected).lstrip(),
stdout.getvalue())
self.assertEqual([], mock_conn.mock_calls)
def test_auth_v2(self):
os_options = {'tenant_name': 'demo'}
with mock.patch('swiftclient.client.get_auth_keystone',
new=fake_get_auth_keystone(os_options)):
stdout = six.StringIO()
with mock.patch('sys.stdout', new=stdout):
argv = [
'',
'auth', '-V2',
'--auth', 'https://keystone.example.com/v2.0/',
'--os-tenant-name', 'demo',
'--os-username', 'demo', '--os-password', 'admin',
]
swiftclient.shell.main(argv)
expected = """
export OS_STORAGE_URL=http://url/
export OS_AUTH_TOKEN=token
"""
self.assertEquals(textwrap.dedent(expected).lstrip(),
stdout.getvalue())
def test_auth_verbose_v2(self):
with mock.patch('swiftclient.client.get_auth_keystone') \
as mock_keystone:
stdout = six.StringIO()
with mock.patch('sys.stdout', new=stdout):
argv = [
'',
'auth', '-V2',
'--auth', 'https://keystone.example.com/v2.0/',
'--os-tenant-name', 'demo',
'--os-username', 'demo', '--os-password', '$eKr3t',
'--verbose',
]
swiftclient.shell.main(argv)
expected = """
export OS_IDENTITY_API_VERSION=2.0
export OS_AUTH_VERSION=2.0
export OS_AUTH_URL=https://keystone.example.com/v2.0/
export OS_PASSWORD='$eKr3t'
export OS_TENANT_NAME=demo
export OS_USERNAME=demo
"""
self.assertEquals(textwrap.dedent(expected).lstrip(),
stdout.getvalue())
self.assertEqual([], mock_keystone.mock_calls)
class TestCrossAccountObjectAccess(TestBase, MockHttpTest): class TestCrossAccountObjectAccess(TestBase, MockHttpTest):
""" """

@ -38,8 +38,10 @@ def fake_get_auth_keystone(expected_os_options=None, exc=None,
if exc: if exc:
raise exc('test') raise exc('test')
# TODO: some way to require auth_url, user and key? # TODO: some way to require auth_url, user and key?
if expected_os_options and actual_os_options != expected_os_options: if expected_os_options:
return "", None for key, value in actual_os_options.items():
if value and value != expected_os_options.get(key):
return "", None
if 'required_kwargs' in kwargs: if 'required_kwargs' in kwargs:
for k, v in kwargs['required_kwargs'].items(): for k, v in kwargs['required_kwargs'].items():
if v != actual_kwargs.get(k): if v != actual_kwargs.get(k):