Merge "More flexible specification of auth credentials."
This commit is contained in:
commit
79cc9254d9
26
bin/glance
26
bin/glance
@ -731,11 +731,12 @@ def get_client(options):
|
|||||||
specified by the --host and --port options
|
specified by the --host and --port options
|
||||||
supplied to the CLI
|
supplied to the CLI
|
||||||
"""
|
"""
|
||||||
creds = dict(username=os.getenv('OS_AUTH_USER'),
|
creds = dict(username=options.username or os.getenv('OS_AUTH_USER'),
|
||||||
password=os.getenv('OS_AUTH_KEY'),
|
password=options.password or os.getenv('OS_AUTH_KEY'),
|
||||||
tenant=os.getenv('OS_AUTH_TENANT'),
|
tenant=options.tenant or os.getenv('OS_AUTH_TENANT'),
|
||||||
auth_url=os.getenv('OS_AUTH_URL'),
|
auth_url=options.auth_url or os.getenv('OS_AUTH_URL'),
|
||||||
strategy=os.getenv('OS_AUTH_STRATEGY', 'noauth'))
|
strategy=options.auth_strategy or \
|
||||||
|
os.getenv('OS_AUTH_STRATEGY', 'noauth'))
|
||||||
|
|
||||||
use_ssl = (options.use_ssl or (
|
use_ssl = (options.use_ssl or (
|
||||||
creds['auth_url'] is not None and
|
creds['auth_url'] is not None and
|
||||||
@ -774,6 +775,21 @@ def create_options(parser):
|
|||||||
metavar="TOKEN", default=None,
|
metavar="TOKEN", default=None,
|
||||||
help="Authentication token to use to identify the "
|
help="Authentication token to use to identify the "
|
||||||
"client to the glance server")
|
"client to the glance server")
|
||||||
|
parser.add_option('-I', '--username', dest="username",
|
||||||
|
metavar="USER", default=None,
|
||||||
|
help="User name used to acquire an authentication token")
|
||||||
|
parser.add_option('-K', '--password', dest="password",
|
||||||
|
metavar="PASSWORD", default=None,
|
||||||
|
help="Password used to acquire an authentication token")
|
||||||
|
parser.add_option('-T', '--tenant', dest="tenant",
|
||||||
|
metavar="TENANT", default=None,
|
||||||
|
help="Tenant name")
|
||||||
|
parser.add_option('-N', '--auth_url', dest="auth_url",
|
||||||
|
metavar="AUTH_URL", default=None,
|
||||||
|
help="Authentication URL")
|
||||||
|
parser.add_option('-S', '--auth_strategy', dest="auth_strategy",
|
||||||
|
metavar="STRATEGY", default=None,
|
||||||
|
help="Authentication strategy (keystone or noauth)")
|
||||||
parser.add_option('--limit', dest="limit", metavar="LIMIT", default=10,
|
parser.add_option('--limit', dest="limit", metavar="LIMIT", default=10,
|
||||||
type="int", help="Page size to use while "
|
type="int", help="Page size to use while "
|
||||||
"requesting image metadata")
|
"requesting image metadata")
|
||||||
|
@ -84,6 +84,32 @@ The final step is to verify that the `OS_AUTH_` crednetials are present::
|
|||||||
OS_AUTH_URL=<THIS SHOULD POINT TO KEYSTONE>
|
OS_AUTH_URL=<THIS SHOULD POINT TO KEYSTONE>
|
||||||
OS_AUTH_STRATEGY=keystone
|
OS_AUTH_STRATEGY=keystone
|
||||||
|
|
||||||
|
Alternatively, these credentials may be specified using the following
|
||||||
|
switches to the ``bin/glance`` command:
|
||||||
|
|
||||||
|
-I USER, --username=USER
|
||||||
|
User name used to acquire an authentication token
|
||||||
|
-K PASSWORD, --password=PASSWORD
|
||||||
|
Password used to acquire an authentication token
|
||||||
|
-T TENANT, --tenant=TENANT
|
||||||
|
Tenant name
|
||||||
|
-N AUTH_URL, --auth_url=AUTH_URL
|
||||||
|
Authentication URL
|
||||||
|
-S STRATEGY, --auth_strategy=STRATEGY
|
||||||
|
Authentication strategy (keystone or noauth)
|
||||||
|
|
||||||
|
Or, if a pre-authenticated token is preferred, the following option allows
|
||||||
|
the client-side interaction with keystone to be by-passed (useful if a long
|
||||||
|
sequence of commands is being scripted):
|
||||||
|
|
||||||
|
-A TOKEN, --auth_token=TOKEN
|
||||||
|
Authentication token to use to identify the client to
|
||||||
|
the glance server
|
||||||
|
|
||||||
|
In general the command line switch takes precedence over the corresponding
|
||||||
|
OS_AUTH_* environment variable, if both are set.
|
||||||
|
|
||||||
|
|
||||||
Configuring the Glance servers to use Keystone
|
Configuring the Glance servers to use Keystone
|
||||||
----------------------------------------------
|
----------------------------------------------
|
||||||
|
|
||||||
|
@ -140,9 +140,19 @@ class KeystoneStrategy(BaseStrategy):
|
|||||||
|
|
||||||
resp, resp_body = self._do_request(token_url, 'GET', headers=headers)
|
resp, resp_body = self._do_request(token_url, 'GET', headers=headers)
|
||||||
|
|
||||||
|
def _management_url(self, resp):
|
||||||
|
for url_header in ('x-image-management-url',
|
||||||
|
'x-server-management-url',
|
||||||
|
'x-glance'):
|
||||||
|
try:
|
||||||
|
return resp[url_header]
|
||||||
|
except KeyError as e:
|
||||||
|
not_found = e
|
||||||
|
raise not_found
|
||||||
|
|
||||||
if resp.status in (200, 204):
|
if resp.status in (200, 204):
|
||||||
try:
|
try:
|
||||||
self.management_url = resp['x-server-management-url']
|
self.management_url = _management_url(self, resp)
|
||||||
self.auth_token = resp['x-auth-token']
|
self.auth_token = resp['x-auth-token']
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise exception.AuthorizationFailure()
|
raise exception.AuthorizationFailure()
|
||||||
|
@ -15,6 +15,9 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
import keystone.manage
|
import keystone.manage
|
||||||
|
|
||||||
DEFAULT_FIXTURE = [
|
DEFAULT_FIXTURE = [
|
||||||
@ -85,7 +88,7 @@ DEFAULT_FIXTURE = [
|
|||||||
'http://nova.publicinternets.com/v1.1/', 'http://127.0.0.1:8774/v1.1',
|
'http://nova.publicinternets.com/v1.1/', 'http://127.0.0.1:8774/v1.1',
|
||||||
'http://localhost:8774/v1.1', '1', '0'),
|
'http://localhost:8774/v1.1', '1', '0'),
|
||||||
('endpointTemplates', 'add', 'RegionOne', 'glance',
|
('endpointTemplates', 'add', 'RegionOne', 'glance',
|
||||||
'http://glance.publicinternets.com/v1.1/%tenant_id%',
|
'http://127.0.0.1:%api_port%/v1',
|
||||||
'http://nova.admin-nets.local/v1.1/%tenant_id%',
|
'http://nova.admin-nets.local/v1.1/%tenant_id%',
|
||||||
'http://127.0.0.1:9292/v1.1/%tenant_id%', '1', '0'),
|
'http://127.0.0.1:9292/v1.1/%tenant_id%', '1', '0'),
|
||||||
('endpointTemplates', 'add', 'RegionOne', 'cdn',
|
('endpointTemplates', 'add', 'RegionOne', 'cdn',
|
||||||
@ -140,10 +143,34 @@ DEFAULT_FIXTURE = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def _get_subsitutions(args):
|
||||||
|
substitutions = {}
|
||||||
|
for arg in args:
|
||||||
|
matches = re.match('(.*)=(.*)', arg)
|
||||||
|
if matches:
|
||||||
|
token = '%%%s%%' % matches.group(1)
|
||||||
|
value = matches.group(2)
|
||||||
|
substitutions[token] = value
|
||||||
|
return substitutions
|
||||||
|
|
||||||
|
|
||||||
|
def _expand(cmd, substitutions):
|
||||||
|
expanded = ()
|
||||||
|
for word in cmd:
|
||||||
|
for token in substitutions.keys():
|
||||||
|
word = word.replace(token, substitutions[token])
|
||||||
|
expanded = expanded + (word,)
|
||||||
|
return expanded
|
||||||
|
|
||||||
|
|
||||||
def load_fixture(fixture=DEFAULT_FIXTURE, args=None):
|
def load_fixture(fixture=DEFAULT_FIXTURE, args=None):
|
||||||
|
substitutions = _get_subsitutions(sys.argv)
|
||||||
|
|
||||||
keystone.manage.parse_args(args)
|
keystone.manage.parse_args(args)
|
||||||
|
|
||||||
for cmd in fixture:
|
for cmd in fixture:
|
||||||
keystone.manage.process(*cmd)
|
expanded = _expand(cmd, substitutions)
|
||||||
|
keystone.manage.process(*expanded)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
@ -66,6 +66,7 @@ log_file = %(log_file)s
|
|||||||
backends = keystone.backends.sqlalchemy
|
backends = keystone.backends.sqlalchemy
|
||||||
service-header-mappings = {
|
service-header-mappings = {
|
||||||
'nova' : 'X-Server-Management-Url',
|
'nova' : 'X-Server-Management-Url',
|
||||||
|
'glance' : 'X-Image-Management-Url',
|
||||||
'swift' : 'X-Storage-Url',
|
'swift' : 'X-Storage-Url',
|
||||||
'cdn' : 'X-CDN-Management-Url'}
|
'cdn' : 'X-CDN-Management-Url'}
|
||||||
service_host = 0.0.0.0
|
service_host = 0.0.0.0
|
||||||
@ -247,7 +248,10 @@ class KeystoneTests(functional.FunctionalTest):
|
|||||||
keystone_conf = self.auth_server.write_conf(**kwargs)
|
keystone_conf = self.auth_server.write_conf(**kwargs)
|
||||||
datafile = os.path.join(os.path.dirname(__file__), 'data',
|
datafile = os.path.join(os.path.dirname(__file__), 'data',
|
||||||
'keystone_data.py')
|
'keystone_data.py')
|
||||||
execute("python %s -c %s" % (datafile, keystone_conf))
|
|
||||||
|
cmd = "python %s -c %s api_port=%d" % \
|
||||||
|
(datafile, keystone_conf, self.api_server.bind_port)
|
||||||
|
execute(cmd)
|
||||||
|
|
||||||
# Start keystone-auth
|
# Start keystone-auth
|
||||||
exitcode, out, err = self.auth_server.start(**kwargs)
|
exitcode, out, err = self.auth_server.start(**kwargs)
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
import httplib2
|
import httplib2
|
||||||
import json
|
import json
|
||||||
|
import os
|
||||||
|
|
||||||
from glance.tests import functional
|
from glance.tests import functional
|
||||||
from glance.tests.functional import keystone_utils
|
from glance.tests.functional import keystone_utils
|
||||||
@ -741,21 +742,25 @@ class TestPrivateImagesCli(keystone_utils.KeystoneTests):
|
|||||||
bin/glance.
|
bin/glance.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@skip_if_disabled
|
def setUp(self):
|
||||||
def test_glance_cli(self):
|
|
||||||
"""
|
"""
|
||||||
Test that we can upload an owned image; that we can manipulate
|
Clear environment to ensure that pre-existing $OS_* variables
|
||||||
its is_public setting; and that appropriate authorization
|
do not leak into test.
|
||||||
checks are applied to other (non-admin) users.
|
"""
|
||||||
|
self._clear_os_env()
|
||||||
|
super(TestPrivateImagesCli, self).setUp()
|
||||||
|
|
||||||
|
def _do_test_glance_cli(self, cmd):
|
||||||
|
"""
|
||||||
|
Test that we can upload an owned image with a given command line;
|
||||||
|
that we can manipulate its is_public setting; and that appropriate
|
||||||
|
authorization checks are applied to other (non-admin) users.
|
||||||
"""
|
"""
|
||||||
self.cleanup()
|
self.cleanup()
|
||||||
self.start_servers()
|
self.start_servers()
|
||||||
|
|
||||||
# Add a non-public image
|
# Add a non-public image using the given glance command line
|
||||||
cmd = ("echo testdata | bin/glance --port=%d --auth_token=%s add "
|
exitcode, out, err = execute("echo testdata | %s" % cmd)
|
||||||
"name=MyImage" %
|
|
||||||
(self.api_port, keystone_utils.pattieblack_token))
|
|
||||||
exitcode, out, err = execute(cmd)
|
|
||||||
|
|
||||||
self.assertEqual(0, exitcode)
|
self.assertEqual(0, exitcode)
|
||||||
image_id = out.strip()[25:]
|
image_id = out.strip()[25:]
|
||||||
@ -833,3 +838,44 @@ class TestPrivateImagesCli(keystone_utils.KeystoneTests):
|
|||||||
self.assertEqual(response['x-image-meta-owner'], '')
|
self.assertEqual(response['x-image-meta-owner'], '')
|
||||||
|
|
||||||
self.stop_servers()
|
self.stop_servers()
|
||||||
|
|
||||||
|
def _clear_os_env(self):
|
||||||
|
os.environ.pop('OS_AUTH_URL', None)
|
||||||
|
os.environ.pop('OS_AUTH_STRATEGY', None)
|
||||||
|
os.environ.pop('OS_AUTH_USER', None)
|
||||||
|
os.environ.pop('OS_AUTH_KEY', None)
|
||||||
|
|
||||||
|
@skip_if_disabled
|
||||||
|
def test_glance_cli_noauth_strategy(self):
|
||||||
|
"""
|
||||||
|
Test the CLI with the noauth strategy defaulted to.
|
||||||
|
"""
|
||||||
|
cmd = ("bin/glance --port=%d --auth_token=%s add name=MyImage" %
|
||||||
|
(self.api_port, keystone_utils.pattieblack_token))
|
||||||
|
self._do_test_glance_cli(cmd)
|
||||||
|
|
||||||
|
@skip_if_disabled
|
||||||
|
def test_glance_cli_keystone_strategy_switches(self):
|
||||||
|
"""
|
||||||
|
Test the CLI with the keystone (v1) strategy enabled via
|
||||||
|
command line switches.
|
||||||
|
"""
|
||||||
|
substitutions = (self.api_port, self.auth_port, 'keystone',
|
||||||
|
'pattieblack', 'secrete')
|
||||||
|
cmd = ("bin/glance --port=%d --auth_url=http://localhost:%d/v1.0 "
|
||||||
|
"--auth_strategy=%s --username=%s --password=%s "
|
||||||
|
" add name=MyImage" % substitutions)
|
||||||
|
self._do_test_glance_cli(cmd)
|
||||||
|
|
||||||
|
@skip_if_disabled
|
||||||
|
def test_glance_cli_keystone_strategy_environment(self):
|
||||||
|
"""
|
||||||
|
Test the CLI with the keystone strategy enabled via
|
||||||
|
environment variables.
|
||||||
|
"""
|
||||||
|
os.environ['OS_AUTH_URL'] = 'http://localhost:%d/v1.0' % self.auth_port
|
||||||
|
os.environ['OS_AUTH_STRATEGY'] = 'keystone'
|
||||||
|
os.environ['OS_AUTH_USER'] = 'pattieblack'
|
||||||
|
os.environ['OS_AUTH_KEY'] = 'secrete'
|
||||||
|
cmd = "bin/glance --port=%d add name=MyImage" % self.api_port
|
||||||
|
self._do_test_glance_cli(cmd)
|
||||||
|
Loading…
Reference in New Issue
Block a user