-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #72 from AlibabaCloudLandingZone/solution-cross-ac…
…count-sts-token/0.0.1 solution-cross-account-sts-token/0.0.1
- Loading branch information
Showing
13 changed files
with
634 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
target/ | ||
!.mvn/wrapper/maven-wrapper.jar | ||
!**/src/main/**/target/ | ||
!**/src/test/**/target/ | ||
|
||
### IntelliJ IDEA ### | ||
.idea/ | ||
|
||
### Eclipse ### | ||
.apt_generated | ||
.classpath | ||
.factorypath | ||
.project | ||
.settings | ||
.springBeans | ||
.sts4-cache | ||
|
||
### NetBeans ### | ||
/nbproject/private/ | ||
/nbbuild/ | ||
/dist/ | ||
/nbdist/ | ||
/.nb-gradle/ | ||
build/ | ||
!**/src/main/**/build/ | ||
!**/src/test/**/build/ | ||
|
||
### VS Code ### | ||
.vscode/ | ||
|
||
### Mac OS ### | ||
.DS_Store | ||
|
||
### Terraform ### | ||
.terraform | ||
.terraform.lock.hcl | ||
*.tfstate |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
# 通过角色扮演实现跨账号临时凭证的获取和使用 | ||
|
||
过角色链式扮演的方式,使应用基于STS临时凭证访问其他账号的云资源,保证全链路无需透露长期AccessKey,既可减少密钥泄露的风险,也可借助访问控制RAM精细化控制资源访问权限,避免权限过度分配。 | ||
|
||
本方案提供Java/Terraform等代码示例,客户能够快速完成应用改造,减少开发和部署的复杂度。 | ||
|
||
## 使用步骤 | ||
|
||
### 目录结构说明 | ||
|
||
``` | ||
. | ||
├── code-example | ||
│ ├── java // Java代码示例 | ||
│ └── terraform // Terraform代码示例 | ||
└── deployment // 自动化部署代码 | ||
└── create-role-cross-account | ||
``` | ||
|
||
### Java代码示例 | ||
|
||
``` | ||
. | ||
└── common | ||
└── src/main/java | ||
└── org | ||
└── example | ||
├── sdk1_0 // 1.0版本SDK简单示例 | ||
└── sdk2_0 // 2.0版本SDK简单示例 | ||
``` | ||
|
||
执行前,请确保运行环境中已配置好Java和Maven。 | ||
|
||
1. Java Development Kit (JDK):确保已安装Java 8或更高版本。 | ||
2. Apache Maven:确保已安装Maven 3.6.0或更高版本。 | ||
|
||
### 自动化部署代码 | ||
|
||
本方案提供了基于ROS的批量跨账号创建角色的Terraform自动化代码,其模版入参输入: | ||
|
||
| **参数名称** | **参数值示例** | **描述** | | ||
| --- | --- | --- | | ||
| role_name | CentralizedOperationRole | 批量创建的角色的名称 | | ||
| policy_name | CentralizedOperationRolePolicy | 绑定到该角色的权限策略的名称 | | ||
| policy_document | {"Version":"1","Statement":[{"Action":"ecs:*","Resource":"*","Effect":"Allow"}]} | 绑定到该角色的权限策略内容。既跨账号资源操作的所有权限。| | ||
| assume_role_principal_account | 1254004******** | 角色的可信账号,既允许扮演到该新建角色的账号,不填默认为当前账号(运维账号)| | ||
| assume_role_principal_type | RamRole | 可信账号下允许扮演该新建角色的对象的类型,枚举值:RamRole(RAM角色)、RamUser(RAM用户)| | ||
| assume_role_principal_name | EcsInstanceRole | 可信账号下允许扮演该新建角色的对象的名称,如果授信对象类型为RamRole(RAM角色),那么请填写对应RAM角色名称,如果RamUser(RAM用户),那么请填写对应RAM用户名称。请确保填写的RAM角色或者RAM用户在可信账号下已经存在,否则会创建失败。| |
52 changes: 52 additions & 0 deletions
52
solution/solution-cross-account-sts-token/code-example/java/common/pom.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<groupId>org.example</groupId> | ||
<artifactId>cross-account-sts-token</artifactId> | ||
<version>1.0-SNAPSHOT</version> | ||
<packaging>jar</packaging> | ||
|
||
<properties> | ||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
<maven.compiler.source>1.8</maven.compiler.source> | ||
<maven.compiler.target>1.8</maven.compiler.target> | ||
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion> | ||
<exec.cleanupDaemonThreads>false</exec.cleanupDaemonThreads> | ||
</properties> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>com.alibaba.fastjson2</groupId> | ||
<artifactId>fastjson2</artifactId> | ||
<version>2.0.51</version> | ||
</dependency> | ||
<!--2.0 sdk--> | ||
<dependency> | ||
<groupId>com.aliyun</groupId> | ||
<artifactId>sts20150401</artifactId> | ||
<version>1.1.4</version> | ||
</dependency> | ||
<!--1.0 sdk--> | ||
<dependency> | ||
<groupId>com.aliyun</groupId> | ||
<artifactId>aliyun-java-sdk-sts</artifactId> | ||
<version>3.1.2</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.aliyun</groupId> | ||
<artifactId>aliyun-java-sdk-core</artifactId> | ||
<version>[4.0.0,5.0.0)</version> | ||
</dependency> | ||
<!-- Requires: version >= 0.3.4 --> | ||
<!-- 推荐使用最新版本 --> | ||
<!--获取所有已发布的版本列表,请参见https://github.com/aliyun/credentials-java/blob/master/ChangeLog.txt--> | ||
<dependency> | ||
<groupId>com.aliyun</groupId> | ||
<artifactId>credentials-java</artifactId> | ||
<version>0.3.4</version> | ||
</dependency> | ||
</dependencies> | ||
</project> |
81 changes: 81 additions & 0 deletions
81
...sts-token/code-example/java/common/src/main/java/org/example/sdk1_0/AssumeRoleSample.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
package org.example.sdk1_0; | ||
|
||
import com.alibaba.fastjson2.JSON; | ||
import com.aliyun.credentials.models.CredentialModel; | ||
import com.aliyuncs.DefaultAcsClient; | ||
import com.aliyuncs.IAcsClient; | ||
import com.aliyuncs.auth.BasicSessionCredentials; | ||
import com.aliyuncs.auth.STSAssumeRoleSessionCredentialsProvider; | ||
import com.aliyuncs.exceptions.ClientException; | ||
import com.aliyuncs.exceptions.ServerException; | ||
import com.aliyuncs.profile.DefaultProfile; | ||
import com.aliyuncs.sts.model.v20150401.GetCallerIdentityRequest; | ||
import com.aliyuncs.sts.model.v20150401.GetCallerIdentityResponse; | ||
|
||
public class AssumeRoleSample { | ||
public static void main(String[] args) { | ||
// 初始化凭据客户端,使用Credentials工具,保证您的应用程序本身是无AK的 | ||
// 借助Credentials工具的默认凭据链,您可以用同一套代码,通过程序之外的配置来控制不同环境下的凭据获取方式 | ||
// 当您在初始化凭据客户端不传入任何参数时,Credentials工具将会尝试按照如下顺序查找相关凭据信息(优先级由高到低): | ||
// 1. 使用系统属性 | ||
// 2. 使用环境变量 | ||
// 3. 使用OIDC RAM角色 | ||
// 4. 使用配置文件 | ||
// 5. 使用ECS实例RAM角色(需要通过环境变量 ALIBABA_CLOUD_ECS_METADATA 指定 ECS 实例角色名称;通过环境变量 ALIBABA_CLOUD_ECS_IMDSV2_ENABLE=true 开启在加固模式下获取STS Token) | ||
// 详情请参考:https://help.aliyun.com/zh/sdk/developer-reference/v2-manage-access-credentials#3ca299f04bw3c | ||
// 要使用默认凭据链,初始化 Client 时,必须使用空的构造函数,不能配置 Config 入参 | ||
// 除了使用默认凭据链,您也可以在代码中显式配置,来初始化凭据客户端 | ||
// 详情请参考:https://help.aliyun.com/zh/sdk/developer-reference/v2-manage-access-credentials#a9e9aa404bzfy | ||
com.aliyun.credentials.Client credentialClient = new com.aliyun.credentials.Client(); | ||
|
||
// 以华东1(杭州)为例 | ||
DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou"); | ||
// 用凭据客户端初始化角色扮演的CredentialsProvider:STSAssumeRoleSessionCredentialsProvider,实现跨账号角色扮演 | ||
// 该CredentialsProvider支持自动刷新STS Token | ||
STSAssumeRoleSessionCredentialsProvider provider = new STSAssumeRoleSessionCredentialsProvider( | ||
() -> { | ||
// 保证线程安全,从 CredentialModel 中获取 ak/sk/security token | ||
CredentialModel credentialModel = credentialClient.getCredential(); | ||
String ak = credentialModel.getAccessKeyId(); | ||
String sk = credentialModel.getAccessKeySecret(); | ||
String token = credentialModel.getSecurityToken(); | ||
return new BasicSessionCredentials(ak, sk, token); | ||
}, | ||
// 请替换为您实际要扮演的RAM角色ARN | ||
// 格式为 acs:ram::${账号 ID}:role/${角色名称} | ||
"<role-arn>", | ||
profile | ||
) | ||
// 角色会话名称 | ||
.withRoleSessionName("WellArchitectedSolutionDemo") | ||
// STS Token 有效期,单位:秒 | ||
.withRoleSessionDurationSeconds(3600L); | ||
|
||
// 初始化SDK 1.0客户端 | ||
IAcsClient iAcsClient = new DefaultAcsClient(profile, provider); | ||
|
||
// 调用API,跨账号进行资源操作 | ||
// 以调用GetCallerIdentity获取当前调用者身份信息为例 | ||
GetCallerIdentityRequest getCallerIdentityRequest = new GetCallerIdentityRequest(); | ||
try { | ||
GetCallerIdentityResponse getCallerIdentityResponse = iAcsClient.getAcsResponse(getCallerIdentityRequest); | ||
System.out.println(JSON.toJSONString(getCallerIdentityResponse)); | ||
} catch (ServerException e) { | ||
// 示例仅做打印展示。请重视异常处理,在工程项目中切勿直接忽略异常。 | ||
// 打印整体的错误输出 | ||
e.printStackTrace(); | ||
// 打印错误码 | ||
System.out.println(e.getErrCode()); | ||
// 打印 RequestId | ||
System.out.println(e.getRequestId()); | ||
// 打印错误信息 | ||
System.out.println(e.getErrMsg()); | ||
} catch (ClientException e) { | ||
// 示例仅做打印展示。请重视异常处理,在工程项目中切勿直接忽略异常。 | ||
// 打印整体的错误输出 | ||
e.printStackTrace(); | ||
// 打印错误码 | ||
System.out.println(e.getMessage()); | ||
} | ||
} | ||
} |
99 changes: 99 additions & 0 deletions
99
...sts-token/code-example/java/common/src/main/java/org/example/sdk2_0/AssumeRoleSample.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
package org.example.sdk2_0; | ||
|
||
import com.aliyun.credentials.models.CredentialModel; | ||
import com.aliyun.credentials.utils.ParameterHelper; | ||
import com.aliyun.sts20150401.models.AssumeRoleRequest; | ||
import com.aliyun.sts20150401.models.AssumeRoleResponse; | ||
import com.aliyun.sts20150401.models.AssumeRoleResponseBody; | ||
import com.aliyun.sts20150401.models.GetCallerIdentityResponse; | ||
import com.aliyun.tea.TeaException; | ||
import com.aliyun.teautil.models.RuntimeOptions; | ||
import com.alibaba.fastjson2.JSON; | ||
|
||
public class AssumeRoleSample { | ||
|
||
public static void main(String[] args) throws Exception { | ||
// 初始化凭据客户端,使用Credentials工具,保证您的应用程序本身是无AK的 | ||
// 借助Credentials工具的默认凭据链,您可以用同一套代码,通过程序之外的配置来控制不同环境下的凭据获取方式 | ||
// 当您在初始化凭据客户端不传入任何参数时,Credentials工具将会尝试按照如下顺序查找相关凭据信息(优先级由高到低): | ||
// 1. 使用系统属性 | ||
// 2. 使用环境变量 | ||
// 3. 使用OIDC RAM角色 | ||
// 4. 使用配置文件 | ||
// 5. 使用ECS实例RAM角色(需要通过环境变量 ALIBABA_CLOUD_ECS_METADATA 指定 ECS 实例角色名称;通过环境变量 ALIBABA_CLOUD_ECS_IMDSV2_ENABLE=true 开启在加固模式下获取STS Token) | ||
// 详情请参考:https://help.aliyun.com/zh/sdk/developer-reference/v2-manage-access-credentials#3ca299f04bw3c | ||
// 要使用默认凭据链,初始化 Client 时,必须使用空的构造函数,不能配置 Config 入参 | ||
// 除了使用默认凭据链,您也可以在代码中显式配置,来初始化凭据客户端 | ||
// 详情请参考:https://help.aliyun.com/zh/sdk/developer-reference/v2-manage-access-credentials#a9e9aa404bzfy | ||
com.aliyun.credentials.Client credentialClient = new com.aliyun.credentials.Client(); | ||
|
||
// 跨账号角色扮演获取STS Token | ||
// 如果您缓存了该STS Token,需要特别注意STS Toke的到期时间,避免缓存时间过长而STS Token过期导致程序错误 | ||
CredentialModel assumeRoleCredentialModel = createAssumeRoleCredential(credentialClient); | ||
|
||
// 调用API,跨账号进行资源操作 | ||
// 以调用GetCallerIdentity获取当前调用者身份信息为例 | ||
com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config() | ||
.setAccessKeyId(assumeRoleCredentialModel.getAccessKeyId()) | ||
.setAccessKeySecret(assumeRoleCredentialModel.getAccessKeySecret()) | ||
.setSecurityToken(assumeRoleCredentialModel.getSecurityToken()) | ||
// 地域,以华东1(杭州)为例 | ||
.setRegionId("cn-hangzhou"); | ||
com.aliyun.sts20150401.Client stsClient = new com.aliyun.sts20150401.Client(config); | ||
RuntimeOptions runtimeOptions = new RuntimeOptions() | ||
// 开启自动重试机制,只会对超时等网络异常进行重试 | ||
.setAutoretry(true) | ||
// 设置自动重试次数,默认3次 | ||
.setMaxAttempts(3); | ||
|
||
try { | ||
GetCallerIdentityResponse getCallerIdentityResponse = stsClient.getCallerIdentityWithOptions(runtimeOptions); | ||
System.out.println(JSON.toJSONString(getCallerIdentityResponse)); | ||
} catch (TeaException e) { | ||
// 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。 | ||
e.printStackTrace(); | ||
// 打印错误码 | ||
System.out.println(e.getCode()); | ||
// 打印错误信息,错误信息中包含 RequestId | ||
System.out.println(e.getMessage()); | ||
// 打印服务端返回的具体错误内容 | ||
System.out.println(e.getData()); | ||
} | ||
} | ||
|
||
public static CredentialModel createAssumeRoleCredential(com.aliyun.credentials.Client credentialClient) throws Exception { | ||
com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config() | ||
.setCredential(credentialClient) | ||
// 地域,以华东1(杭州)为例 | ||
.setRegionId("cn-hangzhou"); | ||
|
||
com.aliyun.sts20150401.Client stsClient = new com.aliyun.sts20150401.Client(config); | ||
RuntimeOptions runtimeOptions = new RuntimeOptions() | ||
// 开启自动重试机制,只会对超时等网络异常进行重试 | ||
.setAutoretry(true) | ||
// 设置自动重试次数,默认3次 | ||
.setMaxAttempts(3); | ||
AssumeRoleRequest assumeRoleRequest = new AssumeRoleRequest() | ||
// 请替换为您实际要扮演的RAM角色ARN | ||
// 格式为 acs:ram::${账号 ID}:role/${角色名称} | ||
.setRoleArn("<role-arn>") | ||
// 角色会话名称 | ||
.setRoleSessionName("WellArchitectedSolutionDemo") | ||
// 设置会话权限策略,进一步限制STS Token 的权限,如果指定该权限策略,则 STS Token 最终的权限策略取 RAM 角色权限策略与该权限策略的交集 | ||
// 非必填。示例值:{"Statement": [{"Action": ["*"],"Effect": "Allow","Resource": ["*"]}],"Version":"1"} | ||
.setPolicy("{\"Statement\": [{\"Action\": [\"*\"],\"Effect\": \"Allow\",\"Resource\": [\"*\"]}]," | ||
+ "\"Version\":\"1\"}") | ||
// STS Token 有效期,单位:秒 | ||
.setDurationSeconds(3600L); | ||
AssumeRoleResponse assumeRoleResponse = stsClient.assumeRoleWithOptions(assumeRoleRequest, runtimeOptions); | ||
AssumeRoleResponseBody.AssumeRoleResponseBodyCredentials credentials = assumeRoleResponse.getBody().getCredentials(); | ||
|
||
// 返回角色扮演获取到的STS Token | ||
return CredentialModel.builder() | ||
.accessKeyId(credentials.getAccessKeyId()) | ||
.accessKeySecret(credentials.getAccessKeySecret()) | ||
.securityToken(credentials.getSecurityToken()) | ||
.expiration(ParameterHelper.getUTCDate(credentials.getExpiration()).getTime()) | ||
.build(); | ||
} | ||
} |
48 changes: 48 additions & 0 deletions
48
solution/solution-cross-account-sts-token/code-example/terraform/ack-rrsa/main.tf
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
# OIDC身份提供商的ARN | ||
# 格式为 acs:ram::${账号ID}:oidc-provider/ack-rrsa-${集群ID} | ||
variable "oidc_provider_arn" { | ||
type = string | ||
} | ||
|
||
# Pod绑定的RAM角色ARN | ||
# 格式为 acs:ram::${账号ID}:role/${角色名称} | ||
variable "oidc_role_arn" { | ||
type = string | ||
} | ||
|
||
# 集群生成的OIDC Token的文件路径 | ||
variable "oidc_token_file" { | ||
type = string | ||
} | ||
|
||
# 配置provider,跨账号扮演角色 | ||
provider "alicloud" { | ||
region = "cn-hangzhou" | ||
assume_role_with_oidc { | ||
oidc_provider_arn = var.oidc_provider_arn | ||
role_arn = var.oidc_role_arn | ||
oidc_token_file = var.oidc_token_file | ||
role_session_name = "WellArchitectedSolutionDemo" | ||
} | ||
assume_role { | ||
# 请替换为您实际要扮演的RAM角色ARN | ||
# 格式为 acs:ram::${账号ID}:role/${角色名称} | ||
role_arn = "<role-arn>" | ||
# 设置会话权限策略,进一步限制STS Token 的权限,如果指定该权限策略,则 STS Token 最终的权限策略取 RAM 角色权限策略与该权限策略的交集 | ||
# 非必填。示例值:{"Statement": [{"Action": ["*"],"Effect": "Allow","Resource": ["*"]}],"Version":"1"} | ||
policy = "{\"Statement\": [{\"Action\": [\"*\"],\"Effect\": \"Allow\",\"Resource\": [\"*\"]}],\"Version\":\"1\"}" | ||
# 角色会话名称 | ||
session_name = "WellArchitectedSolutionDemo" | ||
# STS Token 有效期,单位:秒 | ||
session_expiration = 3600 | ||
} | ||
} | ||
|
||
# 跨账号进行资源操作 | ||
# 以获取当前调用者身份信息为例 | ||
data "alicloud_caller_identity" "current" { | ||
} | ||
|
||
output "caller_identity" { | ||
value = data.alicloud_caller_identity.current | ||
} |
Oops, something went wrong.