summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--keystone_tempest_plugin/README.rst9
-rw-r--r--keystone_tempest_plugin/__init__.py0
-rw-r--r--keystone_tempest_plugin/clients.py42
-rw-r--r--keystone_tempest_plugin/config.py61
-rw-r--r--keystone_tempest_plugin/plugin.py43
-rw-r--r--keystone_tempest_plugin/services/__init__.py0
-rw-r--r--keystone_tempest_plugin/services/identity/__init__.py0
-rw-r--r--keystone_tempest_plugin/services/identity/clients.py78
-rw-r--r--keystone_tempest_plugin/services/identity/v3/__init__.py0
-rw-r--r--keystone_tempest_plugin/services/identity/v3/auth_client.py40
-rw-r--r--keystone_tempest_plugin/services/identity/v3/identity_providers_client.py102
-rw-r--r--keystone_tempest_plugin/services/identity/v3/mapping_rules_client.py44
-rw-r--r--keystone_tempest_plugin/services/identity/v3/saml2_client.py92
-rw-r--r--keystone_tempest_plugin/services/identity/v3/service_providers_client.py73
-rw-r--r--keystone_tempest_plugin/tests/__init__.py0
-rw-r--r--keystone_tempest_plugin/tests/api/__init__.py0
-rw-r--r--keystone_tempest_plugin/tests/api/identity/__init__.py0
-rw-r--r--keystone_tempest_plugin/tests/api/identity/v3/__init__.py0
-rw-r--r--keystone_tempest_plugin/tests/api/identity/v3/fixtures.py67
-rw-r--r--keystone_tempest_plugin/tests/api/identity/v3/test_identity_providers.py244
-rw-r--r--keystone_tempest_plugin/tests/api/identity/v3/test_mapping_rules.py102
-rw-r--r--keystone_tempest_plugin/tests/api/identity/v3/test_service_providers.py206
-rw-r--r--keystone_tempest_plugin/tests/base.py41
-rw-r--r--keystone_tempest_plugin/tests/scenario/__init__.py0
-rw-r--r--keystone_tempest_plugin/tests/scenario/test_federated_authentication.py176
-rw-r--r--setup.cfg8
26 files changed, 4 insertions, 1424 deletions
diff --git a/keystone_tempest_plugin/README.rst b/keystone_tempest_plugin/README.rst
index c880e28..1f310e5 100644
--- a/keystone_tempest_plugin/README.rst
+++ b/keystone_tempest_plugin/README.rst
@@ -1,6 +1,5 @@
1========================== 1=====
2Tempest tests for keystone 2MOVED
3========================== 3=====
4
5This directory contains Tempest tests to cover the keystone project.
6 4
5The keystone tempest plugin has moved to http://git.openstack.org/cgit/openstack/keystone-tempest-plugin
diff --git a/keystone_tempest_plugin/__init__.py b/keystone_tempest_plugin/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/keystone_tempest_plugin/__init__.py
+++ /dev/null
diff --git a/keystone_tempest_plugin/clients.py b/keystone_tempest_plugin/clients.py
deleted file mode 100644
index 97b5b14..0000000
--- a/keystone_tempest_plugin/clients.py
+++ /dev/null
@@ -1,42 +0,0 @@
1# Copyright 2016 Red Hat, Inc.
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15from keystone_tempest_plugin.services.identity.v3 import (
16 identity_providers_client)
17from keystone_tempest_plugin.services.identity.v3 import (
18 mapping_rules_client)
19from keystone_tempest_plugin.services.identity.v3 import (
20 service_providers_client)
21from keystone_tempest_plugin.services.identity.v3 import auth_client
22from keystone_tempest_plugin.services.identity.v3 import saml2_client
23
24from tempest import clients
25
26
27class Manager(clients.Manager):
28
29 def __init__(self, credentials):
30 super(Manager, self).__init__(credentials)
31
32 self.auth_client = auth_client.AuthClient(self.auth_provider)
33 self.identity_providers_client = (
34 identity_providers_client.IdentityProvidersClient(
35 self.auth_provider))
36 self.mapping_rules_client = (
37 mapping_rules_client.MappingRulesClient(
38 self.auth_provider))
39 self.saml2_client = saml2_client.Saml2Client()
40 self.service_providers_client = (
41 service_providers_client.ServiceProvidersClient(
42 self.auth_provider))
diff --git a/keystone_tempest_plugin/config.py b/keystone_tempest_plugin/config.py
deleted file mode 100644
index 87872c5..0000000
--- a/keystone_tempest_plugin/config.py
+++ /dev/null
@@ -1,61 +0,0 @@
1# Copyright 2016 Red Hat, Inc.
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16from oslo_config import cfg
17
18identity_feature_option = [
19 cfg.BoolOpt('federation',
20 default=False,
21 help='Does the environment support the Federated Identity '
22 'feature?'),
23]
24
25fed_scenario_group = cfg.OptGroup(name='fed_scenario',
26 title='Federation Scenario Tests Options')
27
28FedScenarioGroup = [
29 # Identity Provider
30 cfg.StrOpt('idp_id',
31 help='The Identity Provider ID'),
32 cfg.ListOpt('idp_remote_ids',
33 default=[],
34 help='The Identity Provider remote IDs list'),
35 cfg.StrOpt('idp_username',
36 help='Username used to login in the Identity Provider'),
37 cfg.StrOpt('idp_password',
38 help='Password used to login in the Identity Provider'),
39 cfg.StrOpt('idp_ecp_url',
40 help='Identity Provider SAML2/ECP URL'),
41
42 # Mapping rules
43 cfg.StrOpt('mapping_remote_type',
44 help='The assertion attribute to be used in the remote rules'),
45 cfg.StrOpt('mapping_user_name',
46 default='{0}',
47 help='The username to be used in the local rules.'),
48 cfg.StrOpt('mapping_group_name',
49 default='federated_users',
50 help='The group name to be used in the local rules. The group '
51 'must have at least one assignment in one project.'),
52 cfg.StrOpt('mapping_group_domain_name',
53 default='federated_domain',
54 help='The domain name where the "mapping_group_name" is '
55 'created.'),
56
57 # Protocol
58 cfg.StrOpt('protocol_id',
59 default='mapped',
60 help='The Protocol ID')
61]
diff --git a/keystone_tempest_plugin/plugin.py b/keystone_tempest_plugin/plugin.py
deleted file mode 100644
index 76f7a9c..0000000
--- a/keystone_tempest_plugin/plugin.py
+++ /dev/null
@@ -1,43 +0,0 @@
1# Copyright 2016 Red Hat, Inc.
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16
17import os
18
19from tempest import config
20from tempest.test_discover import plugins
21
22from keystone_tempest_plugin import config as project_config
23
24
25class KeystoneTempestPlugin(plugins.TempestPlugin):
26 def load_tests(self):
27 base_path = os.path.split(os.path.dirname(
28 os.path.abspath(__file__)))[0]
29 test_dir = "keystone_tempest_plugin/tests"
30 full_test_dir = os.path.join(base_path, test_dir)
31 return full_test_dir, base_path
32
33 def register_opts(self, conf):
34 config.register_opt_group(conf, config.identity_feature_group,
35 project_config.identity_feature_option)
36 config.register_opt_group(conf, project_config.fed_scenario_group,
37 project_config.FedScenarioGroup)
38
39 def get_opt_lists(self):
40 return [(config.identity_feature_group.name,
41 project_config.identity_feature_option),
42 (project_config.fed_scenario_group.name,
43 project_config.FedScenarioGroup)]
diff --git a/keystone_tempest_plugin/services/__init__.py b/keystone_tempest_plugin/services/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/keystone_tempest_plugin/services/__init__.py
+++ /dev/null
diff --git a/keystone_tempest_plugin/services/identity/__init__.py b/keystone_tempest_plugin/services/identity/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/keystone_tempest_plugin/services/identity/__init__.py
+++ /dev/null
diff --git a/keystone_tempest_plugin/services/identity/clients.py b/keystone_tempest_plugin/services/identity/clients.py
deleted file mode 100644
index aac45d3..0000000
--- a/keystone_tempest_plugin/services/identity/clients.py
+++ /dev/null
@@ -1,78 +0,0 @@
1# Copyright 2016 Red Hat, Inc.
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15import json
16
17import six
18from six.moves import http_client
19from tempest import config
20from tempest.lib.common import rest_client
21
22
23CONF = config.CONF
24
25# We only use the identity catalog type
26SERVICE_TYPE = 'identity'
27
28
29class Identity(rest_client.RestClient):
30 """Tempest REST client for keystone."""
31
32 # Used by the superclass to build the correct URL paths
33 api_version = 'v3'
34
35 def __init__(self, auth_provider):
36 super(Identity, self).__init__(
37 auth_provider,
38 SERVICE_TYPE,
39 CONF.identity.region,
40 endpoint_type='adminURL')
41
42
43class Federation(Identity):
44 """Tempest REST client for keystone's Federated Identity API."""
45
46 subpath_prefix = 'OS-FEDERATION'
47 subpath_suffix = None
48
49 def _build_path(self, entity_id=None):
50 subpath = '%s/%s' % (self.subpath_prefix, self.subpath_suffix)
51 return '%s/%s' % (subpath, entity_id) if entity_id else subpath
52
53 def _delete(self, entity_id, **kwargs):
54 url = self._build_path(entity_id)
55 resp, body = super(Federation, self).delete(url, **kwargs)
56 self.expected_success(http_client.NO_CONTENT, resp.status)
57 return rest_client.ResponseBody(resp, body)
58
59 def _get(self, entity_id=None, **kwargs):
60 url = self._build_path(entity_id)
61 resp, body = super(Federation, self).get(url, **kwargs)
62 self.expected_success(http_client.OK, resp.status)
63 body = json.loads(body if six.PY2 else body.decode('utf-8'))
64 return rest_client.ResponseBody(resp, body)
65
66 def _patch(self, entity_id, body, **kwargs):
67 url = self._build_path(entity_id)
68 resp, body = super(Federation, self).patch(url, body, **kwargs)
69 self.expected_success(http_client.OK, resp.status)
70 body = json.loads(body if six.PY2 else body.decode('utf-8'))
71 return rest_client.ResponseBody(resp, body)
72
73 def _put(self, entity_id, body, **kwargs):
74 url = self._build_path(entity_id)
75 resp, body = super(Federation, self).put(url, body, **kwargs)
76 self.expected_success(http_client.CREATED, resp.status)
77 body = json.loads(body if six.PY2 else body.decode('utf-8'))
78 return rest_client.ResponseBody(resp, body)
diff --git a/keystone_tempest_plugin/services/identity/v3/__init__.py b/keystone_tempest_plugin/services/identity/v3/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/keystone_tempest_plugin/services/identity/v3/__init__.py
+++ /dev/null
diff --git a/keystone_tempest_plugin/services/identity/v3/auth_client.py b/keystone_tempest_plugin/services/identity/v3/auth_client.py
deleted file mode 100644
index f6cd660..0000000
--- a/keystone_tempest_plugin/services/identity/v3/auth_client.py
+++ /dev/null
@@ -1,40 +0,0 @@
1# Copyright 2016 Red Hat, Inc.
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15import json
16
17import six
18from tempest.lib.common import rest_client
19
20from keystone_tempest_plugin.services.identity import clients
21
22
23class AuthClient(clients.Identity):
24
25 def _get_scopes(self, url, token_id):
26 resp, body = self.raw_request(
27 url, 'GET', headers={'X-Auth-Token': token_id})
28 self.expected_success(200, resp.status)
29 body = json.loads(body if six.PY2 else body.decode('utf-8'))
30 return rest_client.ResponseBody(resp, body)
31
32 def get_available_projects_scopes(self, keystone_v3_endpoint, token_id):
33 """Get projects that are available to be scoped to based on a token."""
34 url = '%s/auth/projects' % keystone_v3_endpoint
35 return self._get_scopes(url, token_id)
36
37 def get_available_domains_scopes(self, keystone_v3_endpoint, token_id):
38 """Get domains that are available to be scoped to based on a token."""
39 url = '%s/auth/domains' % keystone_v3_endpoint
40 return self._get_scopes(url, token_id)
diff --git a/keystone_tempest_plugin/services/identity/v3/identity_providers_client.py b/keystone_tempest_plugin/services/identity/v3/identity_providers_client.py
deleted file mode 100644
index 98f49c7..0000000
--- a/keystone_tempest_plugin/services/identity/v3/identity_providers_client.py
+++ /dev/null
@@ -1,102 +0,0 @@
1# Copyright 2016 Red Hat, Inc.
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15import json
16
17import six
18from tempest.lib.common import rest_client
19
20from keystone_tempest_plugin.services.identity import clients
21
22
23class IdentityProvidersClient(clients.Federation):
24
25 subpath_suffix = 'identity_providers'
26
27 def create_identity_provider(self, idp_id, **kwargs):
28 """Create an identity provider.
29
30 :param str idp_id: The ID to be used to create the Identity Provider.
31 :param kwargs: All optional attributes: description (str), enabled
32 (boolean) and remote_ids (list).
33 """
34 put_body = json.dumps({'identity_provider': kwargs})
35 return self._put(idp_id, put_body)
36
37 def list_identity_providers(self):
38 """List the identity providers."""
39 return self._get()
40
41 def show_identity_provider(self, idp_id):
42 """Get an identity provider."""
43 return self._get(idp_id)
44
45 def delete_identity_provider(self, idp_id):
46 """Delete an identity provider."""
47 return self._delete(idp_id)
48
49 def update_identity_provider(self, idp_id, **kwargs):
50 """Update an identity provider.
51
52 :param str idp_id: The ID from the Identity Provider to be updated.
53 :param kwargs: All optional attributes to update: description (str),
54 enabled (boolean) and remote_ids (list).
55 """
56 patch_body = json.dumps({'identity_provider': kwargs})
57 return self._patch(idp_id, patch_body)
58
59 def add_protocol_and_mapping(self, idp_id, protocol_id, mapping_id):
60 """Add a protocol and mapping to an identity provider."""
61 put_body = json.dumps({'protocol': {'mapping_id': mapping_id}})
62 url = '%s/%s/%s' % (
63 self._build_path(entity_id=idp_id), 'protocols', protocol_id)
64 resp, body = self.put(url, put_body)
65 self.expected_success(201, resp.status)
66 body = json.loads(body if six.PY2 else body.decode('utf-8'))
67 return rest_client.ResponseBody(resp, body)
68
69 def delete_protocol_and_mapping(self, idp_id, protocol_id):
70 """Delete a protocol and mapping from an identity provider."""
71 url = '%s/%s/%s' % (
72 self._build_path(entity_id=idp_id), 'protocols', protocol_id)
73 resp, body = self.delete(url)
74 self.expected_success(204, resp.status)
75 return rest_client.ResponseBody(resp, body)
76
77 def get_protocol_and_mapping(self, idp_id, protocol_id):
78 """Get a protocol and mapping from an identity provider."""
79 url = '%s/%s/%s' % (
80 self._build_path(entity_id=idp_id), 'protocols', protocol_id)
81 resp, body = self.get(url)
82 self.expected_success(200, resp.status)
83 body = json.loads(body if six.PY2 else body.decode('utf-8'))
84 return rest_client.ResponseBody(resp, body)
85
86 def list_protocols_and_mappings(self, idp_id):
87 """List the protocols and mappings from an identity provider."""
88 url = '%s/%s' % (self._build_path(entity_id=idp_id), 'protocols')
89 resp, body = self.get(url)
90 self.expected_success(200, resp.status)
91 body = json.loads(body if six.PY2 else body.decode('utf-8'))
92 return rest_client.ResponseBody(resp, body)
93
94 def update_protocol_mapping(self, idp_id, protocol_id, mapping_id):
95 """Update the identity provider protocol with a new mapping."""
96 patch_body = json.dumps({'protocol': {'mapping_id': mapping_id}})
97 url = '%s/%s/%s' % (
98 self._build_path(entity_id=idp_id), 'protocols', protocol_id)
99 resp, body = self.patch(url, patch_body)
100 self.expected_success(200, resp.status)
101 body = json.loads(body if six.PY2 else body.decode('utf-8'))
102 return rest_client.ResponseBody(resp, body)
diff --git a/keystone_tempest_plugin/services/identity/v3/mapping_rules_client.py b/keystone_tempest_plugin/services/identity/v3/mapping_rules_client.py
deleted file mode 100644
index b7fcbd7..0000000
--- a/keystone_tempest_plugin/services/identity/v3/mapping_rules_client.py
+++ /dev/null
@@ -1,44 +0,0 @@
1# Copyright 2016 Red Hat, Inc.
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15import json
16
17from keystone_tempest_plugin.services.identity import clients
18
19
20class MappingRulesClient(clients.Federation):
21
22 subpath_suffix = 'mappings'
23
24 def create_mapping_rule(self, mapping_id, rules):
25 """Create a mapping rule."""
26 put_body = json.dumps({'mapping': rules})
27 return self._put(mapping_id, put_body)
28
29 def list_mapping_rules(self):
30 """List the mapping rules."""
31 return self._get()
32
33 def show_mapping_rule(self, mapping_id):
34 """Get a mapping rule."""
35 return self._get(mapping_id)
36
37 def delete_mapping_rule(self, mapping_id):
38 """Delete a mapping rule."""
39 return self._delete(mapping_id)
40
41 def update_mapping_rule(self, mapping_id, rules):
42 """Update a mapping rule."""
43 patch_body = json.dumps({'mapping': rules})
44 return self._patch(mapping_id, patch_body)
diff --git a/keystone_tempest_plugin/services/identity/v3/saml2_client.py b/keystone_tempest_plugin/services/identity/v3/saml2_client.py
deleted file mode 100644
index b70a389..0000000
--- a/keystone_tempest_plugin/services/identity/v3/saml2_client.py
+++ /dev/null
@@ -1,92 +0,0 @@
1# Copyright 2016 Red Hat, Inc.
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15from lxml import etree
16import requests
17
18
19class Saml2Client(object):
20
21 ECP_SP_EMPTY_REQUEST_HEADERS = {
22 'Accept': 'text/html, application/vnd.paos+xml',
23 'PAOS': ('ver="urn:liberty:paos:2003-08";"urn:oasis:names:tc:'
24 'SAML:2.0:profiles:SSO:ecp"')
25 }
26
27 ECP_SP_SAML2_REQUEST_HEADERS = {'Content-Type': 'application/vnd.paos+xml'}
28
29 def __init__(self):
30 self.reset_session()
31
32 def reset_session(self):
33 self.session = requests.Session()
34
35 def _idp_auth_url(self, keystone_v3_endpoint, idp_id, protocol_id):
36 subpath = 'OS-FEDERATION/identity_providers/%s/protocols/%s/auth' % (
37 idp_id, protocol_id)
38 return '%s/%s' % (keystone_v3_endpoint, subpath)
39
40 def send_service_provider_request(self, keystone_v3_endpoint,
41 idp_id, protocol_id):
42 return self.session.get(
43 self._idp_auth_url(keystone_v3_endpoint, idp_id, protocol_id),
44 headers=self.ECP_SP_EMPTY_REQUEST_HEADERS
45 )
46
47 def _prepare_sp_saml2_authn_response(self, saml2_idp_authn_response,
48 relay_state):
49 # Replace the header contents of the Identity Provider response with
50 # the relay state initially sent by the Service Provider. The response
51 # is a SOAP envelope with the following structure:
52 #
53 # <S:Envelope
54 # <S:Header>
55 # ...
56 # </S:Header>
57 # <S:Body>
58 # ...
59 # </S:Body>
60 # </S:Envelope>
61 saml2_idp_authn_response[0][0] = relay_state
62
63 def send_identity_provider_authn_request(self, saml2_authn_request,
64 idp_url, username, password):
65
66 saml2_authn_request.remove(saml2_authn_request[0])
67 return self.session.post(
68 idp_url,
69 headers={'Content-Type': 'text/xml'},
70 data=etree.tostring(saml2_authn_request),
71 auth=(username, password)
72 )
73
74 def send_service_provider_saml2_authn_response(
75 self, saml2_idp_authn_response, relay_state, idp_consumer_url):
76
77 self._prepare_sp_saml2_authn_response(
78 saml2_idp_authn_response, relay_state)
79
80 return self.session.post(
81 idp_consumer_url,
82 headers=self.ECP_SP_SAML2_REQUEST_HEADERS,
83 data=etree.tostring(saml2_idp_authn_response),
84 # Do not follow HTTP redirect
85 allow_redirects=False
86 )
87
88 def send_service_provider_unscoped_token_request(self, sp_url):
89 return self.session.get(
90 sp_url,
91 headers=self.ECP_SP_SAML2_REQUEST_HEADERS
92 )
diff --git a/keystone_tempest_plugin/services/identity/v3/service_providers_client.py b/keystone_tempest_plugin/services/identity/v3/service_providers_client.py
deleted file mode 100644
index 093ce0f..0000000
--- a/keystone_tempest_plugin/services/identity/v3/service_providers_client.py
+++ /dev/null
@@ -1,73 +0,0 @@
1# Copyright 2016 Red Hat, Inc.
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15import json
16
17from keystone_tempest_plugin.services.identity import clients
18
19
20class ServiceProvidersClient(clients.Federation):
21
22 subpath_suffix = 'service_providers'
23
24 def create_service_provider(self, sp_id, **kwargs):
25 """Create a service provider.
26
27 :param str sp_id: The ID to be used to create the Service Provider.
28 :param kwargs: Extra attributes. Mandatory: auth_url (str) and sp_url
29 (str). Optional: description (str), enabled (boolean)
30 and relay_state_prefix (str).
31 """
32 put_body = json.dumps({'service_provider': kwargs})
33 return self._put(sp_id, put_body)
34
35 def list_service_providers(self):
36 """List the service providers."""
37 return self._get()
38
39 def show_service_provider(self, sp_id):
40 """Get a service provider."""
41 return self._get(sp_id)
42
43 def delete_service_provider(self, sp_id):
44 """Delete a service provider."""
45 return self._delete(sp_id)
46
47 def update_service_provider(self, sp_id, **kwargs):
48 """Update a service provider.
49
50 :param str sp_id: The ID of the Service Provider to be updated.
51 :param kwargs: All attributes to be updated: auth_url (str) and sp_url
52 (str), description (str), enabled (boolean) and
53 relay_state_prefix (str).
54 """
55 patch_body = json.dumps({'service_provider': kwargs})
56 return self._patch(sp_id, patch_body)
57
58 def get_service_providers_in_token(self):
59 """Get the service providers list present in the token.
60
61 Only enabled service providers are displayed in the token.
62 """
63 # First we force the auth_data update via the set_auth() command
64 # in the auth_provider
65 self.auth_provider.set_auth()
66
67 # Now we can retrieve the updated auth_data
68 auth_data = self.auth_provider.get_auth()[1]
69 try:
70 return auth_data['service_providers']
71 except KeyError:
72 # no service providers in token
73 return []
diff --git a/keystone_tempest_plugin/tests/__init__.py b/keystone_tempest_plugin/tests/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/keystone_tempest_plugin/tests/__init__.py
+++ /dev/null
diff --git a/keystone_tempest_plugin/tests/api/__init__.py b/keystone_tempest_plugin/tests/api/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/keystone_tempest_plugin/tests/api/__init__.py
+++ /dev/null
diff --git a/keystone_tempest_plugin/tests/api/identity/__init__.py b/keystone_tempest_plugin/tests/api/identity/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/keystone_tempest_plugin/tests/api/identity/__init__.py
+++ /dev/null
diff --git a/keystone_tempest_plugin/tests/api/identity/v3/__init__.py b/keystone_tempest_plugin/tests/api/identity/v3/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/keystone_tempest_plugin/tests/api/identity/v3/__init__.py
+++ /dev/null
diff --git a/keystone_tempest_plugin/tests/api/identity/v3/fixtures.py b/keystone_tempest_plugin/tests/api/identity/v3/fixtures.py
deleted file mode 100644
index 4e5899c..0000000
--- a/keystone_tempest_plugin/tests/api/identity/v3/fixtures.py
+++ /dev/null
@@ -1,67 +0,0 @@
1# Copyright 2016 Red Hat, Inc.
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15from tempest.lib.common.utils import data_utils
16
17
18def idp_ref(enabled=None, remote_ids=None):
19 ref = {
20 'description': data_utils.rand_uuid_hex(),
21 }
22 if enabled is not None:
23 ref['enabled'] = enabled
24
25 if remote_ids:
26 ref['remote_ids'] = remote_ids
27
28 return ref
29
30
31def mapping_ref():
32 rules = [{
33 'local': [
34 {
35 'user': {'name': '{0}'}
36 },
37 {
38 'group_ids': '{1}'
39 }
40 ],
41 'remote': [
42 {
43 'type': 'openstack_username'
44 },
45 {
46 'type': 'group_ids',
47 'whitelist': ['abc', '123']
48 }
49
50 ]
51 }]
52 return {'rules': rules}
53
54
55def sp_ref(enabled=None, relay_state_prefix=None):
56 ref = {
57 'auth_url': data_utils.rand_url(),
58 'description': data_utils.rand_uuid_hex(),
59 'sp_url': data_utils.rand_url(),
60 }
61 if enabled:
62 ref['enabled'] = enabled
63
64 if relay_state_prefix:
65 ref['relay_state_prefix'] = relay_state_prefix
66
67 return ref
diff --git a/keystone_tempest_plugin/tests/api/identity/v3/test_identity_providers.py b/keystone_tempest_plugin/tests/api/identity/v3/test_identity_providers.py
deleted file mode 100644
index 6b8f6a8..0000000
--- a/keystone_tempest_plugin/tests/api/identity/v3/test_identity_providers.py
+++ /dev/null
@@ -1,244 +0,0 @@
1# Copyright 2016 Red Hat, Inc.
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15from tempest.lib.common.utils import data_utils
16from tempest.lib import decorators
17from tempest.lib import exceptions as lib_exc
18
19from keystone_tempest_plugin.tests.api.identity.v3 import fixtures
20from keystone_tempest_plugin.tests import base
21
22
23class IdentityProvidersTest(base.BaseIdentityTest):
24
25 def _assert_identity_provider_attributes(self, idp, idp_id, idp_ref=None):
26 self.assertIn('id', idp)
27 self.assertEqual(idp_id, idp['id'])
28
29 # Check the optional attributes have been set
30 self.assertIn('description', idp)
31 self.assertIn('enabled', idp)
32 self.assertIn('remote_ids', idp)
33
34 if idp_ref:
35 self.assertEqual(idp_ref['description'], idp['description'])
36
37 if 'enabled' in idp_ref:
38 self.assertEqual(idp_ref['enabled'], idp['enabled'])
39
40 if 'remote_ids' in idp_ref:
41 self.assertItemsEqual(idp_ref['remote_ids'], idp['remote_ids'])
42
43 def _create_idp(self, idp_id, idp_ref):
44 idp = self.idps_client.create_identity_provider(
45 idp_id, **idp_ref)['identity_provider']
46 self.addCleanup(
47 self.idps_client.delete_identity_provider, idp_id)
48 return idp
49
50 @decorators.idempotent_id('09450910-b816-4150-8513-a2fd4628a0c3')
51 def test_identity_provider_create(self):
52 idp_id = data_utils.rand_uuid_hex()
53 idp_ref = fixtures.idp_ref()
54 idp = self._create_idp(idp_id, idp_ref)
55
56 # The identity provider is disabled by default
57 idp_ref['enabled'] = False
58
59 # The remote_ids attribute should be set to an empty list by default
60 idp_ref['remote_ids'] = []
61
62 self._assert_identity_provider_attributes(idp, idp_id, idp_ref)
63
64 @decorators.idempotent_id('f430a337-545d-455e-bb6c-cb0fdf4be5c1')
65 def test_identity_provider_create_with_enabled_true(self):
66 idp_id = data_utils.rand_uuid_hex()
67 idp_ref = fixtures.idp_ref(enabled=True)
68 idp = self._create_idp(idp_id, idp_ref)
69
70 self._assert_identity_provider_attributes(idp, idp_id, idp_ref)
71
72 @decorators.idempotent_id('238e6163-d600-4f59-9982-c621f057221d')
73 def test_identity_provider_create_with_remote_ids(self):
74 idp_id = data_utils.rand_uuid_hex()
75 remote_ids = [data_utils.rand_uuid_hex(), data_utils.rand_uuid_hex()]
76 idp_ref = fixtures.idp_ref(remote_ids=remote_ids)
77 idp = self._create_idp(idp_id, idp_ref)
78
79 self._assert_identity_provider_attributes(idp, idp_id, idp_ref)
80
81 @decorators.idempotent_id('8a7817ad-27f8-436b-9cbe-46aa20989beb')
82 def test_identity_provider_get(self):
83 idp_id = data_utils.rand_uuid_hex()
84 idp_create = self._create_idp(idp_id, fixtures.idp_ref())
85
86 idp_get = self.idps_client.show_identity_provider(
87 idp_id)['identity_provider']
88 self._assert_identity_provider_attributes(idp_get, idp_id, idp_create)
89
90 @decorators.idempotent_id('cbfe5de9-c58a-4810-950c-2acdf985879d')
91 def test_identity_provider_list(self):
92 idp_ids = []
93 for _ in range(3):
94 idp_id = data_utils.rand_uuid_hex()
95 self._create_idp(idp_id, fixtures.idp_ref())
96 idp_ids.append(idp_id)
97
98 idp_list = self.idps_client.list_identity_providers()[
99 'identity_providers']
100 fetched_ids = [fetched_idp['id'] for fetched_idp in idp_list]
101
102 for idp_id in idp_ids:
103 self.assertIn(idp_id, fetched_ids)
104
105 @decorators.idempotent_id('36a0d9f0-9517-4139-85d0-f78d905aece5')
106 def test_identity_provider_update(self):
107 idp_id = data_utils.rand_uuid_hex()
108 idp = self._create_idp(idp_id, fixtures.idp_ref(enabled=True))
109
110 # The identity provider should be enabled
111 self.assertTrue(idp['enabled'])
112
113 idp = self.idps_client.update_identity_provider(
114 idp_id, enabled=False)['identity_provider']
115
116 # The identity provider should be disabled
117 self.assertFalse(idp['enabled'])
118
119 idp_get = self.idps_client.show_identity_provider(
120 idp_id)['identity_provider']
121 self.assertFalse(idp_get['enabled'])
122
123 def _assert_protocol_attributes(self, protocol, protocol_id,
124 mapping_id=None):
125 self.assertIn('id', protocol)
126 self.assertEqual(protocol_id, protocol['id'])
127
128 self.assertIn('mapping_id', protocol)
129 if mapping_id:
130 self.assertEqual(mapping_id, protocol['mapping_id'])
131
132 def _create_identity_provider_and_mapping(self):
133 # Create an identity provider
134 idp_id = data_utils.rand_uuid_hex()
135 self._create_idp(idp_id, fixtures.idp_ref(enabled=True))
136
137 # Create a mapping rule
138 mapping_id = data_utils.rand_uuid_hex()
139 self.mappings_client.create_mapping_rule(
140 mapping_id, fixtures.mapping_ref())
141 self.addCleanup(self.mappings_client.delete_mapping_rule, mapping_id)
142
143 return idp_id, mapping_id
144
145 def _create_protocol(self, idp_id, protocol_id, mapping_id):
146 protocol = self.idps_client.add_protocol_and_mapping(
147 idp_id, protocol_id, mapping_id)['protocol']
148 self.addCleanup(
149 self.idps_client.delete_protocol_and_mapping, idp_id, protocol_id)
150 return protocol
151
152 @decorators.idempotent_id('f5bdf482-1ad3-4aad-b52e-8fe7c1361104')
153 def test_add_protocol_to_identity_provider(self):
154 idp_id, mapping_id = self._create_identity_provider_and_mapping()
155
156 # Now we try to add a protocol to the identity provider
157 protocol_id = data_utils.rand_uuid_hex()
158 protocol = self._create_protocol(idp_id, protocol_id, mapping_id)
159
160 self._assert_protocol_attributes(protocol, protocol_id, mapping_id)
161
162 @decorators.idempotent_id('613d073b-0db7-41aa-b4df-5a1848cde0b3')
163 def test_get_protocol_from_identity_provider(self):
164 idp_id, mapping_id = self._create_identity_provider_and_mapping()
165
166 # Add a protocol to the identity provider
167 protocol_id = data_utils.rand_uuid_hex()
168 self._create_protocol(idp_id, protocol_id, mapping_id)
169
170 # Try to get the protocol
171 protocol = self.idps_client.get_protocol_and_mapping(
172 idp_id, protocol_id)['protocol']
173 self._assert_protocol_attributes(protocol, protocol_id, mapping_id)
174
175 @decorators.idempotent_id('6e6501ac-edae-4dc2-bb68-7a2b58602383')
176 def test_list_protocols_from_identity_provider(self):
177 idp_id, mapping_id = self._create_identity_provider_and_mapping()
178
179 protocol_ids = []
180 for _ in range(3):
181 protocol_id = data_utils.rand_uuid_hex()
182 self._create_protocol(idp_id, protocol_id, mapping_id)
183 protocol_ids.append(protocol_id)
184
185 protocols_list = self.idps_client.list_protocols_and_mappings(idp_id)[
186 'protocols']
187 fetched_ids = [fetched['id'] for fetched in protocols_list]
188
189 for protocol_id in protocol_ids:
190 self.assertIn(protocol_id, fetched_ids)
191
192 @decorators.idempotent_id('680d36df-d6b9-4695-be29-6fc2065c5dde')
193 def test_update_mapping_from_identity_provider_protocol(self):
194 idp_id, mapping_id = self._create_identity_provider_and_mapping()
195
196 # Add a protocol to the identity provider
197 protocol_id = data_utils.rand_uuid_hex()
198 protocol = self._create_protocol(idp_id, protocol_id, mapping_id)
199
200 # Create another mapping
201 new_mapping_id = data_utils.rand_uuid_hex()
202 self.mappings_client.create_mapping_rule(
203 new_mapping_id, fixtures.mapping_ref())
204
205 # Update the identity provider protocol
206 protocol = self.idps_client.update_protocol_mapping(
207 idp_id, protocol_id, new_mapping_id)['protocol']
208
209 self._assert_protocol_attributes(protocol, protocol_id, new_mapping_id)
210
211 @decorators.idempotent_id('04fdf262-af91-4a68-a1cf-794c6d2f2eeb')
212 def test_add_protocol_to_identity_provider_unknown_mapping(self):
213 # Create an identity provider
214 idp_id = data_utils.rand_uuid_hex()
215 self._create_idp(idp_id, fixtures.idp_ref(enabled=True))
216
217 # Now we try to add a protocol to the identity provider using
218 # a non existent mapping ID
219 mapping_id = data_utils.rand_uuid_hex()
220 protocol_id = data_utils.rand_uuid_hex()
221 self.assertRaises(
222 lib_exc.BadRequest,
223 self._create_protocol,
224 idp_id,
225 protocol_id,
226 mapping_id)
227
228 @decorators.idempotent_id('c73311e7-c207-4c11-998f-532a91f1b0d1')
229 def test_update_protocol_from_identity_provider_unknown_mapping(self):
230 idp_id, mapping_id = self._create_identity_provider_and_mapping()
231
232 # Add a protocol to the identity provider
233 protocol_id = data_utils.rand_uuid_hex()
234 self._create_protocol(idp_id, protocol_id, mapping_id)
235
236 # Update the identity provider protocol using a non existent
237 # mapping_id
238 new_mapping_id = data_utils.rand_uuid_hex()
239 self.assertRaises(
240 lib_exc.BadRequest,
241 self.idps_client.update_protocol_mapping,
242 idp_id,
243 protocol_id,
244 new_mapping_id)
diff --git a/keystone_tempest_plugin/tests/api/identity/v3/test_mapping_rules.py b/keystone_tempest_plugin/tests/api/identity/v3/test_mapping_rules.py
deleted file mode 100644
index 7fcf376..0000000
--- a/keystone_tempest_plugin/tests/api/identity/v3/test_mapping_rules.py
+++ /dev/null
@@ -1,102 +0,0 @@
1# Copyright 2016 Red Hat, Inc.
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15from tempest.lib.common.utils import data_utils
16from tempest.lib import decorators
17from tempest.lib import exceptions as lib_exc
18
19from keystone_tempest_plugin.tests.api.identity.v3 import fixtures
20from keystone_tempest_plugin.tests import base
21
22
23class MappingRulesTest(base.BaseIdentityTest):
24
25 _MAPPING_REF = fixtures.mapping_ref()
26
27 def _assert_mapping_rules_attributes(self, mapping, mapping_id,
28 mapping_ref=None):
29 self.assertIn('id', mapping)
30 self.assertEqual(mapping_id, mapping['id'])
31
32 self.assertIn('rules', mapping)
33
34 if mapping_ref:
35 self.assertItemsEqual(mapping_ref['rules'], mapping['rules'])
36
37 def _create_mapping_rule(self, mapping_id, mapping_ref):
38 mapping = self.mappings_client.create_mapping_rule(
39 mapping_id, mapping_ref)['mapping']
40 self.addCleanup(self.mappings_client.delete_mapping_rule, mapping_id)
41 return mapping
42
43 @decorators.idempotent_id('4ca48c01-b6da-4759-acb6-007e15ad712a')
44 def test_mapping_rules_create(self):
45 mapping_id = data_utils.rand_uuid_hex()
46 mapping = self._create_mapping_rule(mapping_id, self._MAPPING_REF)
47 self._assert_mapping_rules_attributes(
48 mapping, mapping_id, self._MAPPING_REF)
49
50 @decorators.attr(type=['negative'])
51 @decorators.idempotent_id('341dac45-ce1f-4f15-afdc-1f9a7d7d7c40')
52 def test_mapping_rules_create_without_mandatory_attributes_fails(self):
53 mapping_id = data_utils.rand_uuid_hex()
54 self.assertRaises(
55 lib_exc.BadRequest,
56 self.mappings_client.create_mapping_rule,
57 mapping_id,
58 {})
59
60 @decorators.idempotent_id('8db213e3-1db0-48c6-863c-7a3ed23577ec')
61 def test_mapping_rules_get(self):
62 mapping_id = data_utils.rand_uuid_hex()
63 mapping_create = self._create_mapping_rule(
64 mapping_id, self._MAPPING_REF)
65
66 mapping_get = self.mappings_client.show_mapping_rule(mapping_id)[
67 'mapping']
68 self._assert_mapping_rules_attributes(
69 mapping_get, mapping_id, mapping_create)
70
71 @decorators.idempotent_id('bb80b242-2a6a-4d29-b45f-4035be574a6e')
72 def test_mapping_rules_list(self):
73 mapping_ids = []
74 for _ in range(3):
75 mapping_id = data_utils.rand_uuid_hex()
76 self._create_mapping_rule(mapping_id, self._MAPPING_REF)
77 mapping_ids.append(mapping_id)
78
79 mappings_list = self.mappings_client.list_mapping_rules()['mappings']
80 fetched_ids = [mapping['id'] for mapping in mappings_list]
81
82 for mapping_id in mapping_ids:
83 self.assertIn(mapping_id, fetched_ids)
84
85 @decorators.idempotent_id('1fc5d104-faf5-4809-8c89-29b5c1666a96')
86 def test_mapping_rule_update(self):
87 mapping_id = data_utils.rand_uuid_hex()
88 mapping_ref = fixtures.mapping_ref()
89 mapping = self._create_mapping_rule(mapping_id, mapping_ref)
90
91 new_local = [{'group': {'id': data_utils.rand_uuid_hex()}}]
92 mapping_ref['rules'][0]['local'] = new_local
93
94 mapping = self.mappings_client.update_mapping_rule(
95 mapping_id, mapping_ref)['mapping']
96 self._assert_mapping_rules_attributes(
97 mapping, mapping_id, mapping_ref)
98
99 mapping_get = self.mappings_client.show_mapping_rule(mapping_id)[
100 'mapping']
101 self._assert_mapping_rules_attributes(
102 mapping_get, mapping_id, mapping)
diff --git a/keystone_tempest_plugin/tests/api/identity/v3/test_service_providers.py b/keystone_tempest_plugin/tests/api/identity/v3/test_service_providers.py
deleted file mode 100644
index a6522f9..0000000
--- a/keystone_tempest_plugin/tests/api/identity/v3/test_service_providers.py
+++ /dev/null
@@ -1,206 +0,0 @@
1# Copyright 2016 Red Hat, Inc.
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15from tempest.lib.common.utils import data_utils
16from tempest.lib import decorators
17from tempest.lib import exceptions as lib_exc
18
19from keystone_tempest_plugin.tests.api.identity.v3 import fixtures
20from keystone_tempest_plugin.tests import base
21
22DEFAULT_RELAY_STATE_PREFIX = 'ss:mem:'
23
24
25class ServiceProvidersTest(base.BaseIdentityTest):
26
27 def _assert_service_provider_attributes(self, sp, sp_id, sp_ref=None):
28 self.assertIn('id', sp)
29 self.assertEqual(sp_id, sp['id'])
30
31 self.assertIn('auth_url', sp)
32 self.assertIn('sp_url', sp)
33
34 # Check the optional attributes have been set
35 self.assertIn('description', sp)
36 self.assertIn('enabled', sp)
37 self.assertIn('relay_state_prefix', sp)
38
39 if sp_ref:
40 self.assertEqual(sp_ref['auth_url'], sp['auth_url'])
41 self.assertEqual(sp_ref['sp_url'], sp['sp_url'])
42 self.assertEqual(sp_ref['description'], sp['description'])
43
44 if 'enabled' in sp_ref:
45 self.assertEqual(sp_ref['enabled'], sp['enabled'])
46
47 if 'relay_state_prefix' in sp_ref:
48 self.assertEqual(
49 sp_ref['relay_state_prefix'], sp['relay_state_prefix'])
50
51 def _add_cleanup(self, sp_id):
52 self.addCleanup(
53 self.sps_client.delete_service_provider, sp_id)
54
55 def _create_sp(self, sp_id, sp_ref):
56 sp = self.sps_client.create_service_provider(
57 sp_id, **sp_ref)['service_provider']
58 self.addCleanup(self.sps_client.delete_service_provider, sp_id)
59 return sp
60
61 @decorators.idempotent_id('6fae0971-5acb-4559-ba25-96f1fd7e5385')
62 def test_service_provider_create(self):
63 sp_id = data_utils.rand_uuid_hex()
64 sp_ref = fixtures.sp_ref()
65 sp = self._create_sp(sp_id, sp_ref)
66
67 # The service provider is disabled by default
68 sp_ref['enabled'] = False
69
70 # The relay_state_prefix should have been set to the default value
71 sp_ref['relay_state_prefix'] = DEFAULT_RELAY_STATE_PREFIX
72
73 self._assert_service_provider_attributes(sp, sp_id, sp_ref)
74
75 @decorators.attr(type=['negative'])
76 @decorators.idempotent_id('d9d7454c-50b7-4966-aedb-b9d520a41409')
77 def test_service_provider_create_without_mandatory_attributes(self):
78 sp_id = data_utils.rand_uuid_hex()
79 self.assertRaises(
80 lib_exc.BadRequest,
81 self.sps_client.create_service_provider,
82 sp_id)
83
84 @decorators.attr(type=['negative'])
85 @decorators.idempotent_id('f77ed1c0-c428-44a7-9364-e8e4362c360a')
86 def test_service_provider_create_with_bad_attributes(self):
87 sp_id = data_utils.rand_uuid_hex()
88 sp_ref = fixtures.sp_ref()
89
90 # The auth_url must follow a URL regex
91 sp_ref['auth_url'] = data_utils.rand_uuid_hex()
92 self.assertRaises(
93 lib_exc.BadRequest,
94 self.sps_client.create_service_provider,
95 sp_id,
96 **sp_ref)
97
98 sp_ref = fixtures.sp_ref()
99
100 # The sp_url must follow a URL regex
101 sp_ref['sp_url'] = data_utils.rand_uuid_hex()
102 self.assertRaises(
103 lib_exc.BadRequest,
104 self.sps_client.create_service_provider,
105 sp_id,
106 **sp_ref)
107
108 @decorators.idempotent_id('8550b419-f212-4e34-a8fa-7ff64f8a7fd3')
109 def test_service_provider_create_with_enabled_true(self):
110 sp_id = data_utils.rand_uuid_hex()
111 sp_ref = fixtures.sp_ref(enabled=True)
112 sp = self._create_sp(sp_id, sp_ref)
113
114 self._assert_service_provider_attributes(sp, sp_id, sp_ref)
115
116 @decorators.idempotent_id('0e319a14-1548-474e-a406-273c6b1c1f2d')
117 def test_service_provider_create_with_relay_state_prefix(self):
118 sp_id = data_utils.rand_uuid_hex()
119 sp_ref = fixtures.sp_ref(
120 enabled=True, relay_state_prefix=data_utils.rand_uuid_hex())
121 sp = self._create_sp(sp_id, sp_ref)
122
123 self._assert_service_provider_attributes(sp, sp_id, sp_ref)
124
125 @decorators.idempotent_id('7df78c7a-9265-4b4f-9630-193b7f07d9eb')
126 def test_service_provider_get(self):
127 sp_id = data_utils.rand_uuid_hex()
128 sp_create = self._create_sp(sp_id, fixtures.sp_ref())
129
130 sp_get = self.sps_client.show_service_provider(sp_id)[
131 'service_provider']
132
133 self._assert_service_provider_attributes(sp_get, sp_id, sp_create)
134
135 @decorators.idempotent_id('9237cea0-fbeb-4d64-8347-46c567e1d78f')
136 def test_service_provider_list(self):
137 sp_ids = []
138 for _ in range(3):
139 sp_id = data_utils.rand_uuid_hex()
140 self._create_sp(sp_id, fixtures.sp_ref())
141 sp_ids.append(sp_id)
142
143 sp_list = self.sps_client.list_service_providers()['service_providers']
144 fetched_ids = [fetched_sp['id'] for fetched_sp in sp_list]
145
146 for sp_id in sp_ids:
147 self.assertIn(sp_id, fetched_ids)
148
149 @decorators.idempotent_id('bb68653f-fbba-4f20-ac1b-7b318a557366')
150 def test_service_provider_update(self):
151 sp_id = data_utils.rand_uuid_hex()
152 sp = self._create_sp(sp_id, fixtures.sp_ref(enabled=True))
153
154 # The service provider should be enabled
155 self.assertTrue(sp['enabled'])
156
157 sp = self.sps_client.update_service_provider(
158 sp_id, enabled=False)['service_provider']
159
160 # The service provider should be now disabled
161 self.assertFalse(sp['enabled'])
162
163 sp_get = self.sps_client.show_service_provider(sp_id)[
164 'service_provider']
165 self.assertFalse(sp_get['enabled'])
166
167 @decorators.attr(type=['negative'])
168 @decorators.idempotent_id('91ce1183-1a15-4598-ae5f-85cfa98a1c77')
169 def test_service_provider_update_with_bad_attributes_fails(self):
170 sp_id = data_utils.rand_uuid_hex()
171 self._create_sp(sp_id, fixtures.sp_ref())
172
173 # The auth_url must follow a URL regex
174 self.assertRaises(
175 lib_exc.BadRequest,
176 self.sps_client.update_service_provider,
177 sp_id,
178 auth_url=data_utils.rand_uuid_hex())
179
180 # The sp_url must follow a URL regex
181 self.assertRaises(
182 lib_exc.BadRequest,
183 self.sps_client.update_service_provider,
184 sp_id,
185 auth_url=data_utils.rand_uuid_hex())
186
187 @decorators.idempotent_id('7553579b-9a9e-45dd-9ada-70d906b516c0')
188 def test_service_providers_in_token(self):
189 # Create some enabled service providers
190 enabled_sps = []
191 for _ in range(2):
192 sp_id = data_utils.rand_uuid_hex()
193 self._create_sp(sp_id, fixtures.sp_ref(enabled=True))
194 enabled_sps.append(sp_id)
195
196 # Create some disabled service providers
197 for _ in range(2):
198 sp_id = data_utils.rand_uuid_hex()
199 self._create_sp(sp_id, fixtures.sp_ref(enabled=False))
200
201 sps_in_token_ids = [
202 sp['id'] for sp in
203 self.sps_client.get_service_providers_in_token()]
204
205 # Should be equal to the enabled_sps list
206 self.assertItemsEqual(enabled_sps, sps_in_token_ids)
diff --git a/keystone_tempest_plugin/tests/base.py b/keystone_tempest_plugin/tests/base.py
deleted file mode 100644
index 6ba6659..0000000
--- a/keystone_tempest_plugin/tests/base.py
+++ /dev/null
@@ -1,41 +0,0 @@
1# Copyright 2016 Red Hat, Inc.
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15from tempest.common import credentials_factory as common_creds
16from tempest import test
17
18from keystone_tempest_plugin import clients
19
20
21class BaseIdentityTest(test.BaseTestCase):
22
23 # The version of the identity that will be used in the tests.
24 identity_version = 'v3'
25
26 # NOTE(rodrigods): for now, all tests are in the admin scope, if
27 # necessary, another class can be created to handle non-admin tests.
28 credential_type = 'identity_admin'
29
30 @classmethod
31 def setup_clients(cls):
32 super(BaseIdentityTest, cls).setup_clients()
33 credentials = common_creds.get_configured_admin_credentials(
34 cls.credential_type, identity_version=cls.identity_version)
35 cls.keystone_manager = clients.Manager(credentials)
36 cls.auth_client = cls.keystone_manager.auth_client
37 cls.idps_client = cls.keystone_manager.identity_providers_client
38 cls.mappings_client = cls.keystone_manager.mapping_rules_client
39 cls.saml2_client = cls.keystone_manager.saml2_client
40 cls.sps_client = cls.keystone_manager.service_providers_client
41 cls.tokens_client = cls.keystone_manager.token_v3_client
diff --git a/keystone_tempest_plugin/tests/scenario/__init__.py b/keystone_tempest_plugin/tests/scenario/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/keystone_tempest_plugin/tests/scenario/__init__.py
+++ /dev/null
diff --git a/keystone_tempest_plugin/tests/scenario/test_federated_authentication.py b/keystone_tempest_plugin/tests/scenario/test_federated_authentication.py
deleted file mode 100644
index 24d7416..0000000
--- a/keystone_tempest_plugin/tests/scenario/test_federated_authentication.py
+++ /dev/null
@@ -1,176 +0,0 @@
1# Copyright 2016 Red Hat, Inc.
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15from lxml import etree
16from six.moves import http_client
17from tempest import config
18from tempest.lib.common.utils import data_utils
19import testtools
20
21from keystone_tempest_plugin.tests import base
22
23
24CONF = config.CONF
25
26
27class TestSaml2EcpFederatedAuthentication(base.BaseIdentityTest):
28
29 ECP_SAML2_NAMESPACES = {
30 'ecp': 'urn:oasis:names:tc:SAML:2.0:profiles:SSO:ecp',
31 'S': 'http://schemas.xmlsoap.org/soap/envelope/',
32 'paos': 'urn:liberty:paos:2003-08'
33 }
34
35 ECP_SERVICE_PROVIDER_CONSUMER_URL = ('/S:Envelope/S:Header/paos:Request/'
36 '@responseConsumerURL')
37
38 ECP_IDP_CONSUMER_URL = ('/S:Envelope/S:Header/ecp:Response/'
39 '@AssertionConsumerServiceURL')
40
41 ECP_RELAY_STATE = '//ecp:RelayState'
42
43 def _setup_settings(self):
44 self.idp_id = CONF.fed_scenario.idp_id
45 self.idp_url = CONF.fed_scenario.idp_ecp_url
46 self.keystone_v3_endpoint = CONF.identity.uri_v3
47 self.password = CONF.fed_scenario.idp_password
48 self.protocol_id = CONF.fed_scenario.protocol_id
49 self.username = CONF.fed_scenario.idp_username
50
51 def _setup_idp(self):
52 remote_ids = CONF.fed_scenario.idp_remote_ids
53 self.idps_client.create_identity_provider(
54 self.idp_id, remote_ids=remote_ids, enabled=True)
55 self.addCleanup(
56 self.idps_client.delete_identity_provider, self.idp_id)
57
58 def _setup_mapping(self):
59 self.mapping_id = data_utils.rand_uuid_hex()
60 mapping_remote_type = CONF.fed_scenario.mapping_remote_type
61 mapping_user_name = CONF.fed_scenario.mapping_user_name
62 mapping_group_name = CONF.fed_scenario.mapping_group_name
63 mapping_group_domain_name = CONF.fed_scenario.mapping_group_domain_name
64
65 rules = [{
66 'local': [
67 {
68 'user': {'name': mapping_user_name}
69 },
70 {
71 'group': {
72 'domain': {'name': mapping_group_domain_name},
73 'name': mapping_group_name
74 }
75 }
76 ],
77 'remote': [
78 {
79 'type': mapping_remote_type
80 }
81 ]
82 }]
83 mapping_ref = {'rules': rules}
84 self.mappings_client.create_mapping_rule(self.mapping_id, mapping_ref)
85 self.addCleanup(
86 self.mappings_client.delete_mapping_rule, self.mapping_id)
87
88 def _setup_protocol(self):
89 self.idps_client.add_protocol_and_mapping(
90 self.idp_id, self.protocol_id, self.mapping_id)
91 self.addCleanup(
92 self.idps_client.delete_protocol_and_mapping,
93 self.idp_id,
94 self.protocol_id)
95
96 def setUp(self):
97 super(TestSaml2EcpFederatedAuthentication, self).setUp()
98 self._setup_settings()
99
100 # Reset client's session to avoid getting garbage from another runs
101 self.saml2_client.reset_session()
102
103 # Setup identity provider, mapping and protocol
104 self._setup_idp()
105 self._setup_mapping()
106 self._setup_protocol()
107
108 def _str_from_xml(self, xml, path):
109 l = xml.xpath(path, namespaces=self.ECP_SAML2_NAMESPACES)
110 self.assertEqual(1, len(l))
111 return l[0]
112
113 def _request_unscoped_token(self):
114 resp = self.saml2_client.send_service_provider_request(
115 self.keystone_v3_endpoint, self.idp_id, self.protocol_id)
116 self.assertEqual(http_client.OK, resp.status_code)
117 saml2_authn_request = etree.XML(resp.content)
118
119 relay_state = self._str_from_xml(
120 saml2_authn_request, self.ECP_RELAY_STATE)
121 sp_consumer_url = self._str_from_xml(
122 saml2_authn_request, self.ECP_SERVICE_PROVIDER_CONSUMER_URL)
123
124 # Perform the authn request to the identity provider
125 resp = self.saml2_client.send_identity_provider_authn_request(
126 saml2_authn_request, self.idp_url, self.username, self.password)
127 self.assertEqual(http_client.OK, resp.status_code)
128 saml2_idp_authn_response = etree.XML(resp.content)
129
130 idp_consumer_url = self._str_from_xml(
131 saml2_idp_authn_response, self.ECP_IDP_CONSUMER_URL)
132
133 # Assert that both saml2_authn_request and saml2_idp_authn_response
134 # have the same consumer URL.
135 self.assertEqual(sp_consumer_url, idp_consumer_url)
136
137 # Present the identity provider authn response to the service provider.
138 resp = self.saml2_client.send_service_provider_saml2_authn_response(
139 saml2_idp_authn_response, relay_state, idp_consumer_url)
140 # Must receive a redirect from service provider to the URL where the
141 # unscoped token can be retrieved.
142 self.assertIn(resp.status_code,
143 [http_client.FOUND, http_client.SEE_OTHER])
144
145 # We can receive multiple types of errors here, the response depends on
146 # the mapping and the username used to authenticate in the Identity
147 # Provider and also in the Identity Provider remote ID validation.
148 # If everything works well, we receive an unscoped token.
149 sp_url = resp.headers['location']
150 resp = (
151 self.saml2_client.send_service_provider_unscoped_token_request(
152 sp_url))
153 self.assertEqual(http_client.CREATED, resp.status_code)
154 self.assertIn('X-Subject-Token', resp.headers)
155 self.assertNotEmpty(resp.json())
156
157 return resp
158
159 @testtools.skipUnless(CONF.identity_feature_enabled.federation,
160 "Federated Identity feature not enabled")
161 def test_request_unscoped_token(self):
162 self._request_unscoped_token()
163
164 @testtools.skipUnless(CONF.identity_feature_enabled.federation,
165 "Federated Identity feature not enabled")
166 def test_request_scoped_token(self):
167 resp = self._request_unscoped_token()
168 token_id = resp.headers['X-Subject-Token']
169
170 projects = self.auth_client.get_available_projects_scopes(
171 self.keystone_v3_endpoint, token_id)['projects']
172 self.assertNotEmpty(projects)
173
174 # Get a scoped token to one of the listed projects
175 self.tokens_client.auth(
176 project_id=projects[0]['id'], token=token_id)
diff --git a/setup.cfg b/setup.cfg
index df40e0a..4c2a418 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -69,11 +69,6 @@ msgid_bugs_address = https://bugs.launchpad.net/keystone
69 69
70[pbr] 70[pbr]
71autodoc_tree_index_modules = True 71autodoc_tree_index_modules = True
72# NOTE(gagehugo): building docs with autodoc_tree_index_modules set to True
73# causes warnings when creating api docs with keystone_tempest_plugin and
74# these issues seem to be related to tempest/oslo_config rather than
75# keystone.
76autodoc_tree_excludes = keystone_tempest_plugin setup.py
77 72
78[entry_points] 73[entry_points]
79console_scripts = 74console_scripts =
@@ -213,6 +208,3 @@ paste.app_factory =
213 public_service = keystone.version.service:public_app_factory 208 public_service = keystone.version.service:public_app_factory
214 public_version_service = keystone.version.service:public_version_app_factory 209 public_version_service = keystone.version.service:public_version_app_factory
215 service_v3 = keystone.version.service:v3_app_factory 210 service_v3 = keystone.version.service:v3_app_factory
216
217tempest.test_plugins =
218 keystone_tests = keystone_tempest_plugin.plugin:KeystoneTempestPlugin