Skip to content

Commit 5c0dede

Browse files
committed
refactor credentials providers
1 parent f8e6e72 commit 5c0dede

31 files changed

+1979
-101
lines changed

aliyun-java-sdk-core/src/main/java/com/aliyuncs/auth/AuthConstant.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
public class AuthConstant {
44
public static final String SYSTEM_ACCESSKEYID = "alibabacloud.accessKeyId";
55
public static final String SYSTEM_ACCESSKEYSECRET = "alibabacloud.accessKeyIdSecret";
6+
public static final String SYSTEM_ACCESSKEY_SECRET = "alibabacloud.accessKeySecret";
7+
public static final String SYSTEM_SESSION_TOKEN = "alibabacloud.sessionToken";
68

79
public static final String DEFAULT_CREDENTIALS_FILE_PATH = System.getProperty("user.home") +
810
"/.alibabacloud/credentials.ini";
@@ -11,6 +13,7 @@ public class AuthConstant {
1113
public static final String INI_TYPE = "type";
1214
public static final String INI_TYPE_RAM = "ecs_ram_role";
1315
public static final String INI_TYPE_ARN = "ram_role_arn";
16+
public static final String INI_TYPE_OIDC = "oidc_role_arn";
1417
public static final String INI_TYPE_KEY_PAIR = "rsa_key_pair";
1518
public static final String INI_PUBLIC_KEY_ID = "public_key_id";
1619
public static final String INI_PRIVATE_KEY_FILE = "private_key_file";
@@ -19,6 +22,8 @@ public class AuthConstant {
1922
public static final String INI_ROLE_SESSION_NAME = "role_session_name";
2023
public static final String INI_ROLE_ARN = "role_arn";
2124
public static final String INI_POLICY = "policy";
25+
public static final String INI_OIDC_PROVIDER_ARN = "oidc_provider_arn";
26+
public static final String INI_OIDC_TOKEN_FILE_PATH = "oidc_token_file_path";
2227
public static final long TSC_VALID_TIME_SECONDS = 3600L;
2328
public static final String DEFAULT_REGION = "region_id";
2429
public static final String INI_ENABLE = "enable";
Lines changed: 271 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
1+
package com.aliyuncs.auth;
2+
3+
import com.aliyuncs.exceptions.ClientException;
4+
import com.aliyuncs.utils.AuthUtils;
5+
import com.aliyuncs.utils.StringUtils;
6+
import com.google.gson.Gson;
7+
import com.google.gson.annotations.SerializedName;
8+
9+
import java.io.BufferedReader;
10+
import java.io.File;
11+
import java.io.FileReader;
12+
import java.io.IOException;
13+
import java.util.List;
14+
15+
public class CLIProfileCredentialsProvider implements AlibabaCloudCredentialsProvider {
16+
private final String CLI_CREDENTIALS_CONFIG_PATH = System.getProperty("user.home") +
17+
"/.aliyun/config.json";
18+
private volatile AlibabaCloudCredentialsProvider credentialsProvider;
19+
private volatile String currentProfileName;
20+
private final Object credentialsProviderLock = new Object();
21+
22+
private CLIProfileCredentialsProvider(Builder builder) {
23+
this.currentProfileName = builder.profileName == null ? System.getenv("ALIBABA_CLOUD_PROFILE") : builder.profileName;
24+
}
25+
26+
public static Builder builder() {
27+
return new Builder();
28+
}
29+
30+
@Override
31+
public AlibabaCloudCredentials getCredentials() throws ClientException {
32+
if (AuthUtils.isDisableCLIProfile()) {
33+
throw new ClientException("CLI credentials file is disabled.");
34+
}
35+
Config config = null;
36+
try {
37+
config = parseProfile(CLI_CREDENTIALS_CONFIG_PATH);
38+
} catch (IOException e) {
39+
throw new ClientException("Unable to get profile from CLI credentials file: " + e);
40+
}
41+
if (null == config) {
42+
throw new ClientException("Unable to get profile from empty CLI credentials file.");
43+
}
44+
String refreshedProfileName = System.getenv("ALIBABA_CLOUD_PROFILE");
45+
if (shouldReloadCredentialsProvider(refreshedProfileName)) {
46+
synchronized (credentialsProviderLock) {
47+
if (shouldReloadCredentialsProvider(refreshedProfileName)) {
48+
if (!StringUtils.isEmpty(refreshedProfileName)) {
49+
this.currentProfileName = refreshedProfileName;
50+
}
51+
this.credentialsProvider = reloadCredentialsProvider(config, this.currentProfileName);
52+
}
53+
}
54+
}
55+
return this.credentialsProvider.getCredentials();
56+
}
57+
58+
AlibabaCloudCredentialsProvider reloadCredentialsProvider(Config config, String profileName) throws ClientException {
59+
String currentProfileName = !StringUtils.isEmpty(profileName) ? profileName : config.getCurrent();
60+
List<Profile> profiles = config.getProfiles();
61+
if (profiles != null && !profiles.isEmpty()) {
62+
for (Profile profile : profiles) {
63+
if (!StringUtils.isEmpty(profile.getName()) && profile.getName().equals(currentProfileName)) {
64+
String mode = profile.getMode();
65+
66+
if ("AK".equals(mode)) {
67+
return new StaticCredentialsProvider(
68+
new BasicCredentials(profile.getAccessKeyId(), profile.getAccessKeySecret()));
69+
} else if ("RamRoleArn".equals(mode)) {
70+
AlibabaCloudCredentialsProvider innerProvider = new StaticCredentialsProvider(
71+
new BasicCredentials(profile.getAccessKeyId(), profile.getAccessKeySecret()));
72+
return STSAssumeRoleSessionCredentialsProvider.builder()
73+
.credentialsProvider(innerProvider)
74+
.durationSeconds(profile.getDurationSeconds())
75+
.roleArn(profile.getRoleArn())
76+
.roleSessionName(profile.getRoleSessionName())
77+
.stsRegionId(profile.getStsRegionId())
78+
.enableVpc(profile.getEnableVpc())
79+
.policy(profile.getPolicy())
80+
.externalId(profile.getExternalId())
81+
.build();
82+
} else if ("EcsRamRole".equals(mode)) {
83+
return InstanceProfileCredentialsProvider.builder()
84+
.roleName(profile.getRamRoleName())
85+
.build();
86+
} else if ("OIDC".equals(mode)) {
87+
return OIDCCredentialsProvider.builder()
88+
.durationSeconds(profile.getDurationSeconds())
89+
.roleArn(profile.getRoleArn())
90+
.roleSessionName(profile.getRoleSessionName())
91+
.oidcProviderArn(profile.getOidcProviderArn())
92+
.oidcTokenFilePath(profile.getOidcTokenFile())
93+
.stsRegionId(profile.getStsRegionId())
94+
.enableVpc(profile.getEnableVpc())
95+
.policy(profile.getPolicy())
96+
.build();
97+
} else if ("ChainableRamRoleArn".equals(mode)) {
98+
AlibabaCloudCredentialsProvider previousProvider = reloadCredentialsProvider(config, profile.getSourceProfile());
99+
return STSAssumeRoleSessionCredentialsProvider.builder()
100+
.credentialsProvider(previousProvider)
101+
.durationSeconds(profile.getDurationSeconds())
102+
.roleArn(profile.getRoleArn())
103+
.roleSessionName(profile.getRoleSessionName())
104+
.stsRegionId(profile.getStsRegionId())
105+
.enableVpc(profile.getEnableVpc())
106+
.policy(profile.getPolicy())
107+
.externalId(profile.getExternalId())
108+
.build();
109+
} else {
110+
throw new ClientException(String.format("Unsupported profile mode '%s' form CLI credentials file.", mode));
111+
}
112+
}
113+
}
114+
}
115+
throw new ClientException(String.format("Unable to get profile with '%s' form CLI credentials file.", currentProfileName));
116+
}
117+
118+
Config parseProfile(String configFilePath) throws ClientException, IOException {
119+
File configFile = new File(configFilePath);
120+
if (!configFile.exists() || !configFile.isFile() || !configFile.canRead()) {
121+
throw new ClientException(String.format("Unable to open credentials file: %s.", configFile.getAbsolutePath()));
122+
}
123+
Gson gson = new Gson();
124+
BufferedReader br = null;
125+
try {
126+
br = new BufferedReader(new FileReader(configFile));
127+
StringBuilder sb = new StringBuilder();
128+
String line;
129+
while ((line = br.readLine()) != null) {
130+
sb.append(line);
131+
}
132+
String jsonContent = sb.toString();
133+
return gson.fromJson(jsonContent, Config.class);
134+
} catch (Exception e) {
135+
throw new ClientException(String.format("Failed to parse credential form CLI credentials file: %s.", configFile.getAbsolutePath()));
136+
} finally {
137+
if (br != null) {
138+
br.close();
139+
}
140+
}
141+
}
142+
143+
boolean shouldReloadCredentialsProvider(String profileName) {
144+
return this.credentialsProvider == null || (!StringUtils.isEmpty(this.currentProfileName) && !StringUtils.isEmpty(profileName) && !this.currentProfileName.equals(profileName));
145+
}
146+
147+
String getProfileName() {
148+
return this.currentProfileName;
149+
}
150+
151+
static final class Builder {
152+
private String profileName;
153+
154+
public Builder profileName(String profileName) {
155+
this.profileName = profileName;
156+
return this;
157+
}
158+
159+
CLIProfileCredentialsProvider build() {
160+
return new CLIProfileCredentialsProvider(this);
161+
}
162+
}
163+
164+
static class Config {
165+
@SerializedName("current")
166+
private String current;
167+
@SerializedName("profiles")
168+
private List<Profile> profiles;
169+
170+
public String getCurrent() {
171+
return current;
172+
}
173+
174+
public List<Profile> getProfiles() {
175+
return profiles;
176+
}
177+
}
178+
179+
static class Profile {
180+
@SerializedName("name")
181+
private String name;
182+
@SerializedName("mode")
183+
private String mode;
184+
@SerializedName("access_key_id")
185+
private String accessKeyId;
186+
@SerializedName("access_key_secret")
187+
private String accessKeySecret;
188+
@SerializedName("ram_role_arn")
189+
private String roleArn;
190+
@SerializedName("ram_session_name")
191+
private String roleSessionName;
192+
@SerializedName("expired_seconds")
193+
private Integer durationSeconds;
194+
@SerializedName("sts_region")
195+
private String stsRegionId;
196+
@SerializedName("enable_vpc")
197+
private Boolean enableVpc;
198+
@SerializedName("ram_role_name")
199+
private String ramRoleName;
200+
@SerializedName("oidc_token_file")
201+
private String oidcTokenFile;
202+
@SerializedName("oidc_provider_arn")
203+
private String oidcProviderArn;
204+
@SerializedName("source_profile")
205+
private String sourceProfile;
206+
@SerializedName("policy")
207+
private String policy;
208+
@SerializedName("external_id")
209+
private String externalId;
210+
211+
public String getName() {
212+
return name;
213+
}
214+
215+
public String getMode() {
216+
return mode;
217+
}
218+
219+
public String getAccessKeyId() {
220+
return accessKeyId;
221+
}
222+
223+
public String getAccessKeySecret() {
224+
return accessKeySecret;
225+
}
226+
227+
public String getRoleArn() {
228+
return roleArn;
229+
}
230+
231+
public String getRoleSessionName() {
232+
return roleSessionName;
233+
}
234+
235+
public Integer getDurationSeconds() {
236+
return durationSeconds;
237+
}
238+
239+
public String getStsRegionId() {
240+
return stsRegionId;
241+
}
242+
243+
public Boolean getEnableVpc() {
244+
return enableVpc;
245+
}
246+
247+
public String getRamRoleName() {
248+
return ramRoleName;
249+
}
250+
251+
public String getOidcTokenFile() {
252+
return oidcTokenFile;
253+
}
254+
255+
public String getOidcProviderArn() {
256+
return oidcProviderArn;
257+
}
258+
259+
public String getSourceProfile() {
260+
return sourceProfile;
261+
}
262+
263+
public String getPolicy() {
264+
return policy;
265+
}
266+
267+
public String getExternalId() {
268+
return externalId;
269+
}
270+
}
271+
}

0 commit comments

Comments
 (0)