Added v3 auth extension and updated v2 auth extension
This commit is contained in:
parent
ed319d1b57
commit
c2ea797565
|
@ -13,78 +13,112 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from cafe.engine.behaviors import BaseBehavior
|
||||
from cafe.engine.http.client import AutoMarshallingHTTPClient
|
||||
|
||||
from syntribos.extensions.rax_auth.models import auth_models
|
||||
from syntribos.extensions.rax_auth.auth_config import (
|
||||
UserAuthConfig, UserConfig)
|
||||
from syntribos.extensions.identity.models import v2, v3
|
||||
from syntribos.extensions.identity.config import (
|
||||
EndpointConfig, UserConfig)
|
||||
|
||||
|
||||
class TokensBehavior(BaseBehavior):
|
||||
@classmethod
|
||||
def get_access_data_config(cls, user_config, userauth_config):
|
||||
return cls.get_access_data(
|
||||
url=user_config.endpoint or userauth_config.endpoint,
|
||||
username=user_config.username,
|
||||
password=user_config.password,
|
||||
tenant_name=user_config.tenant_name,
|
||||
tenant_id=user_config.tenant_id,
|
||||
token=user_config.token,
|
||||
api_key=user_config.api_key,
|
||||
serialize_format=userauth_config.serialize_format,
|
||||
deserialize_format=userauth_config.deserialize_format)
|
||||
def authenticate_v2(
|
||||
url, username=None, password=None, tenant_name=None,
|
||||
tenant_id=None, token=None, domain=None, serialize_format="json",
|
||||
deserialize_format="json"):
|
||||
url = '{0}/v2.0/tokens'.format(url)
|
||||
client = AutoMarshallingHTTPClient(serialize_format, deserialize_format)
|
||||
client.default_headers["Content-Type"] = "application/{0}".format(
|
||||
serialize_format)
|
||||
client.default_headers["Accept"] = "application/{0}".format(
|
||||
deserialize_format)
|
||||
|
||||
@classmethod
|
||||
def get_access_data(cls, *args, **kwargs):
|
||||
return cls.authenticate(*args, **kwargs).entity
|
||||
kwargs = {}
|
||||
kwargs["tenant_name"] = tenant_name
|
||||
kwargs["tenant_id"] = tenant_id
|
||||
|
||||
@classmethod
|
||||
def authenticate(
|
||||
cls, url, username=None, password=None, tenant_name=None,
|
||||
tenant_id=None, token=None, api_key=None, rsa_key=None,
|
||||
domain=None, serialize_format="json", deserialize_format="json"):
|
||||
url = '{0}/tokens'.format(url)
|
||||
client = AutoMarshallingHTTPClient(
|
||||
serialize_format, deserialize_format)
|
||||
if password is not None:
|
||||
password_creds = v2.PasswordCredentials(
|
||||
username=username, password=password)
|
||||
|
||||
client.default_headers["Content-Type"] = "application/{0}".format(
|
||||
serialize_format)
|
||||
client.default_headers["Accept"] = "application/{0}".format(
|
||||
deserialize_format)
|
||||
request_entity = v2.Auth(
|
||||
tenant_name=tenant_name, tenant_id=tenant_id,
|
||||
password_creds=password_creds)
|
||||
|
||||
kwargs = {}
|
||||
kwargs["tenant_name"] = tenant_name
|
||||
kwargs["tenant_id"] = tenant_id
|
||||
r = client.request(
|
||||
"POST", url, request_entity=request_entity,
|
||||
response_entity_type=v2.AuthResponse)
|
||||
|
||||
if password is not None:
|
||||
kwargs["password_creds"] = auth_models.PasswordCredentials(
|
||||
username=username, password=password)
|
||||
if not r.ok:
|
||||
raise Exception("Failed to authenticate")
|
||||
|
||||
if token is not None:
|
||||
kwargs["token_creds"] = auth_models.Token(id_=token)
|
||||
|
||||
if api_key is not None:
|
||||
kwargs["api_key_creds"] = auth_models.APIKeyCredentials(
|
||||
username=username, api_key=api_key)
|
||||
|
||||
request_entity = auth_models.Auth(**kwargs)
|
||||
|
||||
r = client.request(
|
||||
"POST", url, request_entity=request_entity,
|
||||
response_entity_type=auth_models.AuthResponse)
|
||||
if not r.ok:
|
||||
raise Exception("Failed to authenticate")
|
||||
|
||||
r.entity = auth_models.AuthResponse.deserialize(
|
||||
r.content, deserialize_format)
|
||||
if r.entity is None:
|
||||
raise Exception("Failed to parse Auth response Body")
|
||||
return r
|
||||
if r.entity is None:
|
||||
raise Exception("Failed to parse Auth response Body")
|
||||
return r
|
||||
|
||||
|
||||
def get_token(section_name):
|
||||
access_data = TokensBehavior.get_access_data_config(
|
||||
UserConfig(section_name=section_name), UserAuthConfig())
|
||||
def authenticate_v2_config(user_config, userauth_config):
|
||||
return authenticate_v2(
|
||||
url=user_config.endpoint or userauth_config.endpoint,
|
||||
username=user_config.username,
|
||||
password=user_config.password,
|
||||
tenant_name=user_config.tenant_name,
|
||||
tenant_id=user_config.tenant_id,
|
||||
token=user_config.token,
|
||||
serialize_format=userauth_config.serialize_format,
|
||||
deserialize_format=userauth_config.deserialize_format)
|
||||
|
||||
|
||||
def get_token_v2(user_section_name=None, endpoint_section_name=None):
|
||||
access_data = authenticate_v2_config(
|
||||
UserConfig(section_name=user_section_name),
|
||||
EndpointConfig(section_name=endpoint_section_name)).entity
|
||||
return access_data.token.id_
|
||||
|
||||
|
||||
def authenticate_v3(
|
||||
url, username=None, password=None, user_id=None, domain_id=None,
|
||||
domain_name=None, token=None):
|
||||
|
||||
url = '{0}/v3/auth/tokens'.format(url)
|
||||
client = AutoMarshallingHTTPClient("json", "json")
|
||||
client.default_headers["Content-Type"] = "application/json"
|
||||
client.default_headers["Accept"] = "application/json"
|
||||
|
||||
if user_id is not None:
|
||||
domain = None
|
||||
username = None
|
||||
else:
|
||||
domain = v3.Domain(name=domain_name, id_=domain_id)
|
||||
password = v3.Password(user=v3.User(
|
||||
name=username, password=password, id_=user_id, domain=domain))
|
||||
|
||||
if token is not None:
|
||||
kwargs = {"token": v3.Token(id_=token), "methods": ["token"]}
|
||||
else:
|
||||
kwargs = {"password": password, "methods": ["password"]}
|
||||
request_entity = v3.Auth(identity=v3.Identity(**kwargs))
|
||||
|
||||
r = client.request(
|
||||
"POST", url, request_entity=request_entity)
|
||||
|
||||
if not r.ok:
|
||||
raise Exception("Failed to authenticate")
|
||||
|
||||
return r
|
||||
|
||||
|
||||
def authenticate_v3_config(user_config, endpoint_config):
|
||||
return authenticate_v3(
|
||||
url=user_config.endpoint or endpoint_config.endpoint,
|
||||
username=user_config.username,
|
||||
password=user_config.password,
|
||||
user_id=user_config.user_id,
|
||||
domain_id=user_config.domain_id,
|
||||
domain_name=user_config.domain_name,
|
||||
token=user_config.token)
|
||||
|
||||
|
||||
def get_token_v3(user_section_name=None, endpoint_section_name=None):
|
||||
r = authenticate_v3_config(
|
||||
UserConfig(section_name=user_section_name),
|
||||
EndpointConfig(section_name=endpoint_section_name))
|
||||
return r.headers.get("X-Subject-Token")
|
||||
|
|
|
@ -17,7 +17,7 @@ limitations under the License.
|
|||
from cafe.engine.models.data_interfaces import ConfigSectionInterface
|
||||
|
||||
|
||||
class UserAuthConfig(ConfigSectionInterface):
|
||||
class EndpointConfig(ConfigSectionInterface):
|
||||
SECTION_NAME = 'auth'
|
||||
|
||||
@property
|
||||
|
@ -44,6 +44,10 @@ class UserConfig(ConfigSectionInterface):
|
|||
def password(self):
|
||||
return self.get_raw("password")
|
||||
|
||||
@property
|
||||
def user_id(self):
|
||||
return self.get("user_id")
|
||||
|
||||
@property
|
||||
def tenant_id(self):
|
||||
return self.get("tenant_id")
|
||||
|
@ -62,3 +66,11 @@ class UserConfig(ConfigSectionInterface):
|
|||
example the admin user needs to use an internal endpoint.
|
||||
"""
|
||||
return self.get("endpoint")
|
||||
|
||||
@property
|
||||
def domain_id(self):
|
||||
return self.get("domain_id")
|
||||
|
||||
@property
|
||||
def domain_name(self):
|
||||
return self.get("domain_name")
|
|
@ -1,424 +0,0 @@
|
|||
"""
|
||||
Copyright 2015 Rackspace
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT 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 json
|
||||
from xml.etree import ElementTree as ET
|
||||
from cafe.engine.models.base import (
|
||||
AutoMarshallingModel, AutoMarshallingListModel)
|
||||
|
||||
|
||||
class V2_0Constants(object):
|
||||
XML_NS = 'http://docs.openstack.org/identity/api/v2.0'
|
||||
XML_NS_OPENSTACK_COMMON = 'http://docs.openstack.org/common/api/v1.0'
|
||||
XML_NS_XSI = 'http://www.w3.org/2001/XMLSchema-instance'
|
||||
XML_NS_OS_KSADM = \
|
||||
'http://docs.openstack.org/identity/api/ext/OS-KSADM/v1.0'
|
||||
XML_NS_OS_KSEC2 = \
|
||||
'http://docs.openstack.org/identity/api/ext/OS-KSEC2/v1.0'
|
||||
XML_NS_ATOM = 'http://www.w3.org/2005/Atom'
|
||||
|
||||
|
||||
class BaseIdentityModel(AutoMarshallingModel):
|
||||
_namespaces = V2_0Constants
|
||||
|
||||
def __init__(self, kwargs):
|
||||
super(BaseIdentityModel, self).__init__()
|
||||
for var in kwargs:
|
||||
if var != "self" and not var.startswith("_"):
|
||||
setattr(self, var, kwargs.get(var))
|
||||
|
||||
@classmethod
|
||||
def _remove_xml_namespaces(cls, element):
|
||||
for key, value in cls._namespaces.__dict__.items():
|
||||
if key.startswith("__"):
|
||||
continue
|
||||
element = cls._remove_namespace(element, value)
|
||||
return element
|
||||
|
||||
@classmethod
|
||||
def _remove_namespace(cls, element, XML_NS):
|
||||
return cls._remove_xml_etree_namespace(element, XML_NS)
|
||||
|
||||
@classmethod
|
||||
def _json_to_obj(cls, serialized_str):
|
||||
data_dict = json.loads(serialized_str)
|
||||
return cls._dict_to_obj(data_dict)
|
||||
|
||||
@classmethod
|
||||
def _xml_to_obj(cls, serialized_str):
|
||||
element = ET.fromstring(serialized_str)
|
||||
return cls._xml_ele_to_obj(
|
||||
cls._remove_xml_namespaces(element))
|
||||
|
||||
def _obj_to_json(self):
|
||||
return json.dumps(self._obj_to_dict())
|
||||
|
||||
def _obj_to_xml(self):
|
||||
element = self._obj_to_xml_ele()
|
||||
return ET.tostring(element)
|
||||
|
||||
@staticmethod
|
||||
def _find(element, tag):
|
||||
if element is None:
|
||||
return ET.Element(None)
|
||||
new_element = element.find(tag)
|
||||
if new_element is None:
|
||||
return ET.Element(None)
|
||||
return new_element
|
||||
|
||||
|
||||
class BaseIdentityListModel(AutoMarshallingListModel, BaseIdentityModel):
|
||||
pass
|
||||
|
||||
|
||||
class EmptyModel(object):
|
||||
def _obj_to_dict(self):
|
||||
return None
|
||||
|
||||
def _obj_to_xml_ele(self):
|
||||
return ET.Element(None)
|
||||
|
||||
|
||||
class AuthResponse(BaseIdentityModel):
|
||||
def __init__(
|
||||
self, token=None, service_catalog=None, user=None, metadata=None):
|
||||
super(AuthResponse, self).__init__(locals())
|
||||
|
||||
@classmethod
|
||||
def _dict_to_obj(cls, data):
|
||||
return cls(
|
||||
token=AuthResponseToken._dict_to_obj(data.get('token')),
|
||||
metadata=Metadata._dict_to_obj(data.get('metadata')),
|
||||
user=User._dict_to_obj(data.get('user')),
|
||||
service_catalog=ServiceCatalog._dict_to_obj(
|
||||
data.get('serviceCatalog')))
|
||||
|
||||
@classmethod
|
||||
def _json_to_obj(cls, serialized_str):
|
||||
data_dict = json.loads(serialized_str)
|
||||
return cls._dict_to_obj(data_dict.get("access"))
|
||||
|
||||
@classmethod
|
||||
def _xml_ele_to_obj(cls, ele):
|
||||
return cls(
|
||||
token=AuthResponseToken._xml_ele_to_obj(ele.find('token')),
|
||||
metadata=Metadata._xml_ele_to_obj(ele.find('metadata')),
|
||||
user=User._xml_ele_to_obj(ele.find('user')),
|
||||
service_catalog=ServiceCatalog._xml_ele_to_obj(
|
||||
ele.find('serviceCatalog')))
|
||||
|
||||
def get_service(self, name):
|
||||
for service in self.service_catalog:
|
||||
if service.name == name:
|
||||
return service
|
||||
return None
|
||||
|
||||
|
||||
class Metadata(BaseIdentityModel):
|
||||
|
||||
@classmethod
|
||||
def _dict_to_obj(cls, data):
|
||||
return data
|
||||
|
||||
@classmethod
|
||||
def _xml_ele_to_obj(cls, ele):
|
||||
return ele.attrib
|
||||
|
||||
|
||||
class Tenant(BaseIdentityModel):
|
||||
def __init__(self, enabled=None, description=None, name=None, id_=None):
|
||||
super(Tenant, self).__init__(locals())
|
||||
|
||||
@classmethod
|
||||
def _xml_ele_to_obj(cls, element):
|
||||
if element.tag.lower() != "tenant":
|
||||
raise Exception("wrong element")
|
||||
enabled = True if element.attrib.get('enabled') == "true" else False
|
||||
description = element.find('description')
|
||||
description = "" if description is None else description.text
|
||||
return cls(enabled=enabled,
|
||||
description=description,
|
||||
name=element.attrib.get('name'),
|
||||
id_=element.attrib.get('id'))
|
||||
|
||||
@classmethod
|
||||
def _dict_to_obj(cls, data_dict):
|
||||
return cls(description=data_dict.get('description'),
|
||||
enabled=data_dict.get('enabled'),
|
||||
id_=data_dict.get('id'),
|
||||
name=data_dict.get('name'))
|
||||
|
||||
@classmethod
|
||||
def _json_to_obj(cls, serialized_str):
|
||||
data_dict = json.loads(serialized_str)
|
||||
return cls._dict_to_obj(data_dict.get('tenant'))
|
||||
|
||||
|
||||
class AuthResponseToken(BaseIdentityModel):
|
||||
def __init__(self, id_=None, issued_at=None, expires=None, tenant=None):
|
||||
super(AuthResponseToken, self).__init__(locals())
|
||||
|
||||
@classmethod
|
||||
def _dict_to_obj(cls, data):
|
||||
return cls(id_=data.get('id'),
|
||||
expires=data.get('expires'),
|
||||
issued_at=data.get('issued_at'),
|
||||
tenant=Tenant._dict_to_obj(data.get('tenant')))
|
||||
|
||||
@classmethod
|
||||
def _xml_ele_to_obj(cls, ele):
|
||||
return cls(id_=ele.attrib.get('id'),
|
||||
expires=ele.attrib.get('expires'),
|
||||
issued_at=ele.attrib.get('issued_at'),
|
||||
tenant=Tenant._xml_ele_to_obj(ele.find('tenant')))
|
||||
|
||||
|
||||
class ServiceCatalog(BaseIdentityListModel):
|
||||
|
||||
@classmethod
|
||||
def _dict_to_obj(cls, data):
|
||||
return ServiceCatalog(
|
||||
[Service._dict_to_obj(service) for service in data])
|
||||
|
||||
@classmethod
|
||||
def _xml_ele_to_obj(cls, element):
|
||||
return ServiceCatalog(
|
||||
[Service._xml_ele_to_obj(service) for service in element])
|
||||
|
||||
|
||||
class User(BaseIdentityModel):
|
||||
def __init__(
|
||||
self, id_=None, name=None, username=None, roles=None,
|
||||
roles_links=None):
|
||||
super(User, self).__init__(locals())
|
||||
|
||||
@classmethod
|
||||
def _dict_to_obj(cls, data):
|
||||
return cls(
|
||||
id_=data.get('id'),
|
||||
name=data.get('name'),
|
||||
username=data.get('username'),
|
||||
roles=Roles._dict_to_obj(data.get('roles')),
|
||||
roles_links=RolesLinks._dict_to_obj(data.get('roles_links')))
|
||||
|
||||
@classmethod
|
||||
def _xml_ele_to_obj(cls, ele):
|
||||
return cls(
|
||||
id_=ele.attrib.get('id'),
|
||||
name=ele.attrib.get('name'),
|
||||
username=ele.attrib.get('username'),
|
||||
roles=Roles._xml_ele_to_obj(ele.findall('role')),
|
||||
roles_links=RolesLinks._xml_ele_to_obj(ele.find('roles_links')))
|
||||
|
||||
|
||||
class Service(BaseIdentityModel):
|
||||
def __init__(
|
||||
self, endpoints=None, endpoints_links=None, name=None, type_=None):
|
||||
super(Service, self).__init__(locals())
|
||||
|
||||
def get_endpoint(self, region):
|
||||
"""
|
||||
Returns the endpoint that matches the provided region,
|
||||
or None if such an endpoint is not found
|
||||
"""
|
||||
for endpoint in self.endpoints:
|
||||
if getattr(endpoint, 'region'):
|
||||
if str(endpoint.region).lower() == str(region).lower():
|
||||
return endpoint
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def _dict_to_obj(cls, data):
|
||||
return cls(
|
||||
endpoints=Endpoints._dict_to_obj(data.get('endpoints')),
|
||||
endpoints_links=EndpointsLinks._dict_to_obj(
|
||||
data.get('endpoints_links')),
|
||||
name=data.get('name'), type_=data.get('type'))
|
||||
|
||||
@classmethod
|
||||
def _xml_ele_to_obj(cls, ele):
|
||||
return cls(
|
||||
endpoints=Endpoints._xml_ele_to_obj(ele.findall("endpoint")),
|
||||
endpoints_links=EndpointsLinks._xml_ele_to_obj(
|
||||
ele.find('endpoints_links')),
|
||||
name=ele.attrib.get('name'),
|
||||
type_=ele.attrib.get('type'))
|
||||
|
||||
|
||||
class Endpoints(BaseIdentityListModel):
|
||||
@classmethod
|
||||
def _xml_ele_to_obj(cls, elements):
|
||||
if not elements:
|
||||
return cls()
|
||||
return cls([Endpoint._xml_ele_to_obj(endp) for endp in elements])
|
||||
|
||||
@classmethod
|
||||
def _dict_to_obj(cls, data):
|
||||
if not data:
|
||||
return cls()
|
||||
return cls([Endpoint._dict_to_obj(endpoint) for endpoint in data])
|
||||
|
||||
@classmethod
|
||||
def _json_to_obj(cls, string):
|
||||
data = json.loads(string)
|
||||
return cls._dict_to_obj(data.get("endpoints"))
|
||||
|
||||
|
||||
class EndpointsLinks(BaseIdentityListModel):
|
||||
# always returns an empty list since no documentation on endpoint links
|
||||
@classmethod
|
||||
def _dict_to_obj(cls, data):
|
||||
return EndpointsLinks()
|
||||
|
||||
@classmethod
|
||||
def _xml_ele_to_obj(cls, ele):
|
||||
return EndpointsLinks()
|
||||
|
||||
|
||||
class Endpoint(BaseIdentityModel):
|
||||
def __init__(
|
||||
self, region=None, id_=None, public_url=None, admin_url=None,
|
||||
internal_url=None, private_url=None, version_id=None,
|
||||
version_info=None, version_list=None):
|
||||
super(Endpoint, self).__init__(locals())
|
||||
|
||||
@classmethod
|
||||
def _dict_to_obj(cls, data):
|
||||
return cls(region=data.get('region'),
|
||||
id_=data.get('Id'),
|
||||
public_url=data.get('publicURL'),
|
||||
private_url=data.get('privateURL'),
|
||||
admin_url=data.get('adminURL'),
|
||||
internal_url=data.get('internalURL'),
|
||||
version_id=data.get('versionId'),
|
||||
version_info=data.get('versionInfo'),
|
||||
version_list=data.get('versionList'))
|
||||
|
||||
@classmethod
|
||||
def _xml_ele_to_obj(cls, ele):
|
||||
return cls(region=ele.attrib.get('region'),
|
||||
id_=ele.attrib.get('Id'),
|
||||
public_url=ele.attrib.get('publicURL'),
|
||||
private_url=ele.attrib.get('privateURL'),
|
||||
admin_url=ele.attrib.get('adminURL'),
|
||||
internal_url=ele.attrib.get('internalURL'),
|
||||
version_id=ele.attrib.get('versionId'),
|
||||
version_info=ele.attrib.get('versionInfo'),
|
||||
version_list=ele.attrib.get('versionList'))
|
||||
|
||||
|
||||
class Roles(BaseIdentityListModel):
|
||||
|
||||
@classmethod
|
||||
def _xml_ele_to_obj(cls, elements):
|
||||
return Roles(
|
||||
[Role._xml_ele_to_obj(element) for element in elements])
|
||||
|
||||
@classmethod
|
||||
def _dict_to_obj(cls, data):
|
||||
return Roles([Role._dict_to_obj(obj) for obj in data])
|
||||
|
||||
|
||||
class RolesLinks(BaseIdentityListModel):
|
||||
# always returns an empty list since no documentation on role links
|
||||
@classmethod
|
||||
def _dict_to_obj(cls, data):
|
||||
return RolesLinks()
|
||||
|
||||
@classmethod
|
||||
def _xml_ele_to_obj(cls, data):
|
||||
return RolesLinks()
|
||||
|
||||
|
||||
class Role(BaseIdentityModel):
|
||||
def __init__(
|
||||
self, id_=None, name=None, description=None,
|
||||
rax_auth_propagate=None, tenant_id=None, service_id=None):
|
||||
super(Role, self).__init__(locals())
|
||||
|
||||
@classmethod
|
||||
def _xml_ele_to_obj(cls, element):
|
||||
if element is None:
|
||||
return None
|
||||
return cls(
|
||||
id_=element.attrib.get("id"),
|
||||
name=element.attrib.get("name"),
|
||||
description=element.attrib.get("description"))
|
||||
|
||||
@classmethod
|
||||
def _dict_to_obj(cls, data):
|
||||
if data is None:
|
||||
return None
|
||||
return cls(
|
||||
id_=data.get("id"),
|
||||
name=data.get("name"),
|
||||
description=data.get("description"))
|
||||
|
||||
|
||||
class Auth(BaseIdentityModel):
|
||||
|
||||
def __init__(
|
||||
self, username=None, password=None, tenant_name=None,
|
||||
tenant_id=None, token=None):
|
||||
super(Auth, self).__init__(locals())
|
||||
|
||||
def _obj_to_dict(self):
|
||||
attrs = {
|
||||
"tenantName": self.tenant_name,
|
||||
"tenantId": self.tenant_id,
|
||||
"passwordCredentials": self.password_credentials._obj_to_dict()}
|
||||
return {'auth': self._remove_empty_values(attrs)}
|
||||
|
||||
def _obj_to_xml_ele(self):
|
||||
element = ET.Element('auth')
|
||||
element = self._set_xml_etree_element(
|
||||
element, {"tenantName": self.tenant_name,
|
||||
"tenantId": self.tenant_id})
|
||||
element.append(self.password_credentials._obj_to_xml_ele())
|
||||
return element
|
||||
|
||||
|
||||
class PasswordCredentials(BaseIdentityModel):
|
||||
|
||||
def __init__(self, username=None, password=None):
|
||||
super(PasswordCredentials, self).__init__(locals())
|
||||
|
||||
def _obj_to_dict(self):
|
||||
attrs = {
|
||||
"username": self.username,
|
||||
"password": self.password}
|
||||
return self._remove_empty_values(attrs)
|
||||
|
||||
def _obj_to_xml_ele(self):
|
||||
element = ET.Element('passwordCredentials')
|
||||
attrs = {
|
||||
"username": self.username,
|
||||
"password": self.password}
|
||||
return self._set_xml_etree_element(element, attrs)
|
||||
|
||||
|
||||
class Token(BaseIdentityModel):
|
||||
def __init__(self, id_=None):
|
||||
super(Token, self).__init__(locals())
|
||||
|
||||
def _obj_to_dict(self):
|
||||
attrs = {"id": self.id_}
|
||||
return self._remove_empty_values(attrs)
|
||||
|
||||
def _obj_to_xml_ele(self):
|
||||
element = ET.Element('token')
|
||||
attrs = {"id": self.id_}
|
||||
return self._set_xml_etree_element(element, attrs)
|
|
@ -0,0 +1,125 @@
|
|||
import json
|
||||
import six
|
||||
from xml.etree import ElementTree as ET
|
||||
|
||||
from cafe.engine.models.base import AutoMarshallingModel
|
||||
|
||||
|
||||
class Namespaces(object):
|
||||
XMLNS_XSI = "http://www.w3.org/2001/XMLSchema-instance"
|
||||
XMLNS = "http://docs.openstack.org/identity/api/v2.0"
|
||||
XMLNS_KSKEY = "http://docs.rackspace.com/identity/api/ext/RAX-KSKEY/v1.0"
|
||||
XMLNS_RAX_AUTH = "http://docs.rackspace.com/identity/api/ext/RAX-AUTH/v1.0"
|
||||
|
||||
|
||||
class BaseIdentityModel(AutoMarshallingModel):
|
||||
_namespaces = Namespaces
|
||||
|
||||
def __init__(self, kwargs):
|
||||
super(BaseIdentityModel, self).__init__()
|
||||
for k, v in kwargs.items():
|
||||
if k != "self" and not k.startswith("_"):
|
||||
setattr(self, k, v)
|
||||
|
||||
@classmethod
|
||||
def _remove_xml_namespaces(cls, element):
|
||||
for key, value in vars(cls._namespaces).items():
|
||||
if key.startswith("__"):
|
||||
continue
|
||||
element = cls._remove_xml_etree_namespace(element, value)
|
||||
return element
|
||||
|
||||
@classmethod
|
||||
def _json_to_obj(cls, serialized_str):
|
||||
data_dict = json.loads(serialized_str, strict=False)
|
||||
return cls._dict_to_obj(data_dict)
|
||||
|
||||
@classmethod
|
||||
def _xml_to_obj(cls, serialized_str, encoding="iso-8859-2"):
|
||||
parser = ET.XMLParser(encoding=encoding)
|
||||
element = ET.fromstring(serialized_str, parser=parser)
|
||||
return cls._xml_ele_to_obj(cls._remove_xml_namespaces(element))
|
||||
|
||||
def _obj_to_json(self):
|
||||
return json.dumps(self._obj_to_dict())
|
||||
|
||||
def _obj_to_xml(self):
|
||||
element = self._obj_to_xml_ele()
|
||||
element.attrib["xmlns"] = self._namespaces.XMLNS
|
||||
return ET.tostring(element)
|
||||
|
||||
@staticmethod
|
||||
def _find(element, tag):
|
||||
if element is None:
|
||||
return ET.Element(None)
|
||||
new_element = element.find(tag)
|
||||
if new_element is None:
|
||||
return ET.Element(None)
|
||||
return new_element
|
||||
|
||||
@staticmethod
|
||||
def _build_list_model(data, field_name, model):
|
||||
if data is None:
|
||||
return []
|
||||
if isinstance(data, dict):
|
||||
if data.get(field_name) is None:
|
||||
return []
|
||||
return [model._dict_to_obj(tmp) for tmp in data.get(field_name)]
|
||||
return [model._xml_ele_to_obj(tmp) for tmp in data.findall(field_name)]
|
||||
|
||||
@staticmethod
|
||||
def _build_list(items, element=None):
|
||||
if element is None:
|
||||
if items is None:
|
||||
return []
|
||||
return [item._obj_to_dict() for item in items]
|
||||
else:
|
||||
if items is None:
|
||||
return element
|
||||
for item in items:
|
||||
element.append(item._obj_to_xml_ele())
|
||||
return element
|
||||
|
||||
@staticmethod
|
||||
def _create_text_element(name, text):
|
||||
element = ET.Element(name)
|
||||
if text is True or text is False:
|
||||
element.text = str(text).lower()
|
||||
elif text is None:
|
||||
return ET.Element(None)
|
||||
else:
|
||||
element.text = str(text)
|
||||
return element
|
||||
|
||||
def __ne__(self, obj):
|
||||
return not self.__eq__(obj)
|
||||
|
||||
@classmethod
|
||||
def _remove_empty_values(cls, data):
|
||||
"""Returns a new dictionary based on 'dictionary', minus any keys with
|
||||
values that evaluate to False
|
||||
"""
|
||||
if isinstance(data, dict):
|
||||
return dict(
|
||||
(k, v) for k, v in six.iteritems(data) if v not in (
|
||||
[], {}, None))
|
||||
elif isinstance(data, ET.Element):
|
||||
if data.attrib:
|
||||
data.attrib = cls._remove_empty_values(data.attrib)
|
||||
data._children = [
|
||||
c for c in data._children if c.tag is not None and (
|
||||
c.attrib or c.text is not None or c._children)]
|
||||
return data
|
||||
|
||||
@staticmethod
|
||||
def _get_sub_model(model, json=True):
|
||||
if json:
|
||||
if model is not None:
|
||||
return model._obj_to_dict()
|
||||
else:
|
||||
return None
|
||||
else:
|
||||
if model is not None:
|
||||
return model._obj_to_xml_ele()
|
||||
else:
|
||||
return ET.Element(None)
|
|
@ -0,0 +1,237 @@
|
|||
"""
|
||||
Copyright 2015 Rackspace
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT 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 json
|
||||
from xml.etree import ElementTree as ET
|
||||
|
||||
from syntribos.extensions.identity.models.base import BaseIdentityModel
|
||||
|
||||
|
||||
class AuthResponse(BaseIdentityModel):
|
||||
def __init__(
|
||||
self, token=None, service_catalog=None, user=None, metadata=None):
|
||||
super(AuthResponse, self).__init__(locals())
|
||||
|
||||
@classmethod
|
||||
def _dict_to_obj(cls, data):
|
||||
return cls(
|
||||
token=Token._dict_to_obj(data.get('token')),
|
||||
metadata=Metadata._dict_to_obj(data.get('metadata')),
|
||||
user=User._dict_to_obj(data.get('user')),
|
||||
service_catalog=cls._build_list_model(
|
||||
data, "serviceCatalog", Service))
|
||||
|
||||
@classmethod
|
||||
def _json_to_obj(cls, serialized_str):
|
||||
data_dict = json.loads(serialized_str)
|
||||
return cls._dict_to_obj(data_dict.get("access"))
|
||||
|
||||
@classmethod
|
||||
def _xml_ele_to_obj(cls, data):
|
||||
return cls(
|
||||
service_catalog=cls._build_list_model(
|
||||
cls._find(data, "serviceCatalog"), "service", Service),
|
||||
token_model=Token._xml_ele_to_obj(cls._find(data, "token")),
|
||||
user_model=User._xml_ele_to_obj(cls._find(data, "user")))
|
||||
|
||||
def get_service(self, name):
|
||||
for service in self.service_catalog:
|
||||
if service.name == name:
|
||||
return service
|
||||
return None
|
||||
|
||||
|
||||
class Metadata(BaseIdentityModel):
|
||||
|
||||
@classmethod
|
||||
def _dict_to_obj(cls, data):
|
||||
return data
|
||||
|
||||
@classmethod
|
||||
def _xml_ele_to_obj(cls, data):
|
||||
return data.attrib
|
||||
|
||||
|
||||
class Tenant(BaseIdentityModel):
|
||||
def __init__(self, enabled=None, description=None, name=None, id_=None):
|
||||
super(Tenant, self).__init__(locals())
|
||||
|
||||
@classmethod
|
||||
def _xml_ele_to_obj(cls, data):
|
||||
description = data.findtext('description')
|
||||
return cls(
|
||||
name=data.attrib.get("name"),
|
||||
id_=data.attrib.get("id"),
|
||||
enabled=True if data.attrib.get('enabled') == "true" else False,
|
||||
description=description)
|
||||
|
||||
@classmethod
|
||||
def _dict_to_obj(cls, data_dict):
|
||||
return cls(description=data_dict.get('description'),
|
||||
enabled=data_dict.get('enabled'),
|
||||
id_=data_dict.get('id'),
|
||||
name=data_dict.get('name'))
|
||||
|
||||
|
||||
class Token(BaseIdentityModel):
|
||||
def __init__(self, id_=None, issued_at=None, expires=None, tenant=None):
|
||||
super(Token, self).__init__(locals())
|
||||
|
||||
@classmethod
|
||||
def _dict_to_obj(cls, data):
|
||||
return cls(id_=data.get('id'),
|
||||
expires=data.get('expires'),
|
||||
issued_at=data.get('issued_at'),
|
||||
tenant=Tenant._dict_to_obj(data.get('tenant')))
|
||||
|
||||
@classmethod
|
||||
def _xml_ele_to_obj(cls, data):
|
||||
return cls(id_=data.attrib.get('id'),
|
||||
expires=data.attrib.get('expires'),
|
||||
issued_at=data.attrib.get('issued_at'),
|
||||
tenant=Tenant._xml_ele_to_obj(data.find('tenant')))
|
||||
|
||||
|
||||
class User(BaseIdentityModel):
|
||||
def __init__(
|
||||
self, id_=None, name=None, username=None, roles=None):
|
||||
super(User, self).__init__(locals())
|
||||
|
||||
@classmethod
|
||||
def _dict_to_obj(cls, data):
|
||||
return cls(
|
||||
id_=data.get('id'),
|
||||
name=data.get('name'),
|
||||
username=data.get('username'),
|
||||
roles=cls._build_list_model(data, "roles", Role))
|
||||
|
||||
@classmethod
|
||||
def _xml_ele_to_obj(cls, data):
|
||||
return cls(
|
||||
id_=data.attrib.get('id'),
|
||||
name=data.attrib.get('name'),
|
||||
username=data.attrib.get('username'),
|
||||
roles=cls._build_list_model(
|
||||
cls._find(data, "roles"), "role", Role))
|
||||
|
||||
|
||||
class Service(BaseIdentityModel):
|
||||
def __init__(
|
||||
self, endpoints=None, name=None, type_=None):
|
||||
super(Service, self).__init__(locals())
|
||||
|
||||
@classmethod
|
||||
def _dict_to_obj(cls, data):
|
||||
return cls(
|
||||
endpoints=cls._build_list_model(data, "endpoints", Endpoint),
|
||||
name=data.get("name"), type_=data.get("type"))
|
||||
|
||||
@classmethod
|
||||
def _xml_ele_to_obj(cls, data):
|
||||
return cls(
|
||||
endpoints=cls._build_list_model(data, "endpoint", Endpoint),
|
||||
name=data.attrib.get("name"), type_=data.attrib.get("type"))
|
||||
|
||||
|
||||
class Endpoint(BaseIdentityModel):
|
||||
def __init__(
|
||||
self, region=None, id_=None, public_url=None, admin_url=None,
|
||||
internal_url=None, private_url=None, version_id=None,
|
||||
version_info=None, version_list=None):
|
||||
super(Endpoint, self).__init__(locals())
|
||||
|
||||
@classmethod
|
||||
def _dict_to_obj(cls, data):
|
||||
return cls(region=data.get('region'),
|
||||
id_=data.get('Id'),
|
||||
public_url=data.get('publicURL'),
|
||||
private_url=data.get('privateURL'),
|
||||
admin_url=data.get('adminURL'),
|
||||
internal_url=data.get('internalURL'),
|
||||
version_id=data.get('versionId'),
|
||||
version_info=data.get('versionInfo'),
|
||||
version_list=data.get('versionList'))
|
||||
|
||||
@classmethod
|
||||
def _xml_ele_to_obj(cls, ele):
|
||||
return cls(region=ele.attrib.get('region'),
|
||||
id_=ele.attrib.get('Id'),
|
||||
public_url=ele.attrib.get('publicURL'),
|
||||
private_url=ele.attrib.get('privateURL'),
|
||||
admin_url=ele.attrib.get('adminURL'),
|
||||
internal_url=ele.attrib.get('internalURL'),
|
||||
version_id=ele.attrib.get('versionId'),
|
||||
version_info=ele.attrib.get('versionInfo'),
|
||||
version_list=ele.attrib.get('versionList'))
|
||||
|
||||
|
||||
class Role(BaseIdentityModel):
|
||||
def __init__(
|
||||
self, id_=None, name=None, description=None,
|
||||
tenant_id=None, service_id=None):
|
||||
super(Role, self).__init__(locals())
|
||||
|
||||
@classmethod
|
||||
def _xml_ele_to_obj(cls, element):
|
||||
if element is None:
|
||||
return None
|
||||
return cls(
|
||||
id_=element.attrib.get("id"),
|
||||
name=element.attrib.get("name"),
|
||||
description=element.attrib.get("description"))
|
||||
|
||||
@classmethod
|
||||
def _dict_to_obj(cls, data):
|
||||
if data is None:
|
||||
return None
|
||||
return cls(
|
||||
id_=data.get("id"),
|
||||
name=data.get("name"),
|
||||
description=data.get("description"))
|
||||
|
||||
|
||||
class Auth(BaseIdentityModel):
|
||||
def __init__(
|
||||
self, password_creds=None, tenant_id=None, tenant_name=None):
|
||||
super(Auth, self).__init__(locals())
|
||||
|
||||
def _obj_to_dict(self):
|
||||
dic = {}
|
||||
dic["passwordCredentials"] = self._get_sub_model(
|
||||
self.password_creds)
|
||||
dic["tenantId"] = self.tenant_id
|
||||
dic["tenantName"] = self.tenant_name
|
||||
return {"auth": self._remove_empty_values(dic)}
|
||||
|
||||
def _obj_to_xml_ele(self):
|
||||
ele = ET.Element("auth")
|
||||
ele.append(self._get_sub_model(self.password_creds, False))
|
||||
ele.attrib["tenantId"] = self.tenant_id
|
||||
return self._remove_empty_values(ele)
|
||||
|
||||
|
||||
class PasswordCredentials(BaseIdentityModel):
|
||||
def __init__(self, username=None, password=None):
|
||||
super(PasswordCredentials, self).__init__(locals())
|
||||
|
||||
def _obj_to_dict(self):
|
||||
dic = {"username": self.username, "password": self.password}
|
||||
return self._remove_empty_values(dic)
|
||||
|
||||
def _obj_to_xml_ele(self):
|
||||
ele = ET.Element("passwordCredentials")
|
||||
ele.attrib["username"] = self.username
|
||||
ele.attrib["password"] = self.password
|
||||
return self._remove_empty_values(ele)
|
|
@ -0,0 +1,98 @@
|
|||
"""
|
||||
Copyright 2015 Rackspace
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
from syntribos.extensions.identity.models.base import BaseIdentityModel
|
||||
|
||||
|
||||
class Auth(BaseIdentityModel):
|
||||
def __init__(
|
||||
self, identity=None, scope=None):
|
||||
super(Auth, self).__init__(locals())
|
||||
|
||||
def _obj_to_dict(self):
|
||||
return {"auth": self._remove_empty_values({
|
||||
"identity": self._get_sub_model(self.identity),
|
||||
"scope": self._get_sub_model(self.scope)})}
|
||||
|
||||
|
||||
class Identity(BaseIdentityModel):
|
||||
def __init__(self, token=None, password=None, methods=None):
|
||||
super(Identity, self).__init__(locals())
|
||||
|
||||
def _obj_to_dict(self):
|
||||
return self._remove_empty_values({
|
||||
"methods": self.methods or [],
|
||||
"password": self._get_sub_model(self.password),
|
||||
"token": self._get_sub_model(self.token)})
|
||||
|
||||
|
||||
class Password(BaseIdentityModel):
|
||||
def __init__(self, user=None):
|
||||
super(Password, self).__init__(locals())
|
||||
|
||||
def _obj_to_dict(self):
|
||||
return self._remove_empty_values({
|
||||
"user": self._get_sub_model(self.user)})
|
||||
|
||||
|
||||
class User(BaseIdentityModel):
|
||||
def __init__(self, id_=None, password=None, name=None, domain=None):
|
||||
super(User, self).__init__(locals())
|
||||
|
||||
def _obj_to_dict(self):
|
||||
return self._remove_empty_values({
|
||||
"id": self.id_,
|
||||
"password": self.password,
|
||||
"name": self.name,
|
||||
"domain": self._get_sub_model(self.domain)})
|
||||
|
||||
|
||||
class Token(BaseIdentityModel):
|
||||
def __init__(self, id_=None):
|
||||
super(Token, self).__init__(locals())
|
||||
|
||||
def _obj_to_dict(self):
|
||||
return self._remove_empty_values({"id": self.id_})
|
||||
|
||||
|
||||
class Scope(BaseIdentityModel):
|
||||
def __init__(self, project=None, domain=None):
|
||||
super(Scope, self).__init__(locals())
|
||||
|
||||
def _obj_to_dict(self):
|
||||
return self._remove_empty_values({
|
||||
"project": self._get_sub_model(self.project),
|
||||
"domain": self._get_sub_model(self.domain)})
|
||||
|
||||
|
||||
class Domain(BaseIdentityModel):
|
||||
def __init__(self, name=None, id_=None):
|
||||
super(Domain, self).__init__(locals())
|
||||
|
||||
def _obj_to_dict(self):
|
||||
return self._remove_empty_values({
|
||||
"name": self.name,
|
||||
"id": self.id_})
|
||||
|
||||
|
||||
class Project(Domain):
|
||||
def __init__(self, name=None, id_=None, domain=None):
|
||||
super(Project, self).__init__(locals())
|
||||
|
||||
def _obj_to_dict(self):
|
||||
return self._remove_empty_values({
|
||||
"name": self.name,
|
||||
"id": self.id_,
|
||||
"domain": self._get_sub_model(self.domain)})
|
Loading…
Reference in New Issue