summaryrefslogtreecommitdiff
path: root/openstackclient
diff options
context:
space:
mode:
authorZuul <zuul@review.opendev.org>2022-09-30 12:31:51 +0000
committerGerrit Code Review <review@openstack.org>2022-09-30 12:31:51 +0000
commit36f58c2ad7bd56b231c960fcfd4b015327730bc2 (patch)
tree555d013fd0ca3466952055800a0a608708bd31bf /openstackclient
parent5826802793ac4df5c7dbaa53b8a3f790bfae94e2 (diff)
parent167cf11e825af95fe40c1daefdb6095c791a3ee5 (diff)
downloadpython-openstackclient-36f58c2ad7bd56b231c960fcfd4b015327730bc2.tar.gz
Merge "Add authorization_ttl for identity providers"
Diffstat (limited to 'openstackclient')
-rw-r--r--openstackclient/identity/v3/identity_provider.py45
-rw-r--r--openstackclient/tests/unit/identity/v3/test_identity_provider.py170
2 files changed, 214 insertions, 1 deletions
diff --git a/openstackclient/identity/v3/identity_provider.py b/openstackclient/identity/v3/identity_provider.py
index 7307cea0..19a62144 100644
--- a/openstackclient/identity/v3/identity_provider.py
+++ b/openstackclient/identity/v3/identity_provider.py
@@ -63,6 +63,16 @@ class CreateIdentityProvider(command.ShowOne):
'specified, a domain will be created automatically. '
'(Name or ID)'),
)
+ parser.add_argument(
+ '--authorization-ttl',
+ metavar='<authorization-ttl>',
+ type=int,
+ help=_('Time to keep the role assignments for users '
+ 'authenticating via this identity provider. '
+ 'When not provided, global default configured in the '
+ 'Identity service will be used. '
+ 'Available since Identity API version 3.14 (Ussuri).'),
+ )
enable_identity_provider = parser.add_mutually_exclusive_group()
enable_identity_provider.add_argument(
'--enable',
@@ -95,12 +105,23 @@ class CreateIdentityProvider(command.ShowOne):
domain_id = common.find_domain(identity_client,
parsed_args.domain).id
+ # TODO(pas-ha) actually check for 3.14 microversion
+ kwargs = {}
+ auth_ttl = parsed_args.authorization_ttl
+ if auth_ttl is not None:
+ if auth_ttl < 0:
+ msg = (_("%(param)s must be positive integer or zero."
+ ) % {"param": "authorization-ttl"})
+ raise exceptions.CommandError(msg)
+ kwargs['authorization_ttl'] = auth_ttl
+
idp = identity_client.federation.identity_providers.create(
id=parsed_args.identity_provider_id,
remote_ids=remote_ids,
description=parsed_args.description,
domain_id=domain_id,
- enabled=parsed_args.enabled)
+ enabled=parsed_args.enabled,
+ **kwargs)
idp._info.pop('links', None)
remote_ids = format_columns.ListColumn(idp._info.pop('remote_ids', []))
@@ -205,6 +226,14 @@ class SetIdentityProvider(command.Command):
help=_('Name of a file that contains many remote IDs to associate '
'with the identity provider, one per line'),
)
+ parser.add_argument(
+ '--authorization-ttl',
+ metavar='<authorization-ttl>',
+ type=int,
+ help=_('Time to keep the role assignments for users '
+ 'authenticating via this identity provider. '
+ 'Available since Identity API version 3.14 (Ussuri).'),
+ )
enable_identity_provider = parser.add_mutually_exclusive_group()
enable_identity_provider.add_argument(
'--enable',
@@ -241,6 +270,20 @@ class SetIdentityProvider(command.Command):
if parsed_args.remote_id_file or parsed_args.remote_id:
kwargs['remote_ids'] = remote_ids
+ # TODO(pas-ha) actually check for 3.14 microversion
+ # TODO(pas-ha) make it possible to reset authorization_ttl
+ # back to None value.
+ # Currently not possible as filter_kwargs decorator in
+ # keystoneclient/base.py explicitly drops the None-valued keys
+ # from kwargs, and 'update' method is wrapped in this decorator.
+ auth_ttl = parsed_args.authorization_ttl
+ if auth_ttl is not None:
+ if auth_ttl < 0:
+ msg = (_("%(param)s must be positive integer or zero."
+ ) % {"param": "authorization-ttl"})
+ raise exceptions.CommandError(msg)
+ kwargs['authorization_ttl'] = auth_ttl
+
federation_client.identity_providers.update(
parsed_args.identity_provider,
**kwargs
diff --git a/openstackclient/tests/unit/identity/v3/test_identity_provider.py b/openstackclient/tests/unit/identity/v3/test_identity_provider.py
index 1a9a7991..480bae59 100644
--- a/openstackclient/tests/unit/identity/v3/test_identity_provider.py
+++ b/openstackclient/tests/unit/identity/v3/test_identity_provider.py
@@ -15,9 +15,12 @@
import copy
from unittest import mock
+from osc_lib import exceptions
+
from openstackclient.identity.v3 import identity_provider
from openstackclient.tests.unit import fakes
from openstackclient.tests.unit.identity.v3 import fakes as identity_fakes
+from openstackclient.tests.unit import utils as test_utils
class TestIdentityProvider(identity_fakes.TestFederatedIdentity):
@@ -308,6 +311,86 @@ class TestIdentityProviderCreate(TestIdentityProvider):
self.assertEqual(self.columns, columns)
self.assertCountEqual(self.datalist, data)
+ def test_create_identity_provider_authttl_positive(self):
+ arglist = [
+ '--authorization-ttl', '60',
+ identity_fakes.idp_id,
+ ]
+ verifylist = [
+ ('identity_provider_id', identity_fakes.idp_id),
+ ('authorization_ttl', 60),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ columns, data = self.cmd.take_action(parsed_args)
+
+ # Set expected values
+ kwargs = {
+ 'remote_ids': None,
+ 'description': None,
+ 'domain_id': None,
+ 'enabled': True,
+ 'authorization_ttl': 60,
+ }
+
+ self.identity_providers_mock.create.assert_called_with(
+ id=identity_fakes.idp_id,
+ **kwargs
+ )
+
+ self.assertEqual(self.columns, columns)
+ self.assertCountEqual(self.datalist, data)
+
+ def test_create_identity_provider_authttl_zero(self):
+ arglist = [
+ '--authorization-ttl', '0',
+ identity_fakes.idp_id,
+ ]
+ verifylist = [
+ ('identity_provider_id', identity_fakes.idp_id),
+ ('authorization_ttl', 0),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ columns, data = self.cmd.take_action(parsed_args)
+
+ # Set expected values
+ kwargs = {
+ 'remote_ids': None,
+ 'description': None,
+ 'domain_id': None,
+ 'enabled': True,
+ 'authorization_ttl': 0,
+ }
+
+ self.identity_providers_mock.create.assert_called_with(
+ id=identity_fakes.idp_id,
+ **kwargs
+ )
+
+ self.assertEqual(self.columns, columns)
+ self.assertCountEqual(self.datalist, data)
+
+ def test_create_identity_provider_authttl_negative(self):
+ arglist = [
+ '--authorization-ttl', '-60',
+ identity_fakes.idp_id,
+ ]
+ verifylist = [
+ ('identity_provider_id', identity_fakes.idp_id),
+ ('authorization_ttl', -60),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ self.assertRaises(exceptions.CommandError, self.cmd.take_action,
+ parsed_args)
+
+ def test_create_identity_provider_authttl_not_int(self):
+ arglist = [
+ '--authorization-ttl', 'spam',
+ identity_fakes.idp_id,
+ ]
+ verifylist = []
+ self.assertRaises(test_utils.ParserException, self.check_parser,
+ self.cmd, arglist, verifylist)
+
class TestIdentityProviderDelete(TestIdentityProvider):
@@ -678,6 +761,93 @@ class TestIdentityProviderSet(TestIdentityProvider):
self.cmd.take_action(parsed_args)
+ def test_identity_provider_set_authttl_positive(self):
+ def prepare(self):
+ """Prepare fake return objects before the test is executed"""
+ updated_idp = copy.deepcopy(identity_fakes.IDENTITY_PROVIDER)
+ updated_idp['authorization_ttl'] = 60
+ resources = fakes.FakeResource(
+ None,
+ updated_idp,
+ loaded=True
+ )
+ self.identity_providers_mock.update.return_value = resources
+
+ prepare(self)
+ arglist = [
+ '--authorization-ttl', '60',
+ identity_fakes.idp_id
+ ]
+ verifylist = [
+ ('identity_provider', identity_fakes.idp_id),
+ ('enable', False),
+ ('disable', False),
+ ('remote_id', None),
+ ('authorization_ttl', 60),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ self.cmd.take_action(parsed_args)
+ self.identity_providers_mock.update.assert_called_with(
+ identity_fakes.idp_id,
+ authorization_ttl=60,
+ )
+
+ def test_identity_provider_set_authttl_zero(self):
+ def prepare(self):
+ """Prepare fake return objects before the test is executed"""
+ updated_idp = copy.deepcopy(identity_fakes.IDENTITY_PROVIDER)
+ updated_idp['authorization_ttl'] = 0
+ resources = fakes.FakeResource(
+ None,
+ updated_idp,
+ loaded=True
+ )
+ self.identity_providers_mock.update.return_value = resources
+
+ prepare(self)
+ arglist = [
+ '--authorization-ttl', '0',
+ identity_fakes.idp_id
+ ]
+ verifylist = [
+ ('identity_provider', identity_fakes.idp_id),
+ ('enable', False),
+ ('disable', False),
+ ('remote_id', None),
+ ('authorization_ttl', 0),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ self.cmd.take_action(parsed_args)
+ self.identity_providers_mock.update.assert_called_with(
+ identity_fakes.idp_id,
+ authorization_ttl=0,
+ )
+
+ def test_identity_provider_set_authttl_negative(self):
+ arglist = [
+ '--authorization-ttl', '-1',
+ identity_fakes.idp_id
+ ]
+ verifylist = [
+ ('identity_provider', identity_fakes.idp_id),
+ ('enable', False),
+ ('disable', False),
+ ('remote_id', None),
+ ('authorization_ttl', -1),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ self.assertRaises(exceptions.CommandError, self.cmd.take_action,
+ parsed_args)
+
+ def test_identity_provider_set_authttl_not_int(self):
+ arglist = [
+ '--authorization-ttl', 'spam',
+ identity_fakes.idp_id
+ ]
+ verifylist = []
+ self.assertRaises(test_utils.ParserException, self.check_parser,
+ self.cmd, arglist, verifylist)
+
class TestIdentityProviderShow(TestIdentityProvider):