资讯动态

深入理解aws configure sso:从命令行到临时凭证的完整链路

发布时间:2026/10/29 18:03:22 来源:尧图企业网站定制
在 AWS 上长期有效的 Access Key 一直是凭证泄露的主要来源。IAM Identity Center原 AWS SSO给出的方案是本地不保存任何长期密钥每次访问都使用自动过期的临时凭证。AWS CLI v2 中的aws configure sso是这套方案在命令行侧的入口。本文先介绍这个命令的使用方法然后沿着登录 → 拿到 token → 换取凭证 → 调用 API的链路逐层拆解背后的机制OAuth 授权码 PKCE 流程、回环重定向、设备码流程以及 STS 临时凭证的来源。一、命令的作用与配置结果aws configure sso是一个交互式向导。运行后它依次询问 SSO 会话名称、门户地址形如https://xxxx.awsapps.com/start、Identity Center 所在区域以及授权范围默认是sso:account:access。随后它会打开浏览器让你登录授权授权完成后列出你有权访问的账号和角色供你选择最后询问默认区域、输出格式和 profile 名称。向导会把结果写入~/.aws/config[profile dev-admin] sso_session my-sso sso_account_id 123456789012 sso_role_name AdministratorAccess region us-east-1 output json [sso-session my-sso] sso_start_url https://xxxx.awsapps.com/start sso_region us-east-1 sso_registration_scopes sso:account:access这里有两层结构。sso-session段描述如何登录 Identity Centerprofile段描述登录后进入哪个账号的哪个角色。多个 profile 可以共用同一个 session登录一次就能在多个账号和角色之间切换。如果在向导中把会话名称留空会生成旧格式配置即门户地址直接写在 profile 中。旧格式不支持自动刷新 token应当避免使用。日常使用只需要几条命令aws sso login--profiledev-admin# 登录token 过期后重新执行exportAWS_PROFILEdev-admin# 设为当前 shell 的默认 profileaws sts get-caller-identity# 确认当前身份aws ssologout# 登出清除缓存的 token命令很简单但背后经历了两个相互独立的阶段先拿到 Identity Center 的访问 token再用 token 换取 AWS 临时凭证。下面分别展开。二、阶段一获取 SSO token获取 token 用的是标准的 OAuth 2.0 协议授权服务器是 Identity Center 的 OIDC 端点oidc.region.amazonaws.com。CLI 支持两种授权流程较新版本2.22.0 起默认使用授权码 PKCE 流程加上--use-device-code参数时使用设备码流程。2.1 原生应用的难题与回环重定向OAuth 授权完成后授权服务器需要把结果交给客户端。Web 应用有公网地址授权服务器让浏览器跳转过去即可。但 CLI 这类本地原生应用没有公网地址授权服务器无法把结果直接送到你的电脑上。RFC 8252OAuth 2.0 for Native Apps为原生应用提供了三种接收回调的方式方式示例典型场景自定义 URI schememyapp://callback桌面或手机 App需要向系统注册协议声明的 HTTPS 链接Universal Links / App Links手机 App回环地址http://127.0.0.1:53127/callbackCLI、桌面工具CLI 没有安装过程无法注册自定义协议因此选择了回环重定向在本机的127.0.0.1上临时启动一个 HTTP 监听让授权结果跳回这个地址。127.0.0.1是操作系统内核提供的虚拟网络接口。发往它的数据包在内核内部完成收发不经过网卡也不会离开本机。所以外部机器无法访问这个端口而每台机器的127.0.0.1都只指向它自己。RFC 8252 对回环重定向有几条具体要求。客户端应当使用 IP 字面量而不是localhost因为localhost需要名称解析可能被 hosts 文件篡改也可能解析到 IPv6 而监听只在 IPv4 上。授权服务器必须允许任意端口因为客户端每次运行选用的端口可能不同。由于流量不离开本机回调地址允许使用 HTTP 而非 HTTPS。2.2 授权码 PKCE 的完整流程准备阶段。CLI 在127.0.0.1上绑定一个随机空闲端口并生成三个值用于防 CSRF 的随机串state一个高熵随机串code_verifier只保存在 CLI 进程内存中以及code_challenge其值为BASE64URL(SHA256(code_verifier))。然后 CLI 调用RegisterClient向 OIDC 服务注册自己声明回调地址。用户授权。CLI 打开浏览器访问授权地址https://oidc.us-east-1.amazonaws.com/authorize?response_typecode client_id...redirect_urihttp://127.0.0.1:53127/oauth/callback scopessso:account:accessstate... code_challenge...code_challenge_methodS256你在浏览器中登录并确认授权后AWS 服务器返回一个重定向响应HTTP/1.1 302 Found Location: http://127.0.0.1:53127/oauth/callback?codeAbC123...statexyz789浏览器回调。这是整个机制中最关键的一步。302加Location头的含义是请改为访问这个地址AWS 服务器只是下达了指令真正发起连接的是浏览器。浏览器运行在你的电脑上它访问的127.0.0.1自然就是你的电脑于是请求到达了 CLI 的监听端口。AWS 服务器自始至终没有主动连接过你的机器。换取 token。CLI 拿到授权码后调用CreateToken同时提交授权码和code_verifier。服务端计算code_verifier的哈希与此前收到的code_challenge比对一致才签发 access token 和 refresh token。token 缓存在~/.aws/sso/cache/目录下。2.3 本地监听如何返回一个网页CLI 不需要完整的 Web 框架。HTTP/1.1 本质上就是 TCP 连接上按约定格式收发的文本。浏览器连入后发送的请求如下GET /oauth/callback?codeAbC123...statexyz789 HTTP/1.1 Host: 127.0.0.1:53127CLI 解析请求行取出code和state校验state是否与发起时一致然后往同一个连接中写回一段 HTTP 格式的文本HTTP/1.1 200 OK Content-Type: text/html; charsetutf-8 Connection: close h1授权成功可以关闭此页面并返回终端/h1浏览器把它当作普通网页渲染出来CLI 随即关闭连接和监听。下面这段 Python 代码完整复现了这个过程importsocket,urllib.parse ssocket.socket();s.bind((127.0.0.1,0));s.listen(1)# 端口0由系统分配随机空闲端口print(f在浏览器打开: http://127.0.0.1:{s.getsockname()[1]}/oauth/callback?codeabcstatexyz)conn,_s.accept()# 阻塞直到浏览器连进来pathconn.recv(4096).decode().split( )[1]# 请求行: GET path HTTP/1.1print(收到参数:,urllib.parse.parse_qs(urllib.parse.urlparse(path).query))htmlh1授权成功可以关闭此页面/h1.encode()conn.sendall(bHTTP/1.1 200 OK\r\nContent-Type: text/html; charsetutf-8\r\nConnection: close\r\nbContent-Length: str(len(html)).encode()b\r\n\r\nhtml)conn.close();s.close()这个本地监听与普通 Web 站点有本质区别它只绑定回环地址外部不可达只处理一次请求生命周期只有几秒到几分钟端口每次随机不使用 TLS。CLI 也无法自动关闭浏览器标签页因为浏览器只允许脚本关闭由脚本自己打开的窗口所以只能提示用户手动关闭。2.4 PKCE 堵住了什么漏洞回环地址挡住了外部机器但挡不住本机的其他进程。恶意程序可能抢先监听同一端口或者从浏览器历史记录中读到授权码。随机端口降低了被预测的可能端口被占用时bind失败也能让 CLI 察觉但最终的保障是 PKCEcode_verifier从未经过浏览器即使授权码被截获攻击者也换不到 token。2.5 设备码流程没有浏览器的时候授权码流程有一个硬性前提浏览器和 CLI 必须在同一台机器上。在 SSH 远程服务器、容器、云桌面中你本地浏览器里的127.0.0.1指向的是你自己的电脑回调永远到达不了服务器。这时需要使用设备码流程RFC 8628aws sso login--profiledev-admin --use-device-code流程如下CLI Identity Center (AWS) 你的浏览器(任意设备) |-- RegisterClient ---------------| | |-- clientId / clientSecret ------| | |-- StartDeviceAuthorization -----| | |-- deviceCode, userCode, | | | verificationUri, interval ----| | | 屏幕显示网址 userCode ---------------(你手动打开)-----------------| | |---- 登录 输入 userCode 授权 --| | | 服务端将 deviceCode 标记为已授权 | |-- CreateToken(deviceCode) ------| (每隔 interval 秒轮询) | |-- AuthorizationPending ---------| | |-- CreateToken(deviceCode) ------| | |-- accessToken refreshToken ---| |StartDeviceAuthorization返回两个码。deviceCode是一个很长的密钥只保存在 CLI 手中用于轮询。userCode是一个短码比如ABCD-EFGH显示给用户在网页上输入。验证网址同样由 Identity Center 返回通常位于组织门户域名下。CLI 轮询的是https://oidc.sso_region.amazonaws.com/token上的CreateToken接口授权类型为urn:ietf:params:oauth:grant-type:device_code。在用户完成授权之前接口返回AuthorizationPendingException轮询过快时返回SlowDownException授权完成后返回 token。这套机制的核心是两台设备之间从不直接通信AWS 服务端是会合点。服务端记录了deviceCode和userCode的对应关系。你在任意设备上以自己的身份输入userCode服务端就把对应的deviceCode标记为已被该用户授权CLI 再拿deviceCode来取 token。整个过程只要求 CLI 能主动访问外网不需要本地浏览器也不需要任何入站端口。这也带来了一个特有的风险设备码钓鱼。攻击者可以自己发起一次设备授权再把userCode发给你。你一旦输入并授权token 就落入攻击者的 CLI 中。原则很简单只输入你自己刚刚发起的验证码。2.6sso:account:access的含义前面多次出现的sso:account:access是 CLI 注册客户端时申请的 OAuth scope。它声明这个 token 可以用来访问 AWS 访问门户的账号功能包括列出账号、列出角色、获取角色凭证。需要强调的是它不是 IAM 权限也不决定你能访问哪些账号。你能进入哪些账号和角色由管理员在 Identity Center 中分配的 Permission Set 决定。scope 只限定 token 的用途类别。它是默认值绝大多数情况下无需修改。使用新格式配置时带 scope 注册的客户端会获得 refresh token这正是会话能够自动续期的原因。三、阶段二从 SSO token 到 AWS 临时凭证拿到 SSO token 后还不能直接调用 AWS 服务。AWS API 要求使用 SigV4 签名签名需要 AccessKeyId 和 SecretAccessKey。从 token 到凭证的转换发生在你执行第一条业务命令的时候。3.1 实际调用链aws s3 ls --profile dev-admin ├─ 1. 从 ~/.aws/sso/cache/ 读取 SSO access token │ 过期时用 refresh token 调用 CreateToken 自动续期 ├─ 2. 调用 GetRoleCredentials │ 地址: portal.sso.region.amazonaws.com/federation/credentials │ 参数: account_id、role_name │ 认证: 请求头 x-amz-sso_bearer_token │ └─ Identity Center 在服务端内部取得 AWSReservedSSO_权限集_xxx 角色的临时凭证 ├─ 3. 收到 AccessKeyId / SecretAccessKey / SessionToken / Expiration │ 缓存到 ~/.aws/cli/cache/ └─ 4. 用临时凭证进行 SigV4 签名调用 S3一个常见的误解是CLI 先调用 AssumeRole再调用 GetRoleCredentials。实际上CLI 只调用了GetRoleCredentials而且这个请求不使用 SigV4 签名因为此时还没有任何 AWS 凭证它只凭 SSO 的 bearer token 认证。角色扮演发生在 AWS 服务端内部对 CLI 不可见。AWS 没有完整公开服务端的实现但成员账号中AWSReservedSSO_*角色的信任策略提供了线索{Effect:Allow,Principal:{Federated:arn:aws:iam::123456789012:saml-provider/AWSSSO_xxxx_DO_NOT_DELETE},Action:[sts:AssumeRoleWithSAML,sts:TagSession]}这表明 Identity Center 底层是基于 SAML 联合身份让用户进入这个角色的。3.2 STS 与临时凭证STSSecurity Token Service是 AWS 签发临时安全凭证的服务。一组临时凭证包含AccessKeyId、SecretAccessKey、SessionToken和Expiration四部分其中SessionToken是长期 Access Key 所没有的。STS 的主要接口如下API用途AssumeRole扮演 IAM 角色常用于跨账号访问AssumeRoleWithSAML用 SAML 断言换取角色凭证AssumeRoleWithWebIdentity用 OIDC token 换取凭证如 EKS IRSA、GitHub ActionsGetSessionTokenIAM 用户换取临时凭证常配合 MFAGetCallerIdentity查询当前身份DecodeAuthorizationMessage解码权限拒绝时的加密错误信息GetRoleCredentials返回的凭证与 STS 签发的凭证形式完全一致因此通过 SSO 登录后你的身份表现为一个已扮演的角色。3.3 用get-caller-identity确认身份aws sts get-caller-identity--profiledev-admin{UserId:AROAXXXXXXXXXXXX:aliceexample.com,Account:123456789012,Arn:arn:aws:sts::123456789012:assumed-role/AWSReservedSSO_AdministratorAccess_1a2b3c4d/aliceexample.com}ARN 中的assumed-role/AWSReservedSSO_权限集名_随机串/用户名印证了上一节的分析你实际使用的是 Identity Center 自动创建的 IAM 角色会话名就是你的 SSO 用户名。这个命令有一个重要特性它不需要任何 IAM 权限即使显式 Deny 也无法阻止。因此只要它报错问题一定出在凭证本身比如 token 过期、profile 写错或环境变量未生效而不是权限不足。这使它成为排查凭证问题时的第一个命令。3.4 角色链真正的两步走如果在 SSO profile 的基础上再扮演另一个角色例如[profile cross-account] role_arn arn:aws:iam::999999999999:role/DeployRole source_profile dev-admin那么 CLI 会先通过GetRoleCredentials拿到dev-admin的凭证再用这组凭证调用sts:AssumeRole进入DeployRole。这种模式称为角色链。需要注意角色链得到的会话最长只有 1 小时不受目标角色最大会话时长设置的影响。四、全景回顾把整条链路串起来aws configure sso写下如何登录和进入哪个角色两层配置。aws sso login通过 OAuth 拿到 SSO token。有本地浏览器时使用授权码 PKCE 流程授权码借助浏览器的 302 重定向回到本机回环端口没有浏览器时使用设备码流程以 AWS 服务端为会合点完成授权。之后每次调用 AWS 服务CLI 都用 token 调用GetRoleCredentials换取由服务端代为扮演角色而得到的临时凭证再以 SigV4 签名发出请求。这套设计的安全性建立在几个环环相扣的原则之上本地只保存会过期的 token 和临时凭证不保存长期密钥回环地址把回调限制在本机内部PKCE 防止授权码在本机被截获设备码流程用服务端会合代替了设备间的直接通信。理解了这些原理无论是排查浏览器授权后 CLI 没反应还是在远程服务器、CI 环境中设计凭证方案都能做到心中有数。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