Skip to content

Commit 42589ae

Browse files
committed
Version 3.25.5
1 parent d738236 commit 42589ae

File tree

9 files changed

+144
-7
lines changed

9 files changed

+144
-7
lines changed

README-Android.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
Version 3.25.5
2+
New features:
3+
1. Added IMDSv2 logic
4+
-----------------------------------------------------------------------------------
15
Version 3.25.4
26
New features:
37
1. Added logic to set okhttp callTimeout

README-Java.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
Version 3.25.5
2+
New features:
3+
1. Added IMDSv2 logic
4+
-----------------------------------------------------------------------------------
15
Version 3.25.4
26
New features:
37
1. Added logic to set okhttp callTimeout

README_CN.MD

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
Version 3.25.5
2+
New features:
3+
1. 支持IMDSv2
4+
-----------------------------------------------------------------------------------
15
Version 3.25.4
26
New features:
37
1. 支持设置okhttp的callTimeout

app/src/main/java/com/obs/services/EcsObsCredentialsProvider.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
package com.obs.services;
1616

17+
import static com.obs.services.internal.security.EcsSecurityUtils.DEFAULT_METADATA_TOKEN_TTL_SECONDS;
18+
1719
import java.io.IOException;
1820
import java.text.DateFormat;
1921
import java.text.ParseException;
@@ -38,6 +40,8 @@ public class EcsObsCredentialsProvider implements IObsCredentialsProvider {
3840
// default is -1, not retry
3941
private int maxRetryTimes = -1;
4042

43+
private int metadataTokenTTLSeconds = DEFAULT_METADATA_TOKEN_TTL_SECONDS;
44+
4145
public EcsObsCredentialsProvider() {
4246
this.maxRetryTimes = 3;
4347
}
@@ -100,7 +104,7 @@ private void refresh(boolean ignoreException) {
100104

101105
private LimitedTimeSecurityKey getNewSecurityKey() throws IOException, IllegalArgumentException {
102106

103-
String content = EcsSecurityUtils.getSecurityKeyInfoWithDetail();
107+
String content = EcsSecurityUtils.getSecurityKeyInfoWithDetail(metadataTokenTTLSeconds);
104108
SecurityKey securityInfo = (SecurityKey) JSONChange.jsonToObj(new SecurityKey(), content);
105109

106110
if (securityInfo == null) {
@@ -128,4 +132,12 @@ private LimitedTimeSecurityKey getNewSecurityKey() throws IOException, IllegalAr
128132
return new LimitedTimeSecurityKey(bean.getAccessKey(), bean.getSecretKey(), bean.getSecurityToken(),
129133
expiryDate);
130134
}
135+
public int getMetadataTokenTTLSeconds() {
136+
return metadataTokenTTLSeconds;
137+
}
138+
139+
public void setMetadataTokenTTLSeconds(int metadataTokenTTLSeconds) {
140+
this.metadataTokenTTLSeconds = metadataTokenTTLSeconds;
141+
}
142+
131143
}

app/src/main/java/com/obs/services/internal/Constants.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ public static class ObsBucketReplicationRequestParams {
239239

240240
public static final TimeZone GMT_TIMEZONE = TimeZone.getTimeZone("GMT");
241241

242-
public static final String OBS_SDK_VERSION = "3.25.4";
242+
public static final String OBS_SDK_VERSION = "3.25.5";
243243

244244
public static final String USER_AGENT_VALUE = "obs-sdk-java/" + Constants.OBS_SDK_VERSION;
245245

app/src/main/java/com/obs/services/internal/security/EcsSecurityUtils.java

Lines changed: 115 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,34 @@
1515
package com.obs.services.internal.security;
1616

1717
import java.io.IOException;
18+
import java.util.HashMap;
19+
import java.util.Map;
1820
import java.util.concurrent.TimeUnit;
1921

22+
import com.obs.log.ILogger;
23+
import com.obs.log.LoggerBuilder;
24+
import com.obs.services.AbstractClient;
2025
import com.obs.services.internal.Constants;
2126
import com.obs.services.internal.utils.PropertyManager;
27+
import com.obs.services.model.HttpMethodEnum;
28+
2229
import okhttp3.Call;
30+
import okhttp3.MediaType;
2331
import okhttp3.OkHttpClient;
2432
import okhttp3.Request;
33+
import okhttp3.RequestBody;
2534
import okhttp3.Response;
2635

36+
2737
public class EcsSecurityUtils {
2838
/**
2939
* Default root url for the openstack metadata apis.
3040
*/
3141
private static final String OPENSTACK_METADATA_ROOT = "/openstack/latest";
42+
/**
43+
* Default root url for the metadata apis.
44+
*/
45+
private static final String METADATA_ROOT = "/meta-data/latest";
3246

3347
/**
3448
* Default endpoint for the ECS Instance Metadata Service.
@@ -46,13 +60,32 @@ public class EcsSecurityUtils {
4660
.writeTimeout(HTTP_CONNECT_TIMEOUT_VALUE, TimeUnit.MILLISECONDS)
4761
.readTimeout(HTTP_CONNECT_TIMEOUT_VALUE, TimeUnit.MILLISECONDS).build();
4862

63+
private static final String METADATA_TOKEN_HEADER_KEY = "X-Metadata-Token";
64+
private static final String METADATA_TOKEN_TTL = METADATA_TOKEN_HEADER_KEY + "-Ttl-Seconds";
65+
public static final int DEFAULT_METADATA_TOKEN_TTL_SECONDS = 21600;
66+
private static final String METADATA_TOKEN_RESOURCE_PATH = METADATA_ROOT + "/api/token";
67+
private static final String OPENSTACK_SECURITY_KEY_RESOURCE_PATH = OPENSTACK_METADATA_ROOT + "/securitykey";
68+
private static final ILogger ILOG = LoggerBuilder.getLogger(AbstractClient.class);
4969
/**
5070
* Returns the temporary security credentials (access, secret,
5171
* securitytoken, and expires_at) associated with the IAM roles on the
5272
* instance.
5373
*/
5474
public static String getSecurityKeyInfoWithDetail() throws IOException {
55-
return getResourceWithDetail(getEndpointForECSMetadataService() + OPENSTACK_METADATA_ROOT + "/securitykey");
75+
return getSecurityKeyInfoWithDetail(DEFAULT_METADATA_TOKEN_TTL_SECONDS);
76+
}
77+
78+
public static String getSecurityKeyInfoWithDetail(int metadataTokenTTLSeconds) throws IOException {
79+
// try get metadataToken
80+
String metadataApiToken = getMetadataApiToken(metadataTokenTTLSeconds);
81+
String securityKeyResourcePath = getEndpointForECSMetadataService() + OPENSTACK_SECURITY_KEY_RESOURCE_PATH;
82+
if(metadataApiToken.isEmpty()) {
83+
// failed to get metadataToken(404 or 405), use IMDSv1
84+
return getResourceWithDetail(securityKeyResourcePath);
85+
} else {
86+
// succeeded to get metadataToken(2xx), use IMDSv2
87+
return getResourceWithDetailWithMetaDataToken(securityKeyResourcePath, metadataApiToken);
88+
}
5689
}
5790

5891
/**
@@ -85,7 +118,7 @@ private static String getResourceWithDetail(String endpoint) throws IOException
85118
}
86119

87120
if (!(res.code() >= 200 && res.code() < 300)) {
88-
String errorMessage = "Get securityKey form ECS failed, Code : " + res.code() + "; Headers : " + header
121+
String errorMessage = "Get securityKey from ECS failed, Code : " + res.code() + "; Headers : " + header
89122
+ "; Content : " + content;
90123
throw new IllegalArgumentException(errorMessage);
91124
}
@@ -97,4 +130,84 @@ private static String getResourceWithDetail(String endpoint) throws IOException
97130
}
98131
}
99132
}
133+
134+
private static String getMetadataApiToken(int metadataTokenTTLSeconds) throws IOException {
135+
Map<String, String> headers = new HashMap<>();
136+
headers.put(METADATA_TOKEN_TTL, String.valueOf(metadataTokenTTLSeconds));
137+
ECSResult ecsResult =
138+
executeEcsRequest(getEndpointForECSMetadataService() + METADATA_TOKEN_RESOURCE_PATH
139+
, headers, HttpMethodEnum.PUT, "", null);
140+
if(ecsResult.code == 404 || ecsResult.code == 405) {
141+
ILOG.debug(METADATA_TOKEN_HEADER_KEY + " not supported," + ecsResult);
142+
return "";
143+
} else if (!(ecsResult.code >= 200 && ecsResult.code < 300)) {
144+
String errorMessage = "Get " + METADATA_TOKEN_HEADER_KEY+ " with " +
145+
METADATA_TOKEN_TTL + ":" + metadataTokenTTLSeconds
146+
+ " from ECS failed," + ecsResult;
147+
ILOG.error(errorMessage);
148+
throw new IllegalArgumentException(errorMessage);
149+
} else {
150+
ILOG.debug(METADATA_TOKEN_HEADER_KEY + " refreshed succeeded.");
151+
return ecsResult.content;
152+
}
153+
}
154+
155+
private static String getResourceWithDetailWithMetaDataToken(String endpoint, String metadataApiToken) throws IOException {
156+
Map<String, String> headers = new HashMap<>();
157+
headers.put(METADATA_TOKEN_HEADER_KEY, metadataApiToken);
158+
ECSResult ecsResult = executeEcsRequest(endpoint, headers, HttpMethodEnum.GET, "", null);
159+
// if not 2xx, throw exception
160+
if (!(ecsResult.code >= 200 && ecsResult.code < 300)) {
161+
String errorMessage = "Get securityKey by " + METADATA_TOKEN_HEADER_KEY +
162+
" from ECS failed," + ecsResult;
163+
ILOG.error(errorMessage);
164+
throw new IllegalArgumentException(errorMessage);
165+
}
166+
ILOG.debug("getResourceWithDetailWithMetaDataToken succeeded.");
167+
return ecsResult.content;
168+
}
169+
170+
private static ECSResult executeEcsRequest(String url, Map<String, String> headers,
171+
HttpMethodEnum httpMethod, String body, MediaType contentType) throws IOException, IllegalArgumentException {
172+
Request.Builder builder = new Request.Builder();
173+
builder.header("Accept", "*/*");
174+
headers.forEach(builder::header);
175+
Request request;
176+
if (httpMethod == HttpMethodEnum.PUT) {
177+
request = builder.url(url).put(RequestBody.create(body, contentType)).build();
178+
} else {
179+
request = builder.url(url).get().build();
180+
}
181+
Call c = httpClient.newCall(request);
182+
try (Response res = c.execute()) {
183+
String header = "";
184+
String content = "";
185+
if (res.headers() != null) {
186+
header = res.headers().toString();
187+
}
188+
if (res.body() != null) {
189+
content = res.body().string();
190+
}
191+
192+
return new ECSResult(res.code(), header, content);
193+
}
194+
}
195+
196+
private static class ECSResult {
197+
public final int code;
198+
public final String header;
199+
public final String content;
200+
201+
public ECSResult(int code, String header, String content) {
202+
this.code = code;
203+
this.header = header;
204+
this.content = content;
205+
}
206+
207+
@Override
208+
public String toString() {
209+
return " Code : " + code + "; Headers : " + header
210+
+ "; Content : " + content;
211+
}
212+
}
100213
}

pom-android.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
<groupId>com.huaweicloud</groupId>
66
<artifactId>esdk-obs-android</artifactId>
7-
<version>3.25.4</version>
7+
<version>3.25.5</version>
88
<packaging>jar</packaging>
99

1010
<name>OBS SDK for Android</name>

pom-java.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
<groupId>com.huaweicloud</groupId>
66
<artifactId>esdk-obs-java</artifactId>
7-
<version>3.25.4</version>
7+
<version>3.25.5</version>
88
<packaging>jar</packaging>
99

1010
<name>OBS SDK for Java</name>

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
<groupId>com.huaweicloud</groupId>
66
<artifactId>esdk-obs-java</artifactId>
7-
<version>3.25.4</version>
7+
<version>3.25.5</version>
88
<packaging>jar</packaging>
99

1010
<name>OBS SDK for Java</name>

0 commit comments

Comments
 (0)