Merge pull request #2494 from edekadigital/add-iam-open-id-connect-provider
Add iam open id connect provider
This commit is contained in:
commit
b433399cb5
@ -3163,7 +3163,7 @@
|
|||||||
- [ ] describe_events
|
- [ ] describe_events
|
||||||
|
|
||||||
## iam
|
## iam
|
||||||
55% implemented
|
57% implemented
|
||||||
- [ ] add_client_id_to_open_id_connect_provider
|
- [ ] add_client_id_to_open_id_connect_provider
|
||||||
- [X] add_role_to_instance_profile
|
- [X] add_role_to_instance_profile
|
||||||
- [X] add_user_to_group
|
- [X] add_user_to_group
|
||||||
@ -3176,7 +3176,7 @@
|
|||||||
- [X] create_group
|
- [X] create_group
|
||||||
- [X] create_instance_profile
|
- [X] create_instance_profile
|
||||||
- [X] create_login_profile
|
- [X] create_login_profile
|
||||||
- [ ] create_open_id_connect_provider
|
- [X] create_open_id_connect_provider
|
||||||
- [X] create_policy
|
- [X] create_policy
|
||||||
- [X] create_policy_version
|
- [X] create_policy_version
|
||||||
- [X] create_role
|
- [X] create_role
|
||||||
@ -3193,7 +3193,7 @@
|
|||||||
- [ ] delete_group_policy
|
- [ ] delete_group_policy
|
||||||
- [ ] delete_instance_profile
|
- [ ] delete_instance_profile
|
||||||
- [X] delete_login_profile
|
- [X] delete_login_profile
|
||||||
- [ ] delete_open_id_connect_provider
|
- [X] delete_open_id_connect_provider
|
||||||
- [X] delete_policy
|
- [X] delete_policy
|
||||||
- [X] delete_policy_version
|
- [X] delete_policy_version
|
||||||
- [X] delete_role
|
- [X] delete_role
|
||||||
@ -3227,7 +3227,7 @@
|
|||||||
- [X] get_group_policy
|
- [X] get_group_policy
|
||||||
- [X] get_instance_profile
|
- [X] get_instance_profile
|
||||||
- [X] get_login_profile
|
- [X] get_login_profile
|
||||||
- [ ] get_open_id_connect_provider
|
- [X] get_open_id_connect_provider
|
||||||
- [ ] get_organizations_access_report
|
- [ ] get_organizations_access_report
|
||||||
- [X] get_policy
|
- [X] get_policy
|
||||||
- [X] get_policy_version
|
- [X] get_policy_version
|
||||||
@ -3253,7 +3253,7 @@
|
|||||||
- [ ] list_instance_profiles
|
- [ ] list_instance_profiles
|
||||||
- [ ] list_instance_profiles_for_role
|
- [ ] list_instance_profiles_for_role
|
||||||
- [X] list_mfa_devices
|
- [X] list_mfa_devices
|
||||||
- [ ] list_open_id_connect_providers
|
- [X] list_open_id_connect_providers
|
||||||
- [X] list_policies
|
- [X] list_policies
|
||||||
- [ ] list_policies_granting_service_access
|
- [ ] list_policies_granting_service_access
|
||||||
- [X] list_policy_versions
|
- [X] list_policy_versions
|
||||||
|
@ -93,3 +93,27 @@ class TooManyTags(RESTError):
|
|||||||
super(TooManyTags, self).__init__(
|
super(TooManyTags, self).__init__(
|
||||||
'ValidationError', "1 validation error detected: Value '{}' at '{}' failed to satisfy "
|
'ValidationError', "1 validation error detected: Value '{}' at '{}' failed to satisfy "
|
||||||
"constraint: Member must have length less than or equal to 50.".format(tags, param))
|
"constraint: Member must have length less than or equal to 50.".format(tags, param))
|
||||||
|
|
||||||
|
|
||||||
|
class EntityAlreadyExists(RESTError):
|
||||||
|
code = 409
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super(EntityAlreadyExists, self).__init__(
|
||||||
|
'EntityAlreadyExists', "Unknown")
|
||||||
|
|
||||||
|
|
||||||
|
class ValidationError(RESTError):
|
||||||
|
code = 400
|
||||||
|
|
||||||
|
def __init__(self, message):
|
||||||
|
super(ValidationError, self).__init__(
|
||||||
|
'ValidationError', message)
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidInput(RESTError):
|
||||||
|
code = 400
|
||||||
|
|
||||||
|
def __init__(self, message):
|
||||||
|
super(InvalidInput, self).__init__(
|
||||||
|
'InvalidInput', message)
|
||||||
|
@ -7,6 +7,7 @@ import re
|
|||||||
|
|
||||||
from cryptography import x509
|
from cryptography import x509
|
||||||
from cryptography.hazmat.backends import default_backend
|
from cryptography.hazmat.backends import default_backend
|
||||||
|
from six.moves.urllib.parse import urlparse
|
||||||
|
|
||||||
from moto.core.exceptions import RESTError
|
from moto.core.exceptions import RESTError
|
||||||
from moto.core import BaseBackend, BaseModel
|
from moto.core import BaseBackend, BaseModel
|
||||||
@ -14,8 +15,9 @@ from moto.core.utils import iso_8601_datetime_without_milliseconds, iso_8601_dat
|
|||||||
from moto.iam.policy_validation import IAMPolicyDocumentValidator
|
from moto.iam.policy_validation import IAMPolicyDocumentValidator
|
||||||
|
|
||||||
from .aws_managed_policies import aws_managed_policies_data
|
from .aws_managed_policies import aws_managed_policies_data
|
||||||
from .exceptions import IAMNotFoundException, IAMConflictException, IAMReportNotPresentException, IAMLimitExceededException, \
|
from .exceptions import (IAMNotFoundException, IAMConflictException, IAMReportNotPresentException, IAMLimitExceededException,
|
||||||
MalformedCertificate, DuplicateTags, TagKeyTooBig, InvalidTagCharacters, TooManyTags, TagValueTooBig
|
MalformedCertificate, DuplicateTags, TagKeyTooBig, InvalidTagCharacters, TooManyTags, TagValueTooBig,
|
||||||
|
EntityAlreadyExists, ValidationError, InvalidInput)
|
||||||
from .utils import random_access_key, random_alphanumeric, random_resource_id, random_policy_id
|
from .utils import random_access_key, random_alphanumeric, random_resource_id, random_policy_id
|
||||||
|
|
||||||
ACCOUNT_ID = 123456789012
|
ACCOUNT_ID = 123456789012
|
||||||
@ -93,6 +95,82 @@ class SAMLProvider(BaseModel):
|
|||||||
return "arn:aws:iam::{0}:saml-provider/{1}".format(ACCOUNT_ID, self.name)
|
return "arn:aws:iam::{0}:saml-provider/{1}".format(ACCOUNT_ID, self.name)
|
||||||
|
|
||||||
|
|
||||||
|
class OpenIDConnectProvider(BaseModel):
|
||||||
|
def __init__(self, url, thumbprint_list, client_id_list=None):
|
||||||
|
self._errors = []
|
||||||
|
self._validate(url, thumbprint_list, client_id_list)
|
||||||
|
|
||||||
|
parsed_url = urlparse(url)
|
||||||
|
self.url = parsed_url.netloc + parsed_url.path
|
||||||
|
self.thumbprint_list = thumbprint_list
|
||||||
|
self.client_id_list = client_id_list
|
||||||
|
self.create_date = datetime.utcnow()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def arn(self):
|
||||||
|
return 'arn:aws:iam::{0}:oidc-provider/{1}'.format(ACCOUNT_ID, self.url)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def created_iso_8601(self):
|
||||||
|
return iso_8601_datetime_without_milliseconds(self.create_date)
|
||||||
|
|
||||||
|
def _validate(self, url, thumbprint_list, client_id_list):
|
||||||
|
if any(len(client_id) > 255 for client_id in client_id_list):
|
||||||
|
self._errors.append(self._format_error(
|
||||||
|
key='clientIDList',
|
||||||
|
value=client_id_list,
|
||||||
|
constraint='Member must satisfy constraint: '
|
||||||
|
'[Member must have length less than or equal to 255, '
|
||||||
|
'Member must have length greater than or equal to 1]',
|
||||||
|
))
|
||||||
|
|
||||||
|
if any(len(thumbprint) > 40 for thumbprint in thumbprint_list):
|
||||||
|
self._errors.append(self._format_error(
|
||||||
|
key='thumbprintList',
|
||||||
|
value=thumbprint_list,
|
||||||
|
constraint='Member must satisfy constraint: '
|
||||||
|
'[Member must have length less than or equal to 40, '
|
||||||
|
'Member must have length greater than or equal to 40]',
|
||||||
|
))
|
||||||
|
|
||||||
|
if len(url) > 255:
|
||||||
|
self._errors.append(self._format_error(
|
||||||
|
key='url',
|
||||||
|
value=url,
|
||||||
|
constraint='Member must have length less than or equal to 255',
|
||||||
|
))
|
||||||
|
|
||||||
|
self._raise_errors()
|
||||||
|
|
||||||
|
parsed_url = urlparse(url)
|
||||||
|
if not parsed_url.scheme or not parsed_url.netloc:
|
||||||
|
raise ValidationError('Invalid Open ID Connect Provider URL')
|
||||||
|
|
||||||
|
if len(thumbprint_list) > 5:
|
||||||
|
raise InvalidInput('Thumbprint list must contain fewer than 5 entries.')
|
||||||
|
|
||||||
|
if len(client_id_list) > 100:
|
||||||
|
raise IAMLimitExceededException('Cannot exceed quota for ClientIdsPerOpenIdConnectProvider: 100')
|
||||||
|
|
||||||
|
def _format_error(self, key, value, constraint):
|
||||||
|
return 'Value "{value}" at "{key}" failed to satisfy constraint: {constraint}'.format(
|
||||||
|
constraint=constraint,
|
||||||
|
key=key,
|
||||||
|
value=value,
|
||||||
|
)
|
||||||
|
|
||||||
|
def _raise_errors(self):
|
||||||
|
if self._errors:
|
||||||
|
count = len(self._errors)
|
||||||
|
plural = "s" if len(self._errors) > 1 else ""
|
||||||
|
errors = "; ".join(self._errors)
|
||||||
|
self._errors = [] # reset collected errors
|
||||||
|
|
||||||
|
raise ValidationError('{count} validation error{plural} detected: {errors}'.format(
|
||||||
|
count=count, plural=plural, errors=errors,
|
||||||
|
))
|
||||||
|
|
||||||
|
|
||||||
class PolicyVersion(object):
|
class PolicyVersion(object):
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
@ -515,6 +593,7 @@ class IAMBackend(BaseBackend):
|
|||||||
self.managed_policies = self._init_managed_policies()
|
self.managed_policies = self._init_managed_policies()
|
||||||
self.account_aliases = []
|
self.account_aliases = []
|
||||||
self.saml_providers = {}
|
self.saml_providers = {}
|
||||||
|
self.open_id_providers = {}
|
||||||
self.policy_arn_regex = re.compile(
|
self.policy_arn_regex = re.compile(
|
||||||
r'^arn:aws:iam::[0-9]*:policy/.*$')
|
r'^arn:aws:iam::[0-9]*:policy/.*$')
|
||||||
super(IAMBackend, self).__init__()
|
super(IAMBackend, self).__init__()
|
||||||
@ -1264,5 +1343,28 @@ class IAMBackend(BaseBackend):
|
|||||||
return user
|
return user
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def create_open_id_connect_provider(self, url, thumbprint_list, client_id_list):
|
||||||
|
open_id_provider = OpenIDConnectProvider(url, thumbprint_list, client_id_list)
|
||||||
|
|
||||||
|
if open_id_provider.arn in self.open_id_providers:
|
||||||
|
raise EntityAlreadyExists
|
||||||
|
|
||||||
|
self.open_id_providers[open_id_provider.arn] = open_id_provider
|
||||||
|
return open_id_provider
|
||||||
|
|
||||||
|
def delete_open_id_connect_provider(self, arn):
|
||||||
|
self.open_id_providers.pop(arn, None)
|
||||||
|
|
||||||
|
def get_open_id_connect_provider(self, arn):
|
||||||
|
open_id_provider = self.open_id_providers.get(arn)
|
||||||
|
|
||||||
|
if not open_id_provider:
|
||||||
|
raise IAMNotFoundException('OpenIDConnect Provider not found for arn {}'.format(arn))
|
||||||
|
|
||||||
|
return open_id_provider
|
||||||
|
|
||||||
|
def list_open_id_connect_providers(self):
|
||||||
|
return list(self.open_id_providers.keys())
|
||||||
|
|
||||||
|
|
||||||
iam_backend = IAMBackend()
|
iam_backend = IAMBackend()
|
||||||
|
@ -755,6 +755,38 @@ class IamResponse(BaseResponse):
|
|||||||
template = self.response_template(UNTAG_ROLE_TEMPLATE)
|
template = self.response_template(UNTAG_ROLE_TEMPLATE)
|
||||||
return template.render()
|
return template.render()
|
||||||
|
|
||||||
|
def create_open_id_connect_provider(self):
|
||||||
|
open_id_provider_url = self._get_param('Url')
|
||||||
|
thumbprint_list = self._get_multi_param('ThumbprintList.member')
|
||||||
|
client_id_list = self._get_multi_param('ClientIDList.member')
|
||||||
|
|
||||||
|
open_id_provider = iam_backend.create_open_id_connect_provider(open_id_provider_url, thumbprint_list, client_id_list)
|
||||||
|
|
||||||
|
template = self.response_template(CREATE_OPEN_ID_CONNECT_PROVIDER_TEMPLATE)
|
||||||
|
return template.render(open_id_provider=open_id_provider)
|
||||||
|
|
||||||
|
def delete_open_id_connect_provider(self):
|
||||||
|
open_id_provider_arn = self._get_param('OpenIDConnectProviderArn')
|
||||||
|
|
||||||
|
iam_backend.delete_open_id_connect_provider(open_id_provider_arn)
|
||||||
|
|
||||||
|
template = self.response_template(DELETE_OPEN_ID_CONNECT_PROVIDER_TEMPLATE)
|
||||||
|
return template.render()
|
||||||
|
|
||||||
|
def get_open_id_connect_provider(self):
|
||||||
|
open_id_provider_arn = self._get_param('OpenIDConnectProviderArn')
|
||||||
|
|
||||||
|
open_id_provider = iam_backend.get_open_id_connect_provider(open_id_provider_arn)
|
||||||
|
|
||||||
|
template = self.response_template(GET_OPEN_ID_CONNECT_PROVIDER_TEMPLATE)
|
||||||
|
return template.render(open_id_provider=open_id_provider)
|
||||||
|
|
||||||
|
def list_open_id_connect_providers(self):
|
||||||
|
open_id_provider_arns = iam_backend.list_open_id_connect_providers()
|
||||||
|
|
||||||
|
template = self.response_template(LIST_OPEN_ID_CONNECT_PROVIDERS_TEMPLATE)
|
||||||
|
return template.render(open_id_provider_arns=open_id_provider_arns)
|
||||||
|
|
||||||
|
|
||||||
LIST_ENTITIES_FOR_POLICY_TEMPLATE = """<ListEntitiesForPolicyResponse>
|
LIST_ENTITIES_FOR_POLICY_TEMPLATE = """<ListEntitiesForPolicyResponse>
|
||||||
<ListEntitiesForPolicyResult>
|
<ListEntitiesForPolicyResult>
|
||||||
@ -1974,3 +2006,57 @@ UNTAG_ROLE_TEMPLATE = """<UntagRoleResponse xmlns="https://iam.amazonaws.com/doc
|
|||||||
<RequestId>EXAMPLE8-90ab-cdef-fedc-ba987EXAMPLE</RequestId>
|
<RequestId>EXAMPLE8-90ab-cdef-fedc-ba987EXAMPLE</RequestId>
|
||||||
</ResponseMetadata>
|
</ResponseMetadata>
|
||||||
</UntagRoleResponse>"""
|
</UntagRoleResponse>"""
|
||||||
|
|
||||||
|
|
||||||
|
CREATE_OPEN_ID_CONNECT_PROVIDER_TEMPLATE = """<CreateOpenIDConnectProviderResponse xmlns="https://iam.amazonaws.com/doc/2010-05-08/">
|
||||||
|
<CreateOpenIDConnectProviderResult>
|
||||||
|
<OpenIDConnectProviderArn>{{ open_id_provider.arn }}</OpenIDConnectProviderArn>
|
||||||
|
</CreateOpenIDConnectProviderResult>
|
||||||
|
<ResponseMetadata>
|
||||||
|
<RequestId>f248366a-4f64-11e4-aefa-bfd6aEXAMPLE</RequestId>
|
||||||
|
</ResponseMetadata>
|
||||||
|
</CreateOpenIDConnectProviderResponse>"""
|
||||||
|
|
||||||
|
|
||||||
|
DELETE_OPEN_ID_CONNECT_PROVIDER_TEMPLATE = """<DeleteOpenIDConnectProviderResponse xmlns="https://iam.amazonaws.com/doc/2010-05-08/">
|
||||||
|
<ResponseMetadata>
|
||||||
|
<RequestId>b5e49e29-4f64-11e4-aefa-bfd6aEXAMPLE</RequestId>
|
||||||
|
</ResponseMetadata>
|
||||||
|
</DeleteOpenIDConnectProviderResponse>"""
|
||||||
|
|
||||||
|
|
||||||
|
GET_OPEN_ID_CONNECT_PROVIDER_TEMPLATE = """<GetOpenIDConnectProviderResponse xmlns="https://iam.amazonaws.com/doc/2010-05-08/">
|
||||||
|
<GetOpenIDConnectProviderResult>
|
||||||
|
<ThumbprintList>
|
||||||
|
{% for thumbprint in open_id_provider.thumbprint_list %}
|
||||||
|
<member>{{ thumbprint }}</member>
|
||||||
|
{% endfor %}
|
||||||
|
</ThumbprintList>
|
||||||
|
<CreateDate>{{ open_id_provider.created_iso_8601 }}</CreateDate>
|
||||||
|
<ClientIDList>
|
||||||
|
{% for client_id in open_id_provider.client_id_list %}
|
||||||
|
<member>{{ client_id }}</member>
|
||||||
|
{% endfor %}
|
||||||
|
</ClientIDList>
|
||||||
|
<Url>{{ open_id_provider.url }}</Url>
|
||||||
|
</GetOpenIDConnectProviderResult>
|
||||||
|
<ResponseMetadata>
|
||||||
|
<RequestId>2c91531b-4f65-11e4-aefa-bfd6aEXAMPLE</RequestId>
|
||||||
|
</ResponseMetadata>
|
||||||
|
</GetOpenIDConnectProviderResponse>"""
|
||||||
|
|
||||||
|
|
||||||
|
LIST_OPEN_ID_CONNECT_PROVIDERS_TEMPLATE = """<ListOpenIDConnectProvidersResponse xmlns="https://iam.amazonaws.com/doc/2010-05-08/">
|
||||||
|
<ListOpenIDConnectProvidersResult>
|
||||||
|
<OpenIDConnectProviderList>
|
||||||
|
{% for open_id_provider_arn in open_id_provider_arns %}
|
||||||
|
<member>
|
||||||
|
<Arn>{{ open_id_provider_arn }}</Arn>
|
||||||
|
</member>
|
||||||
|
{% endfor %}
|
||||||
|
</OpenIDConnectProviderList>
|
||||||
|
</ListOpenIDConnectProvidersResult>
|
||||||
|
<ResponseMetadata>
|
||||||
|
<RequestId>de2c0228-4f63-11e4-aefa-bfd6aEXAMPLE</RequestId>
|
||||||
|
</ResponseMetadata>
|
||||||
|
</ListOpenIDConnectProvidersResponse>"""
|
||||||
|
@ -9,6 +9,8 @@ import sure # noqa
|
|||||||
import sys
|
import sys
|
||||||
from boto.exception import BotoServerError
|
from boto.exception import BotoServerError
|
||||||
from botocore.exceptions import ClientError
|
from botocore.exceptions import ClientError
|
||||||
|
from dateutil.tz import tzutc
|
||||||
|
|
||||||
from moto import mock_iam, mock_iam_deprecated
|
from moto import mock_iam, mock_iam_deprecated
|
||||||
from moto.iam.models import aws_managed_policies
|
from moto.iam.models import aws_managed_policies
|
||||||
from nose.tools import assert_raises, assert_equals
|
from nose.tools import assert_raises, assert_equals
|
||||||
@ -1565,3 +1567,251 @@ def test_create_role_with_permissions_boundary():
|
|||||||
|
|
||||||
# Ensure the PermissionsBoundary is included in role listing as well
|
# Ensure the PermissionsBoundary is included in role listing as well
|
||||||
conn.list_roles().get('Roles')[0].get('PermissionsBoundary').should.equal(expected)
|
conn.list_roles().get('Roles')[0].get('PermissionsBoundary').should.equal(expected)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_iam
|
||||||
|
def test_create_open_id_connect_provider():
|
||||||
|
client = boto3.client('iam', region_name='us-east-1')
|
||||||
|
response = client.create_open_id_connect_provider(
|
||||||
|
Url='https://example.com',
|
||||||
|
ThumbprintList=[] # even it is required to provide at least one thumbprint, AWS accepts an empty list
|
||||||
|
)
|
||||||
|
|
||||||
|
response['OpenIDConnectProviderArn'].should.equal(
|
||||||
|
'arn:aws:iam::123456789012:oidc-provider/example.com'
|
||||||
|
)
|
||||||
|
|
||||||
|
response = client.create_open_id_connect_provider(
|
||||||
|
Url='http://example.org',
|
||||||
|
ThumbprintList=[
|
||||||
|
'b' * 40
|
||||||
|
],
|
||||||
|
ClientIDList=[
|
||||||
|
'b'
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
response['OpenIDConnectProviderArn'].should.equal(
|
||||||
|
'arn:aws:iam::123456789012:oidc-provider/example.org'
|
||||||
|
)
|
||||||
|
|
||||||
|
response = client.create_open_id_connect_provider(
|
||||||
|
Url='http://example.org/oidc',
|
||||||
|
ThumbprintList=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
response['OpenIDConnectProviderArn'].should.equal(
|
||||||
|
'arn:aws:iam::123456789012:oidc-provider/example.org/oidc'
|
||||||
|
)
|
||||||
|
|
||||||
|
response = client.create_open_id_connect_provider(
|
||||||
|
Url='http://example.org/oidc-query?test=true',
|
||||||
|
ThumbprintList=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
response['OpenIDConnectProviderArn'].should.equal(
|
||||||
|
'arn:aws:iam::123456789012:oidc-provider/example.org/oidc-query'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_iam
|
||||||
|
def test_create_open_id_connect_provider_errors():
|
||||||
|
client = boto3.client('iam', region_name='us-east-1')
|
||||||
|
client.create_open_id_connect_provider(
|
||||||
|
Url='https://example.com',
|
||||||
|
ThumbprintList=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
client.create_open_id_connect_provider.when.called_with(
|
||||||
|
Url='https://example.com',
|
||||||
|
ThumbprintList=[]
|
||||||
|
).should.throw(
|
||||||
|
ClientError,
|
||||||
|
'Unknown'
|
||||||
|
)
|
||||||
|
|
||||||
|
client.create_open_id_connect_provider.when.called_with(
|
||||||
|
Url='example.org',
|
||||||
|
ThumbprintList=[]
|
||||||
|
).should.throw(
|
||||||
|
ClientError,
|
||||||
|
'Invalid Open ID Connect Provider URL'
|
||||||
|
)
|
||||||
|
|
||||||
|
client.create_open_id_connect_provider.when.called_with(
|
||||||
|
Url='example',
|
||||||
|
ThumbprintList=[]
|
||||||
|
).should.throw(
|
||||||
|
ClientError,
|
||||||
|
'Invalid Open ID Connect Provider URL'
|
||||||
|
)
|
||||||
|
|
||||||
|
client.create_open_id_connect_provider.when.called_with(
|
||||||
|
Url='http://example.org',
|
||||||
|
ThumbprintList=[
|
||||||
|
'a' * 40,
|
||||||
|
'b' * 40,
|
||||||
|
'c' * 40,
|
||||||
|
'd' * 40,
|
||||||
|
'e' * 40,
|
||||||
|
'f' * 40,
|
||||||
|
]
|
||||||
|
).should.throw(
|
||||||
|
ClientError,
|
||||||
|
'Thumbprint list must contain fewer than 5 entries.'
|
||||||
|
)
|
||||||
|
|
||||||
|
too_many_client_ids = ['{}'.format(i) for i in range(101)]
|
||||||
|
client.create_open_id_connect_provider.when.called_with(
|
||||||
|
Url='http://example.org',
|
||||||
|
ThumbprintList=[],
|
||||||
|
ClientIDList=too_many_client_ids
|
||||||
|
).should.throw(
|
||||||
|
ClientError,
|
||||||
|
'Cannot exceed quota for ClientIdsPerOpenIdConnectProvider: 100'
|
||||||
|
)
|
||||||
|
|
||||||
|
too_long_url = 'b' * 256
|
||||||
|
too_long_thumbprint = 'b' * 41
|
||||||
|
too_long_client_id = 'b' * 256
|
||||||
|
client.create_open_id_connect_provider.when.called_with(
|
||||||
|
Url=too_long_url,
|
||||||
|
ThumbprintList=[
|
||||||
|
too_long_thumbprint
|
||||||
|
],
|
||||||
|
ClientIDList=[
|
||||||
|
too_long_client_id
|
||||||
|
]
|
||||||
|
).should.throw(
|
||||||
|
ClientError,
|
||||||
|
'3 validation errors detected: '
|
||||||
|
'Value "{0}" at "clientIDList" failed to satisfy constraint: '
|
||||||
|
'Member must satisfy constraint: '
|
||||||
|
'[Member must have length less than or equal to 255, '
|
||||||
|
'Member must have length greater than or equal to 1]; '
|
||||||
|
'Value "{1}" at "thumbprintList" failed to satisfy constraint: '
|
||||||
|
'Member must satisfy constraint: '
|
||||||
|
'[Member must have length less than or equal to 40, '
|
||||||
|
'Member must have length greater than or equal to 40]; '
|
||||||
|
'Value "{2}" at "url" failed to satisfy constraint: '
|
||||||
|
'Member must have length less than or equal to 255'.format([too_long_client_id], [too_long_thumbprint], too_long_url)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_iam
|
||||||
|
def test_delete_open_id_connect_provider():
|
||||||
|
client = boto3.client('iam', region_name='us-east-1')
|
||||||
|
response = client.create_open_id_connect_provider(
|
||||||
|
Url='https://example.com',
|
||||||
|
ThumbprintList=[]
|
||||||
|
)
|
||||||
|
open_id_arn = response['OpenIDConnectProviderArn']
|
||||||
|
|
||||||
|
client.delete_open_id_connect_provider(
|
||||||
|
OpenIDConnectProviderArn=open_id_arn
|
||||||
|
)
|
||||||
|
|
||||||
|
client.get_open_id_connect_provider.when.called_with(
|
||||||
|
OpenIDConnectProviderArn=open_id_arn
|
||||||
|
).should.throw(
|
||||||
|
ClientError,
|
||||||
|
'OpenIDConnect Provider not found for arn {}'.format(open_id_arn)
|
||||||
|
)
|
||||||
|
|
||||||
|
# deleting a non existing provider should be successful
|
||||||
|
client.delete_open_id_connect_provider(
|
||||||
|
OpenIDConnectProviderArn=open_id_arn
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_iam
|
||||||
|
def test_get_open_id_connect_provider():
|
||||||
|
client = boto3.client('iam', region_name='us-east-1')
|
||||||
|
response = client.create_open_id_connect_provider(
|
||||||
|
Url='https://example.com',
|
||||||
|
ThumbprintList=[
|
||||||
|
'b' * 40
|
||||||
|
],
|
||||||
|
ClientIDList=[
|
||||||
|
'b'
|
||||||
|
]
|
||||||
|
)
|
||||||
|
open_id_arn = response['OpenIDConnectProviderArn']
|
||||||
|
|
||||||
|
response = client.get_open_id_connect_provider(
|
||||||
|
OpenIDConnectProviderArn=open_id_arn
|
||||||
|
)
|
||||||
|
|
||||||
|
response['Url'].should.equal('example.com')
|
||||||
|
response['ThumbprintList'].should.equal([
|
||||||
|
'b' * 40
|
||||||
|
])
|
||||||
|
response['ClientIDList'].should.equal([
|
||||||
|
'b'
|
||||||
|
])
|
||||||
|
response.should.have.key('CreateDate').should.be.a(datetime)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_iam
|
||||||
|
def test_get_open_id_connect_provider_errors():
|
||||||
|
client = boto3.client('iam', region_name='us-east-1')
|
||||||
|
response = client.create_open_id_connect_provider(
|
||||||
|
Url='https://example.com',
|
||||||
|
ThumbprintList=[
|
||||||
|
'b' * 40
|
||||||
|
],
|
||||||
|
ClientIDList=[
|
||||||
|
'b'
|
||||||
|
]
|
||||||
|
)
|
||||||
|
open_id_arn = response['OpenIDConnectProviderArn']
|
||||||
|
|
||||||
|
client.get_open_id_connect_provider.when.called_with(
|
||||||
|
OpenIDConnectProviderArn=open_id_arn + '-not-existing'
|
||||||
|
).should.throw(
|
||||||
|
ClientError,
|
||||||
|
'OpenIDConnect Provider not found for arn {}'.format(open_id_arn + '-not-existing')
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_iam
|
||||||
|
def test_list_open_id_connect_providers():
|
||||||
|
client = boto3.client('iam', region_name='us-east-1')
|
||||||
|
response = client.create_open_id_connect_provider(
|
||||||
|
Url='https://example.com',
|
||||||
|
ThumbprintList=[]
|
||||||
|
)
|
||||||
|
open_id_arn_1 = response['OpenIDConnectProviderArn']
|
||||||
|
|
||||||
|
response = client.create_open_id_connect_provider(
|
||||||
|
Url='http://example.org',
|
||||||
|
ThumbprintList=[
|
||||||
|
'b' * 40
|
||||||
|
],
|
||||||
|
ClientIDList=[
|
||||||
|
'b'
|
||||||
|
]
|
||||||
|
)
|
||||||
|
open_id_arn_2 = response['OpenIDConnectProviderArn']
|
||||||
|
|
||||||
|
response = client.create_open_id_connect_provider(
|
||||||
|
Url='http://example.org/oidc',
|
||||||
|
ThumbprintList=[]
|
||||||
|
)
|
||||||
|
open_id_arn_3 = response['OpenIDConnectProviderArn']
|
||||||
|
|
||||||
|
response = client.list_open_id_connect_providers()
|
||||||
|
|
||||||
|
sorted(response['OpenIDConnectProviderList'], key=lambda i: i['Arn']).should.equal(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
'Arn': open_id_arn_1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'Arn': open_id_arn_2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'Arn': open_id_arn_3
|
||||||
|
}
|
||||||
|
]
|
||||||
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user