diff --git a/packages/smithy-aws-core/.changes/next-release/smithy-aws-core-enhancement-14481b3143ee48f28828876920f5ff2f.json b/packages/smithy-aws-core/.changes/next-release/smithy-aws-core-enhancement-14481b3143ee48f28828876920f5ff2f.json new file mode 100644 index 000000000..592e1f7b1 --- /dev/null +++ b/packages/smithy-aws-core/.changes/next-release/smithy-aws-core-enhancement-14481b3143ee48f28828876920f5ff2f.json @@ -0,0 +1,4 @@ +{ + "type": "enhancement", + "description": "Update identity chain validation to use case-insensitive comparisons for provider names." +} \ No newline at end of file diff --git a/packages/smithy-aws-core/src/smithy_aws_core/identity/chain/__init__.py b/packages/smithy-aws-core/src/smithy_aws_core/identity/chain/__init__.py index f644c1d09..4dc033fe6 100644 --- a/packages/smithy-aws-core/src/smithy_aws_core/identity/chain/__init__.py +++ b/packages/smithy-aws-core/src/smithy_aws_core/identity/chain/__init__.py @@ -99,12 +99,13 @@ def _validate_providers(providers: Sequence[ChainIdentityProvider]) -> None: discovered_standard_slots: dict[StandardProvider, ChainIdentityProvider] = {} for provider in providers: - if (previous := discovered_names.get(provider.name)) is not None: + normalized_name = provider.name.casefold() + if (previous := discovered_names.get(normalized_name)) is not None: raise IdentityChainConfigurationError( f"Credential providers {type(previous).__name__} and " f"{type(provider).__name__} use the same name: {provider.name}." ) - discovered_names[provider.name] = provider + discovered_names[normalized_name] = provider ordering = provider.ordering if isinstance(ordering, Standard): diff --git a/packages/smithy-aws-core/tests/unit/identity/chain/test_chain.py b/packages/smithy-aws-core/tests/unit/identity/chain/test_chain.py index 07a23c110..abb12f8e1 100644 --- a/packages/smithy-aws-core/tests/unit/identity/chain/test_chain.py +++ b/packages/smithy-aws-core/tests/unit/identity/chain/test_chain.py @@ -198,6 +198,18 @@ def test_validate_rejects_duplicate_names() -> None: chain_module._validate_providers((first, second)) +def test_validate_rejects_case_insensitive_duplicate_names() -> None: + first = _StubProvider("Duplicate", Standard(slot=StandardProvider.ENVIRONMENT)) + second = _StubProvider("duplicate", Standard(slot=StandardProvider.SHARED_CONFIG)) + + with pytest.raises( + IdentityChainConfigurationError, + match="Credential providers _StubProvider and _StubProvider use the " + "same name: duplicate", + ): + chain_module._validate_providers((first, second)) + + def test_validate_rejects_duplicate_standard_slots() -> None: first = _StubProvider("a", Standard(slot=StandardProvider.ENVIRONMENT)) second = _StubProvider("b", Standard(slot=StandardProvider.ENVIRONMENT))