Skip to content

Commit d49ca7d

Browse files
committed
feat(auth): add support for new service version in VPC Instant Auth
Signed-off-by: Lídia Tarcza <100163235+diatrcz@users.noreply.github.com>
1 parent 308d0b4 commit d49ca7d

3 files changed

Lines changed: 166 additions & 6 deletions

File tree

src/main/java/com/ibm/cloud/sdk/core/security/Authenticator.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ public interface Authenticator {
6060
String PROPNAME_IAM_PROFILE_ID = "IAM_PROFILE_ID";
6161
String PROPNAME_IAM_PROFILE_NAME = "IAM_PROFILE_NAME";
6262
String PROPNAME_IAM_ACCOUNT_ID = "IAM_ACCOUNT_ID";
63+
String PROPNAME_VPC_IMS_VERSION = "VPC_IMS_VERSION";
6364
String PROPNAME_SCOPE_COLLECTION_TYPE = "SCOPE_COLLECTION_TYPE";
6465
String PROPNAME_SCOPE_ID = "SCOPE_ID";
6566
String PROPNAME_INCLUDE_BUILTIN_ACTIONS = "INCLUDE_BUILTIN_ACTIONS";

src/main/java/com/ibm/cloud/sdk/core/security/VpcInstanceAuthenticator.java

Lines changed: 98 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ public class VpcInstanceAuthenticator
5050
private String iamProfileCrn;
5151
private String iamProfileId;
5252
private String url;
53+
private String serviceVersion;
54+
private int tokenLifetime;
5355

5456

5557
/**
@@ -59,6 +61,8 @@ public static class Builder {
5961
private String iamProfileCrn;
6062
private String iamProfileId;
6163
private String url;
64+
private String serviceVersion;
65+
private int tokenLifetime;
6266

6367
// Default ctor.
6468
public Builder() {
@@ -69,6 +73,8 @@ private Builder(VpcInstanceAuthenticator obj) {
6973
this.iamProfileCrn = obj.iamProfileCrn;
7074
this.iamProfileId = obj.iamProfileId;
7175
this.url = obj.url;
76+
this.serviceVersion = obj.serviceVersion;
77+
this.tokenLifetime = obj.tokenLifetime;
7278
}
7379

7480
/**
@@ -121,6 +127,27 @@ public Builder url(String url) {
121127
this.url = url;
122128
return this;
123129
}
130+
131+
/**
132+
* Sets the serviceVersion Property.
133+
*
134+
* @param serviceVersion the base service version to use with the service.
135+
* @return the Builder
136+
*/
137+
public Builder serviceVersion(String serviceVersion) {
138+
this.serviceVersion = serviceVersion;
139+
return this;
140+
}
141+
142+
/**
143+
* Sets the tokenLifetime Property.
144+
* @param tokenLifetime the base token lifetime to use.
145+
* @return the Builder
146+
*/
147+
public Builder tokenLifetime(int tokenLifetime) {
148+
this.tokenLifetime = tokenLifetime;
149+
return this;
150+
}
124151
}
125152

126153
// The default ctor is hidden to force the use of the non-default ctors.
@@ -139,6 +166,8 @@ protected VpcInstanceAuthenticator(Builder builder) {
139166
this.iamProfileCrn = builder.iamProfileCrn;
140167
this.iamProfileId = builder.iamProfileId;
141168
this.url = builder.url;
169+
this.serviceVersion = StringUtils.isEmpty(builder.serviceVersion) ? metadataServiceVersion : builder.serviceVersion;
170+
this.tokenLifetime = builder.tokenLifetime == 0 ? instanceIdentityTokenLifetime : builder.tokenLifetime;
142171
this.validate();
143172
}
144173

