diff --git a/awscli/botocore/useragent.py b/awscli/botocore/useragent.py index e3618150e322..51fddfb8bf2a 100644 --- a/awscli/botocore/useragent.py +++ b/awscli/botocore/useragent.py @@ -104,6 +104,7 @@ 'FLEXIBLE_CHECKSUMS_REQ_XXHASH3': 'AG', 'FLEXIBLE_CHECKSUMS_REQ_XXHASH64': 'AH', 'FLEXIBLE_CHECKSUMS_REQ_XXHASH128': 'AI', + 'SSO_LOGIN_VANITY_URL': 'AM', 'AGENTIC_CALLER_CLAUDE_CODE': 'AN', 'AGENTIC_CALLER_GEMINI_CLI': 'AO', 'AGENTIC_CALLER_CODEX': 'AP', diff --git a/awscli/customizations/agenttoolkit/agents.py b/awscli/customizations/agenttoolkit/agents.py index 4c38488f531b..7b2d13fc71f4 100644 --- a/awscli/customizations/agenttoolkit/agents.py +++ b/awscli/customizations/agenttoolkit/agents.py @@ -276,9 +276,6 @@ def __init__(self, agent, name, path): self.path = path -# TODO: Verify detection, skills, and MCP config paths against actual -# installations before release. Currently only tested with Kiro and -# simulated agent directories. AGENT_CONFIGS = [ # https://docs.anthropic.com/en/docs/claude-code/mcp AgentConfig( diff --git a/awscli/customizations/configure/sso_commands.py b/awscli/customizations/configure/sso_commands.py index cfd90a3beba8..3c7d0054127c 100644 --- a/awscli/customizations/configure/sso_commands.py +++ b/awscli/customizations/configure/sso_commands.py @@ -33,6 +33,7 @@ from botocore.config import Config from botocore.configprovider import ConstantProvider from botocore.exceptions import ProfileNotFound +from botocore.useragent import register_feature_id from awscli.customizations.configure import ( get_section_header, @@ -448,6 +449,7 @@ def _prompt_for_sso_start_url_and_sso_region(self, verify=None): self._sso_session_prompter.sso_session_config['sso_region'] = ( region ) + register_feature_id('SSO_LOGIN_VANITY_URL') return start_url, region, resolved_url except Exception as e: logger.debug( diff --git a/awscli/customizations/sso/login.py b/awscli/customizations/sso/login.py index 3ad71608746f..99145a58c6bb 100644 --- a/awscli/customizations/sso/login.py +++ b/awscli/customizations/sso/login.py @@ -12,6 +12,8 @@ # language governing permissions and limitations under the License. import os +from botocore.useragent import register_feature_id + from awscli.customizations.configure.writer import ConfigFileWriter from awscli.customizations.sso.resolve import resolve_start_url from awscli.customizations.sso.utils import ( @@ -62,6 +64,9 @@ def _run_main(self, parsed_args, parsed_globals): verify=verify, ) + if resolved_url != start_url: + register_feature_id('SSO_LOGIN_VANITY_URL') + on_pending_authorization = None if parsed_args.no_browser: on_pending_authorization = PrintOnlyHandler() diff --git a/tests/functional/sso/test_login.py b/tests/functional/sso/test_login.py index 6f618be0ef27..89d0a3612c03 100644 --- a/tests/functional/sso/test_login.py +++ b/tests/functional/sso/test_login.py @@ -15,6 +15,8 @@ import os import re +from botocore.context import start_as_current_context + from awscli.testutils import mock from tests.functional.sso import BaseSSOTest @@ -560,6 +562,12 @@ def test_config_not_rewritten_when_region_matches(self): config_content = f.read() self.assertIn('sso_region=us-east-1', config_content) + def test_vanity_url_sets_feature_id_in_user_agent(self): + self.add_oidc_auth_code_responses(self.access_token) + with start_as_current_context(): + self.run_cmd('sso login') + self.assertIn('AM', self.last_request_dict['headers']['User-Agent']) + class TestLoginWithVanityUrlLegacy(BaseSSOTest): def setUp(self): @@ -628,3 +636,10 @@ def test_login_uses_configured_region(self): self.add_oidc_auth_code_responses(self.access_token) self.run_cmd('sso login') self.assert_used_expected_sso_region('us-west-2') + + def test_direct_url_does_not_set_vanity_feature_id(self): + self.add_oidc_auth_code_responses(self.access_token) + with start_as_current_context(): + self.run_cmd('sso login') + user_agent = self.last_request_dict['headers']['User-Agent'] + self.assertNotIn('AM', user_agent.split('m/')[-1])