initial pass to cliauth blueprint
This commit is contained in:
26
README.rst
26
README.rst
@@ -27,7 +27,7 @@ By way of a quick-start::
|
||||
|
||||
# use v2.0 auth with http://example.com:5000/v2.0")
|
||||
>>> from keystoneclient.v2_0 import client
|
||||
>>> keystone = client.Client(username=USERNAME, password=API_KEY, project_id=TENANT, auth_url=KEYSTONE_URL)
|
||||
>>> keystone = client.Client(user_name=USERNAME, password=PASSWORD, tenant_name=TENANT, auth_url=KEYSTONE_URL)
|
||||
>>> keystone.tenants.list()
|
||||
>>> tenant = keystone.tenants.create(name="test", descrption="My new tenant!", enabled=True)
|
||||
>>> tenant.delete()
|
||||
@@ -48,17 +48,16 @@ You'll need to provide your OpenStack username and API key. You can do this
|
||||
with the ``--username``, ``--apikey`` and ``--projectid`` params, but it's
|
||||
easier to just set them as environment variables::
|
||||
|
||||
export KEYSTONE_USERNAME=openstack
|
||||
export KEYSTONE_API_KEY=yadayada
|
||||
export KEYSTONE_PROJECTID=yadayada
|
||||
export OS_TENANT_NAME=project
|
||||
export OS_USER_NAME=user
|
||||
export OS_PASSWORD=pass
|
||||
|
||||
You will also need to define the authentication url with ``--url`` and the
|
||||
version of the API with ``--version``. Or set them as an environment
|
||||
variables as well::
|
||||
|
||||
export KEYSTONE_URL=http://example.com:5000/v2.0
|
||||
export OS_AUTH_URL=http://example.com:5000/v2.0
|
||||
export KEYSTONE_ADMIN_URL=http://example.com:35357/v2.0
|
||||
export KEYSTONE_VERSION=2.0
|
||||
|
||||
Since Keystone can return multiple regions in the Service Catalog, you
|
||||
can specify the one you want with ``--region_name`` (or
|
||||
@@ -67,8 +66,8 @@ can specify the one you want with ``--region_name`` (or
|
||||
You'll find complete documentation on the shell by running
|
||||
``keystone help``::
|
||||
|
||||
usage: keystone [--username USERNAME] [--apikey APIKEY] [--projectid PROJECTID]
|
||||
[--url URL] [--version VERSION] [--region_name NAME]
|
||||
usage: keystone [--user_name user] [--password password]
|
||||
[--tenant_name tenant] [--auth_url URL]
|
||||
<subcommand> ...
|
||||
|
||||
Command-line interface to the OpenStack Keystone API.
|
||||
@@ -79,11 +78,12 @@ You'll find complete documentation on the shell by running
|
||||
|
||||
|
||||
Optional arguments:
|
||||
--username USERNAME Defaults to env[KEYSTONE_USERNAME].
|
||||
--apikey APIKEY Defaults to env[KEYSTONE_API_KEY].
|
||||
--apikey PROJECTID Defaults to env[KEYSTONE_PROJECT_ID].
|
||||
--url AUTH_URL Defaults to env[KEYSTONE_URL] or
|
||||
--url ADMIN_URL Defaults to env[KEYSTONE_ADMIN_URL]
|
||||
--user_name USER Defaults to env[OS_USER_NAME].
|
||||
--user_id USERID Defaults to env[OS_USER_ID].
|
||||
--password PASSWORD Defaults to env[OS_PASSWORD].
|
||||
--tenant_name TENANT Defaults to env[OS_TENANT_NAME].
|
||||
--tenant_id TENANTID Defaults to env[OS_TENANT_].
|
||||
--url AUTH_URL Defaults to env[OS_AUTH_URL] or
|
||||
--version VERSION Defaults to env[KEYSTONE_VERSION] or 2.0.
|
||||
--region_name NAME The region name in the Keystone Service Catalog
|
||||
to use after authentication. Defaults to
|
||||
|
||||
@@ -38,19 +38,22 @@ class HTTPClient(httplib2.Http):
|
||||
|
||||
USER_AGENT = 'python-keystoneclient'
|
||||
|
||||
def __init__(self, username=None, password=None, token=None,
|
||||
def __init__(self, user_name=None, user_id=None,
|
||||
tenant_id=None, tenant_name=None, password=None,
|
||||
project_id=None, auth_url=None, region_name=None,
|
||||
timeout=None, endpoint=None):
|
||||
timeout=None, endpoint=None, token=None):
|
||||
super(HTTPClient, self).__init__(timeout=timeout)
|
||||
self.user = username
|
||||
self.user_id = user_id
|
||||
self.user_name = user_name
|
||||
self.tenant_id = tenant_id
|
||||
self.tenant_name = tenant_name
|
||||
self.password = password
|
||||
self.project_id = unicode(project_id)
|
||||
self.auth_url = auth_url
|
||||
self.version = 'v2.0'
|
||||
self.region_name = region_name
|
||||
self.auth_token = token
|
||||
|
||||
self.management_url = endpoint
|
||||
self.auth_token = token or password
|
||||
|
||||
# httplib2 overrides
|
||||
self.force_exception_to_status_code = True
|
||||
@@ -140,12 +143,11 @@ class HTTPClient(httplib2.Http):
|
||||
kwargs.setdefault('headers', {})
|
||||
if self.auth_token and self.auth_token != self.password:
|
||||
kwargs['headers']['X-Auth-Token'] = self.auth_token
|
||||
if self.project_id:
|
||||
kwargs['headers']['X-Auth-Project-Id'] = self.project_id
|
||||
|
||||
# Perform the request once. If we get a 401 back then it
|
||||
# might be because the auth token expired, so try to
|
||||
# re-authenticate and try again. If it still fails, bail.
|
||||
print 'SENDING: %s' % kwargs
|
||||
try:
|
||||
resp, body = self.request(self.management_url + url, method,
|
||||
**kwargs)
|
||||
|
||||
@@ -55,21 +55,29 @@ class OpenStackIdentityShell(object):
|
||||
action='store_true',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument('--username',
|
||||
default=env('KEYSTONE_USERNAME'),
|
||||
help='Defaults to env[KEYSTONE_USERNAME].')
|
||||
parser.add_argument('--user_name',
|
||||
default=env('OS_USER_NAME'),
|
||||
help='Defaults to env[OS_USER_NAME].')
|
||||
|
||||
parser.add_argument('--apikey',
|
||||
default=env('KEYSTONE_API_KEY'),
|
||||
help='Defaults to env[KEYSTONE_API_KEY].')
|
||||
parser.add_argument('--user_id',
|
||||
default=env('OS_USER_ID'),
|
||||
help='Defaults to env[OS_USER_ID].')
|
||||
|
||||
parser.add_argument('--projectid',
|
||||
default=env('KEYSTONE_PROJECT_ID'),
|
||||
help='Defaults to env[KEYSTONE_PROJECT_ID].')
|
||||
parser.add_argument('--password',
|
||||
default=env('OS_PASSWORD'),
|
||||
help='Defaults to env[OS_PASSWORD].')
|
||||
|
||||
parser.add_argument('--tenant_name',
|
||||
default=env('OS_TENANT_NAME'),
|
||||
help='Defaults to env[OS_TENANT_NAME].')
|
||||
|
||||
parser.add_argument('--tenant_id',
|
||||
default=env('OS_TENANT_ID'),
|
||||
help='Defaults to env[OS_TENANT_ID].')
|
||||
|
||||
parser.add_argument('--url',
|
||||
default=env('KEYSTONE_URL'),
|
||||
help='Defaults to env[KEYSTONE_URL].')
|
||||
default=env('OS_AUTH_URL'),
|
||||
help='Defaults to env[OS_AUTH_URL].')
|
||||
|
||||
parser.add_argument('--region_name',
|
||||
default=env('KEYSTONE_REGION_NAME'),
|
||||
@@ -144,37 +152,29 @@ class OpenStackIdentityShell(object):
|
||||
self.do_help(args)
|
||||
return 0
|
||||
|
||||
user, apikey, projectid, url, region_name = \
|
||||
args.username, args.apikey, args.projectid, args.url, \
|
||||
args.region_name
|
||||
|
||||
#FIXME(usrleon): Here should be restrict for project id same as
|
||||
# for username or apikey but for compatibility it is not.
|
||||
|
||||
if not user:
|
||||
raise exc.CommandError("You must provide a username, either"
|
||||
"via --username or via "
|
||||
"env[KEYSTONE_USERNAME]")
|
||||
if not apikey:
|
||||
raise exc.CommandError("You must provide an API key, either"
|
||||
"via --apikey or via"
|
||||
"env[KEYSTONE_API_KEY]")
|
||||
if options.version and options.version != '1.0':
|
||||
if not projectid:
|
||||
raise exc.CommandError("You must provide an projectid, either"
|
||||
"via --projectid or via"
|
||||
"env[KEYSTONE_PROJECT_ID")
|
||||
if not args.user_id and not args.user_name:
|
||||
raise exc.CommandError("You must provide a user name or id:"
|
||||
"via --user_name or env[OS_USER_NAME]"
|
||||
"via --user_id or env[OS_USER_ID])")
|
||||
if not args.password:
|
||||
raise exc.CommandError("You must provide a password, either"
|
||||
"via --password or env[OS_PASSWORD]")
|
||||
|
||||
if not url:
|
||||
raise exc.CommandError("You must provide a auth url, either"
|
||||
"via --url or via"
|
||||
"env[KEYSTONE_URL")
|
||||
if not args.url:
|
||||
raise exc.CommandError("You must provide a auth url, either"
|
||||
"via --auth_url or via"
|
||||
"env[OS_AUTH_URL")
|
||||
|
||||
self.cs = self.get_api_class(options.version)(user,
|
||||
apikey,
|
||||
projectid,
|
||||
url,
|
||||
region_name=region_name)
|
||||
self.cs = self.get_api_class(options.version)(user_name=args.user_name,
|
||||
user_id=args.user_id,
|
||||
tenant_name=args.tenant_name,
|
||||
tenant_id=args.tenant_id,
|
||||
password=args.password,
|
||||
auth_url=args.auth_url,
|
||||
region_name=args.region_name)
|
||||
|
||||
try:
|
||||
self.cs.authenticate()
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
import urlparse
|
||||
import logging
|
||||
|
||||
from keystoneclient import client
|
||||
@@ -86,20 +85,22 @@ class Client(client.HTTPClient):
|
||||
Returns ``True`` if authentication was successful.
|
||||
"""
|
||||
self.management_url = self.auth_url
|
||||
try:
|
||||
raw_token = self.tokens.authenticate(username=self.user,
|
||||
password=self.password,
|
||||
tenant=self.project_id,
|
||||
token=self.auth_token,
|
||||
return_raw=True)
|
||||
self._extract_service_catalog(self.auth_url, raw_token)
|
||||
return True
|
||||
except (exceptions.AuthorizationFailure, exceptions.Unauthorized):
|
||||
raise
|
||||
except Exception, e:
|
||||
_logger.exception("Authorization Failed.")
|
||||
raise exceptions.AuthorizationFailure("Authorization Failed: "
|
||||
"%s" % e)
|
||||
# try:
|
||||
raw_token = self.tokens.authenticate(user_name=self.user_name,
|
||||
user_id=self.user_id,
|
||||
tenant_id=self.tenant_id,
|
||||
tenant_name=self.tenant_name,
|
||||
password=self.password,
|
||||
return_raw=True)
|
||||
print 'got token %s' % raw_token
|
||||
self._extract_service_catalog(self.auth_url, raw_token)
|
||||
return True
|
||||
# except (exceptions.AuthorizationFailure, exceptions.Unauthorized):
|
||||
# raise
|
||||
# except Exception, e:
|
||||
# _logger.exception("Authorization Failed.")
|
||||
# raise exceptions.AuthorizationFailure("Authorization Failed: "
|
||||
# "%s" % e)
|
||||
|
||||
def _extract_service_catalog(self, url, body):
|
||||
""" Set the client's service catalog from the response data. """
|
||||
@@ -108,9 +109,8 @@ class Client(client.HTTPClient):
|
||||
self.auth_token = self.service_catalog.get_token()
|
||||
except KeyError:
|
||||
raise exceptions.AuthorizationFailure()
|
||||
if self.project_id:
|
||||
# Unscoped tokens don't return a service catalog
|
||||
self.management_url = self.service_catalog.url_for(
|
||||
attr='region',
|
||||
filter_value=self.region_name)
|
||||
|
||||
# Unscoped tokens don't return a service catalog
|
||||
self.management_url = self.service_catalog.url_for(attr='region',
|
||||
filter_value=self.region_name)
|
||||
return self.service_catalog
|
||||
|
||||
@@ -21,17 +21,22 @@ class Token(base.Resource):
|
||||
class TokenManager(base.ManagerWithFind):
|
||||
resource_class = Token
|
||||
|
||||
def authenticate(self, username=None, password=None, tenant=None,
|
||||
token=None, return_raw=False):
|
||||
def authenticate(self, user_name=None, user_id=None, tenant_id=None,
|
||||
tenant_name=None, password=None, token=None, return_raw=False):
|
||||
if token and token != password:
|
||||
params = {"auth": {"token": {"id": token}}}
|
||||
elif username and password:
|
||||
params = {"auth": {"passwordCredentials": {"username": username,
|
||||
elif user_name and password:
|
||||
params = {"auth": {"passwordCredentials": {"username": user_name,
|
||||
"password": password}}}
|
||||
elif user_id and password:
|
||||
params = {"auth": {"passwordCredentials": {"userId": user_id,
|
||||
"password": password}}}
|
||||
else:
|
||||
raise ValueError('A username and password or token is required.')
|
||||
if tenant:
|
||||
params['auth']['tenantId'] = tenant
|
||||
if tenant_id:
|
||||
params['auth']['tenantId'] = tenant_id
|
||||
elif tenant_name:
|
||||
params['auth']['tenantName'] = tenant_name
|
||||
return self._create('/tokens', params, "access", return_raw=return_raw)
|
||||
|
||||
def endpoints(self, token):
|
||||
|
||||
Reference in New Issue
Block a user