- 后端
- 认证鉴权
- 单点登录
【免费下载链接】cas
Apereo CAS - Identity & Single Sign On for all earthlings and beyond.
本指南聚焦 Apereo CAS 与 Amazon Web Services 的专用集成方案,核心是让 CAS 作为统一身份认证入口,通过cas-server-support-aws模块暴露的awsStsActuator 端点,为已认证用户签发 AWS Security Token Service(STS)临时安全凭证,从而把 CAS 的认证与授权能力无缝衔接到 AWS 生态(如 AWS CLI、各类 AWS 服务调用)。读完本文,你将掌握如何在 CAS Overlay 中引入该模块、完整配置cas.amazon-sts.*属性、理解AssumeRole与GetSessionToken两种凭证签发策略,并能通过源码级分析把握其底层调用链与安全边界。
概览:CAS 与 AWS 的集成策略
Apereo CAS 提供了一套专门针对 AWS 的集成机制,支持将 CAS 认证后的主体(Principal)转换为 AWS 临时安全凭证。该功能通过cas-server-support-aws模块实现,在 Overlay 工程中添加如下依赖即可启用:
implementation "org.apereo.cas:cas-server-support-aws"该模块的自动装配入口为 CasAmazonCoreAutoConfiguration,它通过@ConditionalOnFeatureEnabled(feature = CasFeatureModule.FeatureCatalog.Core, module = "aws")控制模块启用,并以@ConditionalOnAvailableEndpoint按需注册awsSts端点 Bean。也就是说,只有当端点被显式暴露且模块被启用时,相关能力才会加载,体现了 CAS 一贯的“按需装配”设计。
从依赖管理看,cas-server-support-aws在 gradle/dependencies.gradle 中汇聚了 AWS SDK 核心库(software.amazon.awssdk:core)、awssts、verifiedpermissions等组件,并对commons-logging、httpclient、jackson等传递依赖做了统一排除,避免与 CAS 自身依赖冲突。
配置:cas.amazon-sts.*属性详解
所有与 STS 相关的配置均以cas.amazon-sts为前缀。这些属性定义于 AmazonSecurityTokenServiceProperties,并继承自 BaseAmazonWebServicesProperties。核心属性如下:
| 配置键 | 类型 | 说明 |
|---|---|---|
cas.amazon-sts.credential-access-key | String(必填) | AWS Access Key,用于向 STS 发起认证;支持 Spring 表达式语言(SpEL)解析 |
cas.amazon-sts.credential-secret-key | String(必填) | AWS Secret Key,配合 Access Key 使用;同样支持 SpEL |
cas.amazon-sts.region | String(必填) | AWS 区域标识,例如us-east-1;留空时回退为aws-global |
cas.amazon-sts.endpoint | String(必填) | AWS 自定义端点地址;可用于指向本地模拟服务(如 LocalStack) |
cas.amazon-sts.profile-name | String | 使用的 AWS 配置文件(credentials 文件)中的 Profile 名称 |
cas.amazon-sts.profile-path | String | AWS Profile 文件的自定义路径 |
cas.amazon-sts.principal-attribute-name | String | 必须存在于认证主体属性中的属性名,用于授权校验 |
cas.amazon-sts.principal-attribute-value | String(正则) | 对主体属性值执行的正则匹配模式,用于进一步收紧授权 |
cas.amazon-sts.rbac-enabled | boolean | 是否启用基于角色的凭证获取(对应 STSAssumeRole),默认false |
cas.amazon-sts.max-connections | int | HTTP 最大连接数,默认10 |
cas.amazon-sts.connection-timeout | Duration | 连接超时,默认5000(毫秒) |
cas.amazon-sts.socket-timeout | Duration | Socket 超时,默认5000(毫秒) |
cas.amazon-sts.client-execution-timeout | Duration | 客户端执行超时,默认10000(毫秒) |
cas.amazon-sts.use-reaper | boolean | 是否启用空闲连接回收(Reaper) |
cas.amazon-sts.proxy-host | String | 可选代理主机地址 |
cas.amazon-sts.proxy-username/proxy-password | String | 代理认证凭据 |
cas.amazon-sts.retry-mode | String | 重试模式,可选STANDARD/LEGACY,默认STANDARD |
cas.amazon-sts.local-address | String | 绑定本地地址 |
其中principal-attribute-name与principal-attribute-value的语义在源码中体现得非常清晰:AmazonSecurityTokenServiceEndpoint 的authorizePrincipal方法会先检查主体属性中是否包含指定属性名,若属性值非空,还会用RegexUtils.find(amz.getPrincipalAttributeValue(), value.toString())做正则匹配,任何一步失败都会返回401 Unauthorized与 "Authorization failure"。
一个完整的配置示例:
cas.amazon-sts.credential-access-key=${AWS_ACCESS_KEY} cas.amazon-sts.credential-secret-key=${AWS_SECRET_KEY} cas.amazon-sts.region=us-east-1 cas.amazon-sts.profile-name=default cas.amazon-sts.max-connections=20 cas.amazon-sts.connection-timeout=10000 cas.amazon-sts.retry-mode=STANDARD cas.amazon-sts.rbac-enabled=true cas.amazon-sts.principal-attribute-name=awsroles cas.amazon-sts.principal-attribute-value=arn:aws:iam::.+:role/.+AmazonSecurityTokenServiceProperties类通过@RequiresModule(name = "cas-server-support-aws")标注了前置模块依赖,确保这些配置只有在相应模块存在时才生效。
Actuator 端点:awsSts
CAS 通过 Actuator 端点awsSts对外提供临时凭证签发能力,端点类 AmazonSecurityTokenServiceEndpoint 标注了@Endpoint(id = "awsSts", defaultAccess = Access.NONE),默认不开放访问,需要显式配置:
management.endpoint.awsSts.access=UNRESTRICTED management.endpoints.web.exposure.include=awsSts调用方式
awsSts端点只接受 HTTPPOST,请求体采用application/x-www-form-urlencoded格式。认证与授权信息通过表单字段携带,支持以下参数:
| 参数 | 位置 | 说明 |
|---|---|---|
username/password | 表单 | 调用方的 CAS 凭据,端点会先通过RestAuthenticationService完成认证 |
duration | 表单 | 临时凭证有效期(ISO-8601 时长),默认PT15S(15 秒) |
token | Query | MFA 令牌码,用于GetSessionToken/AssumeRole的 MFA 校验 |
serialNumber | Query | MFA 设备序列号(可选) |
roleArn | Query | 目标角色 ARN,RBAC 模式下指定具体角色 |
profile | Query | 覆盖默认的 AWS Profile 名称 |
典型的curl调用:
curl -k -X POST 'https://localhost:8443/cas/actuator/awsSts' \ -H 'Content-Type: application/x-www-form-urlencoded' \ -d 'username=casuser&password=Mellon&duration=PT15S'成功时端点返回200 OK,响应体是可直接写入~/.aws/credentials的 INI 格式内容:
[default] aws_access_key_id=... aws_secret_access_key=... aws_session_token=... region=us-east-1这一输出格式由端点内部的createOutputResponse方法构造:它依次写入aws_access_key_id、aws_secret_access_key、aws_session_token,并在region为空时回退为Region.AWS_GLOBAL(即aws-global),与 AWS SDK 的ProfileProperty常量一一对应,保证了输出可直接被 AWS CLI 读取。
仓库中的 Puppeteer 端到端场景 aws-sts-credentials/script.js 验证了这一点:它向/cas/actuator/awsSts提交username=casuser&password=Mellon&duration=PT15S,并断言响应中包含aws_access_key_id、aws_secret_access_key、aws_session_token三个键。对应的 script.json 展示了配套的运行时参数(--cas.amazon-sts.endpoint=http://127.0.0.1:4566指向 LocalStack 模拟服务)。
底层调用链
端点的执行逻辑分为四步,源码路径为 AmazonSecurityTokenServiceEndpoint.java#L109-L181:
- 认证:调用
RestAuthenticationService#authenticate(requestBody, request, response)认证表单中的凭据,失败即返回401 Authentication failed; - 授权:调用
authorizePrincipal校验主体属性(见上文),失败返回401 Authorization failure; - 构建 STS 客户端:通过
ChainingAWSCredentialsProvider.getInstance(...)解析凭证链,再经AmazonClientConfigurationBuilder.prepareSyncClientBuilder(...)应用区域、端点、超时、代理、重试策略等配置; - 签发凭证:根据
rbacEnabled分支,分别走AssumeRoleRequest或GetSessionTokenRequest并返回格式化输出。
AWS 客户端构建细节
AmazonClientConfigurationBuilder 承担了 AWS SDK 客户端的统一装配:使用 Apache HTTP 客户端,可配置代理(ProxyConfiguration)、空闲连接回收(useIdleConnectionReaper)、三类超时(socket / connection / connection-acquisition),并支持ClientOverrideConfiguration注入RetryMode;region为空时回退Region.AWS_GLOBAL,endpoint非空时通过endpointOverride覆盖目标地址。此外,模块还提供 AmazonEnvironmentAwareClientBuilder,供其他 AWS 集成以${prefix}.credential-access-key之类的 Spring Environment 属性方式构建客户端。
临时安全凭证获取策略之一:Roles(AssumeRole)
在cas.amazon-sts.rbac-enabled=true时,CAS 走 STS 的AssumeRoleAPI 操作获取临时安全凭证。该方式通常用于账户内授权或跨账户访问。
角色信息以“预定义属性”的形式附着于认证主体之上。从 AmazonSecurityTokenServiceEndpoint.java#L141-L171 可以梳理出完整的角色解析逻辑:
- 端点从主体属性中取出
principal-attribute-name对应的属性值作为候选角色列表(值即roleArn列表); - 若主体没有任何角色属性,返回
401 No roles are available for the authenticated principal; - 若候选角色多于一个,且调用方未通过
roleArn参数指定,返回401并列出当前角色; - 调用方指定的
roleArn必须精确匹配候选角色之一(角色名不做正则匹配,测试用例verifyRoleArnIsNotTreatedAsRegex专门验证了传入arn:aws:iam::.*这类正则无法通过校验),否则返回401; - 最终构建
AssumeRoleRequest,roleSessionName由 CAS 自动生成(UUID.randomUUID().toString()),同时透传serialNumber与tokenCode以支持 MFA 加固。
关于跨账户访问,AWS 的信任关系约束仍然适用:要担任其他账户的角色,你的账户必须被该角色信任,信任关系在角色创建时定义于角色信任策略中;同时,用户所在账户的管理员必须为该用户附加允许调用该操作(针对目标账户角色 ARN)的策略。
角色属性值需要符合 AWS IAM 资源命名规则,其合法字符集为[\u0009\u000A\u000D\u0020-\u007E\u0085\u00A0-\uD7FF\uE000-\uFFFD\u10000-\u10FFFF]+。
临时安全凭证获取策略之二:Session Tokens(GetSessionToken)
当cas.amazon-sts.rbac-enabled未开启(默认)时,端点走 STS 的GetSessionTokenAPI 操作。其典型应用场景是必须通过多因素认证(MFA)的用户:已认证用户可通过 CAS 提供的多因素认证触发器来满足并启动 MFA 流程,相关触发机制参见 多因素认证触发器指南。
从源码看,GetSessionToken 分支 会构建GetSessionTokenRequest,携带durationSeconds、serialNumber、tokenCode,然后调用client.getSessionToken(...)返回凭证。
仓库中的 Puppeteer 场景 aws-sts-credentials-mfa/script.js 展示了带 MFA 的完整调用:先为casuser获取 Duo Security 的 bypass code,随后在 POST 请求中追加passcode=${bypassCode}参数提交给awsSts端点,并断言返回的临时凭证包含三项关键字段。
值得注意的是,AWS 官方对GetSessionToken的权限说明是:用户获取会话令牌不需要任何权限,该 API 的用途就是通过 MFA 对用户进行身份验证,策略无法控制认证类操作。
权限边界与安全建议
授予的权限
AWS 官方对临时凭证权限的规定如下:
若 API 以 IAM 用户的凭据调用,则临时安全凭证拥有与该 IAM 用户相同的权限;同理,若以 AWS 账户根用户凭据调用,则临时安全凭证拥有根用户权限。
因此 AWS 建议不要使用根用户凭据调用该 API,而应创建具备所需最小权限的 IAM 用户,再以这些 IAM 用户进行日常交互。
使用限制
需要注意,通过GetSessionToken获得的临时凭证不能用于调用 IAM 或 AWS STS 的 API 操作,但可以用于调用其他 AWS 服务的 API。
基于主体属性的授权校验
除 AWS 侧权限外,CAS 还在应用层做了双重防线:端点要求认证主体的属性满足principal-attribute-name/principal-attribute-value的约束(属性缺失或值不匹配均返回401)。测试类 AmazonSecurityTokenServiceEndpointTests 覆盖了以下场景:
- 属性存在但值不匹配正则(
groupMembership=some-value对^un[A-Z]known.*)→401; - 属性名不存在(
principal-attribute-name=unknown)→401; - 未配置授权属性时,合法凭据直接签发 →
200,错误密码 →401; - RBAC 模式下单一角色不可被覆盖、多角色必须显式指定、未知角色与正则角色均被拒绝 →
401。
将临时凭证接入 AWS CLI
签发成功后,为方便使用,可以直接将上面生成的临时 AWS 访问凭据复制粘贴,设置为环境变量,或保存到~/.aws/credentials文件中,AWS CLI 会根据 Profile 名称自动加载识别:
# 方式一:写入凭据文件(内容即 awsSts 端点返回的 INI 文本) cat <<EOF >> ~/.aws/credentials [default] aws_access_key_id=... aws_secret_access_key=... aws_session_token=... EOF # 方式二:导出环境变量 export AWS_ACCESS_KEY_ID=... export AWS_SECRET_ACCESS_KEY=... export AWS_SESSION_TOKEN=...关于 AWS CLI 的凭据存储约定:AWS CLI 将通过aws configure指定的敏感凭据信息保存在主目录.aws文件夹下的credentials文件中,而敏感度较低的配置选项则保存在同目录下的config文件中。了解更多 AWS CLI 用法,可参阅 AWS 官方 CLI 用户指南。
延伸:基于 AWS Verified Permissions 的服务访问策略
作为cas-server-support-aws模块的延伸能力(非 STS 端点本身),CAS 7.0.0 起还提供了 AmazonVerifiedPermissionsRegisteredServiceAccessStrategy,将 AWS Verified Permissions(AVP)接入 CAS 的服务访问控制:当该策略被配置到注册服务上时,CAS 会把认证主体的principalId、服务 ID 及上下文属性构造成IsAuthorizedRequest(含policyStoreId、actionId与基于主体/服务属性构建的ContextDefinition),调用 AVP 的isAuthorized决策接口,仅当决策为ALLOW时才放行服务访问。该策略同样支持通过credential-access-key/credential-secret-key/region等 SpEL 表达式配置 AWS 凭据,适合需要把 CAS 授权策略迁移到云原生策略引擎的场景。
小结
Apereo CAS 的 AWS 集成以cas-server-support-aws模块为桥梁,通过awsStsActuator 端点将 CAS 认证与 AWS STS 临时凭证签发打通:既支持基于角色属性(AssumeRole)的 RBAC 式授权,也支持面向 MFA 场景的会话令牌(GetSessionToken)签发,并在应用层叠加主体属性校验、在输出层直接生成 AWS CLI 可识别的凭据文件格式。配合源码中的凭证链解析(WebIdentity → InstanceProfile → Profile → 系统属性 → 环境变量 → 静态凭据 → 容器 → 实例配置文件)与完整的端到端测试(Puppeteer 与 JUnit),这套方案为“CAS 认证 + AWS 授权”的联合身份场景提供了开箱即用且可审计的实现路径。
- 后端
- 认证鉴权
- 单点登录
【免费下载链接】cas
Apereo CAS - Identity & Single Sign On for all earthlings and beyond.
相关推荐
使用 AWS SDK for Go 实现 STS AssumeRole:获取临时安全凭证的完整实战指南
使用 AWS SDK for Go 实现 STS AssumeRole:获取临时安全凭证的完整实战指南 导读 本文以 go/sts https://link.g
示例工程教程后端Gimme AWS Creds:简化AWS临时凭证获取的利器
Gimme AWS Creds:简化AWS临时凭证获取的利器 项目介绍 在现代云环境中,安全性和便捷性是开发者关注的两大核心问题。 Gimme AWS Cred
MinIO 与 WSO2 Identity Server 集成:通过 STS Client Grants 获取临时凭证
MinIO 与 WSO2 Identity Server 集成:通过 STS Client Grants 获取临时凭证 本篇指南基于 MinIO 仓库中的 do
后端存储对象存储分布式存储云原生
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考