@@ -161,7 +190,8 @@ public Builder newBuilder() {
161190
*/
162191
public static VpcInstanceAuthenticator fromConfiguration(Map<String, String> config) {
163192
return new Builder().iamProfileCrn(config.get(PROPNAME_IAM_PROFILE_CRN))
164-
.iamProfileId(config.get(PROPNAME_IAM_PROFILE_ID)).url(config.get(PROPNAME_URL)).build();
193+
.iamProfileId(config.get(PROPNAME_IAM_PROFILE_ID)).url(config.get(PROPNAME_URL))
194+
.serviceVersion(config.get(PROPNAME_VPC_IMS_VERSION)).build();
165195
}
166196

167197
/**
@@ -236,10 +266,71 @@ protected void setURL(String url) {
236266
this.url = url;
237267
}
238268

269+
/**
270+
* @return the VPC ServiceVersion configured in this Authenticator.
271+
*/
272+
public String getServiceVersion() {
273+
return this.serviceVersion;
274+
}
275+
276+
/**
277+
* Sets the ServiceVersion in this Authenticator.
278+
*
279+
* @return the VPC ServiceVersion
280+
*/
281+
protected void setServiceVersion(String serviceVersion) {
282+
if (StringUtils.isEmpty(serviceVersion)) {
283+
serviceVersion = metadataServiceVersion;
284+
}
285+
this.serviceVersion = serviceVersion;
286+
}
287+
288+
/**
289+
* @return the TokenLifetime configured on this Authenticator.
290+
*/
291+
public int getTokenLifetime() {
292+
return this.tokenLifetime;
293+
}
294+
295+
/**
296+
* Sets the TokenLifetime in this Authenticator.
297+
* @param tokenLifetime
298+
*/
299+
protected void setTokenLifetime(int tokenLifetime) {
300+
if (tokenLifetime == 0) {
301+
tokenLifetime = instanceIdentityTokenLifetime;
302+
}
303+
this.tokenLifetime = tokenLifetime;
304+
}
305+
239306
private String getImsEndpoint() {
240307
return (StringUtils.isEmpty(this.url) ? defaultIMSEndpoint : this.url);
241308
}
242309

310+
/**
311+
* Gets the operation path for creating an access token based on the service version.
312+
*
313+
* @return the correct access token path
314+
*/
315+
public String getCreateAccessTokenPath() {
316+
if (this.serviceVersion.equals("2025-08-26")) {
317+
return "/identity/v1/token";
318+
}
319+
return operationPathCreateAccessToken;
320+
}
321+
322+
/**
323+
* Gets the operation path for creating an IAM token based on the service version.
324+
*
325+
* @return the correct IAM token path
326+
*/
327+
public String getCreateIamTokenPath() {
328+
if (this.serviceVersion.equals("2025-08-26")) {
329+
return "/identity/v1/iam_tokens";
330+
}
331+
return operationPathCreateIamToken;
332+
}
333+
243334
/**
244335
* Fetches an IAM access token using the authenticator's configuration.
245336
*
@@ -271,15 +362,15 @@ public String retrieveInstanceIdentityToken() throws Throwable {
271362
try {
272363
// Create a PUT request to retrieve the instance identity token.
273364
RequestBuilder builder = RequestBuilder
274-
.put(RequestBuilder.resolveRequestUrl(getImsEndpoint(), operationPathCreateAccessToken));
365+
.put(RequestBuilder.resolveRequestUrl(getImsEndpoint(), this.getCreateAccessTokenPath()));
275366

276367
// Set the params and request body.
277-
builder.query("version", metadataServiceVersion);
368+
builder.query("version", this.getServiceVersion());
278369
builder.header(HttpHeaders.ACCEPT, HttpMediaType.APPLICATION_JSON);
279370
builder.header(HttpHeaders.CONTENT_TYPE, HttpMediaType.APPLICATION_JSON);
280371
builder.header("Metadata-Flavor", metadataFlavor);
281372

282-
String requestBody = String.format("{\"expires_in\": %d}", instanceIdentityTokenLifetime);
373+
String requestBody = String.format("{\"expires_in\": %d}", this.getTokenLifetime());
283374
builder.bodyContent(requestBody, HttpMediaType.APPLICATION_JSON);
284375

285376
// Invoke the VPC IMDS "create_access_token" operation.
@@ -306,10 +397,10 @@ public IamToken retrieveIamAccessToken(String instanceIdentityToken) {
306397
try {
307398
// Create a POST request to retrieve the IAM access token.
308399
RequestBuilder builder =
309-
RequestBuilder.post(RequestBuilder.resolveRequestUrl(getImsEndpoint(), operationPathCreateIamToken));
400+
RequestBuilder.post(RequestBuilder.resolveRequestUrl(getImsEndpoint(), this.getCreateIamTokenPath()));
310401

311402
// Set the params and request body.
312-
builder.query("version", metadataServiceVersion);
403+
builder.query("version", this.getServiceVersion());
313404
builder.header(HttpHeaders.ACCEPT, HttpMediaType.APPLICATION_JSON);
314405
builder.header(HttpHeaders.CONTENT_TYPE, HttpMediaType.APPLICATION_JSON);
315406
builder.header(HttpHeaders.AUTHORIZATION, "Bearer " + instanceIdentityToken);
@@ -347,3 +438,4 @@ public IamToken retrieveIamAccessToken(String instanceIdentityToken) {
347438
return iamToken;
348439
}
349440
}
441+

src/test/java/com/ibm/cloud/sdk/core/test/security/VpcInstanceAuthenticatorTest.java

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,4 +623,71 @@ public void testAuthenticateResponseError2() throws Throwable {
623623
fail("Expected RuntimeException, not " + t.getClass().getSimpleName());
624624
}
625625
}
626+
627+
@Test
628+
public void testVpcAuthServiceVersionDefaults() {
629+
VpcInstanceAuthenticator authenticator = new VpcInstanceAuthenticator.Builder()
630+
.build();
631+
assertNotNull(authenticator);
632+
633+
assertEquals(authenticator.getServiceVersion(), "2022-03-01");
634+
assertEquals(authenticator.getTokenLifetime(), 300);
635+
636+
assertEquals("/instance_identity/v1/token", authenticator.getCreateAccessTokenPath());
637+
assertEquals("/instance_identity/v1/iam_token", authenticator.getCreateIamTokenPath());
638+
}
639+
640+
@Test
641+
public void testVpcAuthServiceVersionBuilder() {
642+
VpcInstanceAuthenticator authenticator = new VpcInstanceAuthenticator.Builder()
643+
.serviceVersion("2025-08-26")
644+
.tokenLifetime(600)
645+
.build();
646+
assertNotNull(authenticator);
647+
648+
assertEquals(authenticator.getServiceVersion(), "2025-08-26");
649+
assertEquals(authenticator.getTokenLifetime(), 600);
650+
651+
assertEquals("/identity/v1/token", authenticator.getCreateAccessTokenPath());
652+
assertEquals("/identity/v1/iam_tokens", authenticator.getCreateIamTokenPath());
653+
}
654+
655+
@Test
656+
public void testVpcAuthServiceVersionFromMap() {
657+
Map<String, String> properties = new HashMap<>();
658+
properties.put(Authenticator.PROPNAME_VPC_IMS_VERSION, "2025-08-26");
659+
660+
VpcInstanceAuthenticator authenticator = VpcInstanceAuthenticator.fromConfiguration(properties);
661+
assertNotNull(authenticator);
662+
663+
assertEquals(authenticator.getServiceVersion(), "2025-08-26");
664+
665+
assertEquals("/identity/v1/token", authenticator.getCreateAccessTokenPath());
666+
assertEquals("/identity/v1/iam_tokens", authenticator.getCreateIamTokenPath());
667+
}
668+
669+
@Test
670+
public void testVpcAuthServiceVersionOldVersion() {
671+
VpcInstanceAuthenticator authenticator = new VpcInstanceAuthenticator.Builder()
672+
.serviceVersion("2022-03-01")
673+
.build();
674+
assertNotNull(authenticator);
675+
676+
assertEquals(authenticator.getServiceVersion(), "2022-03-01");
677+
678+
assertEquals("/instance_identity/v1/token", authenticator.getCreateAccessTokenPath());
679+
assertEquals("/instance_identity/v1/iam_token", authenticator.getCreateIamTokenPath());
680+
}
681+
682+
@Test
683+
public void testVpcAuthServiceVersionCustomVersion() {
684+
VpcInstanceAuthenticator authenticator = new VpcInstanceAuthenticator.Builder()
685+
.serviceVersion("2024-01-01")
686+
.build();
687+
assertNotNull(authenticator);
688+
689+
assertEquals(authenticator.getServiceVersion(), "2024-01-01");
690+
assertEquals("/instance_identity/v1/token", authenticator.getCreateAccessTokenPath());
691+
assertEquals("/instance_identity/v1/iam_token", authenticator.getCreateIamTokenPath());
692+
}
626693
}

0 commit comments

Comments
 (0)