Skip to content

Commit c5df672

Browse files
authored
Merge branch 'main' into update-readme
2 parents 2d5e47e + 152c851 commit c5df672

File tree

6 files changed

+198
-27
lines changed

6 files changed

+198
-27
lines changed

.github/workflows/members.json

Lines changed: 98 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,102 @@
2121
{"login":"surbhigarg92"},
2222
{"login":"alkatrivedi"},
2323
{"login":"olavloite"},
24-
{"login":"harshachinta"}
24+
{"login":"harshachinta"},
25+
{"login":"dazuma"},
26+
{"login":"quartzmo"},
27+
{"login":"codyoss"},
28+
{"login":"BrennaEpp"},
29+
{"login":"tritone"},
30+
{"login":"bisun-google"},
31+
{"login":"linchin"},
32+
{"login":"ohmayr"},
33+
{"login":"parthea"},
34+
{"login":"vchudnov-g"},
35+
{"login":"scotthart"},
36+
{"login":"dbolduc"},
37+
{"login":"cuiy0006"},
38+
{"login":"andrewsg"},
39+
{"login":"BenWhitehead"},
40+
{"login":"danielduhh"},
41+
{"login":"vishwarajanand"},
42+
{"login":"bajajneha27"},
43+
{"login":"JesseLovelace"},
44+
{"login":"cojenco"},
45+
{"login":"ddelgrosso1"},
46+
{"login":"sydney-munro"},
47+
{"login":"marcoa6"},
48+
{"login":"jskeet"},
49+
{"login":"glaforge"},
50+
{"login":"cwest"},
51+
{"login":"engelke"},
52+
{"login":"fhinkel"},
53+
{"login":"briandorsey"},
54+
{"login":"palladius"},
55+
{"login":"callingshotgun"},
56+
{"login":"muncus"},
57+
{"login":"darylducharme"},
58+
{"login":"grayside"},
59+
{"login":"koverholt"},
60+
{"login":"wietsevenema"},
61+
{"login":"ankurkotwal"},
62+
{"login":"ksprashu"},
63+
{"login":"arbrown"},
64+
{"login":"momander"},
65+
{"login":"donmccasland"},
66+
{"login":"glasnt"},
67+
{"login":"rsamborski"},
68+
{"login":"meteatamel"},
69+
{"login":"iennae"},
70+
{"login":"rominirani"},
71+
{"login":"kazunori279"},
72+
{"login":"davidcavazos"},
73+
{"login":"bourgeoisor"},
74+
{"login":"minherz"},
75+
{"login":"vladkol"},
76+
{"login":"kaslin"},
77+
{"login":"LukeSchlangen"},
78+
{"login":"billyjacobson"},
79+
{"login":"msampathkumar"},
80+
{"login":"polong-lin"},
81+
{"login":"villasenor"},
82+
{"login":"alphinside"},
83+
{"login":"telpirion"},
84+
{"login":"ZackAkil"},
85+
{"login":"joeshirey"},
86+
{"login":"m-strzelczyk"},
87+
{"login":"NimJay"},
88+
{"login":"saraford"},
89+
{"login":"kweinmeister"},
90+
{"login":"Mukamik"},
91+
{"login":"holtskinner"},
92+
{"login":"Neenu1995"},
93+
{"login":"Deleplace"},
94+
{"login":"Sita04"},
95+
{"login":"AbiramiSukumaran"},
96+
{"login":"moficodes"},
97+
{"login":"amanda-tarafa"},
98+
{"login":"aliciawilliams"},
99+
{"login":"jeffonelson"},
100+
{"login":"GabeWeiss"},
101+
{"login":"h3xar0n"},
102+
{"login":"katiemn"},
103+
{"login":"iamthuya"},
104+
{"login":"bradmiro"},
105+
{"login":"PicardParis"},
106+
{"login":"gotochkin"},
107+
{"login":"jesuispy"},
108+
{"login":"hyunuk"},
109+
{"login":"rachael-ds"},
110+
{"login":"eaball35"},
111+
{"login":"alokpattani"},
112+
{"login":"dandhlee"},
113+
{"login":"duncantech"},
114+
{"login":"inardini"},
115+
{"login":"lavinigam-gcp"},
116+
{"login":"gericdong"},
117+
{"login":"priyapandeyb"},
118+
{"login":"erwinh85"},
119+
{"login":"CadillacBurgess1"},
120+
{"login":"julieqiu"},
121+
{"login":"coryan"}
25122
]

oauth2_http/java/com/google/auth/oauth2/ComputeEngineCredentials.java

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@
8383
public class ComputeEngineCredentials extends GoogleCredentials
8484
implements ServiceAccountSigner, IdTokenProvider {
8585

86+
static final String METADATA_RESPONSE_EMPTY_CONTENT_ERROR_MESSAGE =
87+
"Empty content from metadata token server request.";
8688
// Decrease timing margins on GCE.
8789
// This is needed because GCE VMs maintain their own OAuth cache that expires T-4 mins, attempting
8890
// to refresh a token before then, will yield the same stale token. To enable pre-emptive
@@ -366,7 +368,7 @@ public AccessToken refreshAccessToken() throws IOException {
366368
if (content == null) {
367369
// Throw explicitly here on empty content to avoid NullPointerException from parseAs call.
368370
// Mock transports will have success code with empty content by default.
369-
throw new IOException("Empty content from metadata token server request.");
371+
throw new IOException(METADATA_RESPONSE_EMPTY_CONTENT_ERROR_MESSAGE);
370372
}
371373
GenericData responseData = response.parseAs(GenericData.class);
372374
String accessToken =
@@ -408,9 +410,24 @@ public IdToken idTokenWithAudience(String targetAudience, List<IdTokenProvider.O
408410
documentUrl.set("audience", targetAudience);
409411
HttpResponse response =
410412
getMetadataResponse(documentUrl.toString(), RequestType.ID_TOKEN_REQUEST, true);
413+
int statusCode = response.getStatusCode();
414+
if (statusCode == HttpStatusCodes.STATUS_CODE_NOT_FOUND) {
415+
throw new IOException(
416+
String.format(
417+
"Error code %s trying to get identity token from"
418+
+ " Compute Engine metadata. This may be because the virtual machine instance"
419+
+ " does not have permission scopes specified.",
420+
statusCode));
421+
}
422+
if (statusCode != HttpStatusCodes.STATUS_CODE_OK) {
423+
throw new IOException(
424+
String.format(
425+
"Unexpected Error code %s trying to get identity token from Compute Engine metadata: %s",
426+
statusCode, response.parseAsString()));
427+
}
411428
InputStream content = response.getContent();
412429
if (content == null) {
413-
throw new IOException("Empty content from metadata token server request.");
430+
throw new IOException(METADATA_RESPONSE_EMPTY_CONTENT_ERROR_MESSAGE);
414431
}
415432
String rawToken = response.parseAsString();
416433
return IdToken.create(rawToken);
@@ -710,7 +727,7 @@ private String getDefaultServiceAccount() throws IOException {
710727
if (content == null) {
711728
// Throw explicitly here on empty content to avoid NullPointerException from parseAs call.
712729
// Mock transports will have success code with empty content by default.
713-
throw new IOException("Empty content from metadata token server request.");
730+
throw new IOException(METADATA_RESPONSE_EMPTY_CONTENT_ERROR_MESSAGE);
714731
}
715732
GenericData responseData = response.parseAs(GenericData.class);
716733
Map<String, Object> defaultAccount =

oauth2_http/javatests/com/google/auth/oauth2/ComputeEngineCredentialsTest.java

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,14 @@
3131

3232
package com.google.auth.oauth2;
3333

34+
import static com.google.auth.oauth2.ComputeEngineCredentials.METADATA_RESPONSE_EMPTY_CONTENT_ERROR_MESSAGE;
3435
import static org.junit.Assert.assertArrayEquals;
3536
import static org.junit.Assert.assertEquals;
3637
import static org.junit.Assert.assertFalse;
3738
import static org.junit.Assert.assertNotNull;
3839
import static org.junit.Assert.assertNull;
3940
import static org.junit.Assert.assertSame;
41+
import static org.junit.Assert.assertThrows;
4042
import static org.junit.Assert.assertTrue;
4143
import static org.junit.Assert.fail;
4244

@@ -420,7 +422,7 @@ public void getRequestMetadata_shouldInvalidateAccessTokenWhenScoped_newAccessTo
420422
@Test
421423
public void getRequestMetadata_missingServiceAccount_throws() {
422424
MockMetadataServerTransportFactory transportFactory = new MockMetadataServerTransportFactory();
423-
transportFactory.transport.setRequestStatusCode(HttpStatusCodes.STATUS_CODE_NOT_FOUND);
425+
transportFactory.transport.setStatusCode(HttpStatusCodes.STATUS_CODE_NOT_FOUND);
424426
ComputeEngineCredentials credentials =
425427
ComputeEngineCredentials.newBuilder().setHttpTransportFactory(transportFactory).build();
426428
try {
@@ -437,7 +439,7 @@ public void getRequestMetadata_missingServiceAccount_throws() {
437439
@Test
438440
public void getRequestMetadata_serverError_throws() {
439441
MockMetadataServerTransportFactory transportFactory = new MockMetadataServerTransportFactory();
440-
transportFactory.transport.setRequestStatusCode(HttpStatusCodes.STATUS_CODE_SERVER_ERROR);
442+
transportFactory.transport.setStatusCode(HttpStatusCodes.STATUS_CODE_SERVER_ERROR);
441443
ComputeEngineCredentials credentials =
442444
ComputeEngineCredentials.newBuilder().setHttpTransportFactory(transportFactory).build();
443445
try {
@@ -668,7 +670,7 @@ public void sign_getUniverseException() {
668670
ComputeEngineCredentials credentials =
669671
ComputeEngineCredentials.newBuilder().setHttpTransportFactory(transportFactory).build();
670672

671-
transportFactory.transport.setRequestStatusCode(501);
673+
transportFactory.transport.setStatusCode(501);
672674
Assert.assertThrows(IOException.class, credentials::getUniverseDomain);
673675

674676
byte[] expectedSignature = {0xD, 0xE, 0xA, 0xD};
@@ -962,7 +964,7 @@ public void getUniverseDomain_fromMetadata_non404error_throws() throws IOExcepti
962964
continue;
963965
}
964966
try {
965-
transportFactory.transport.setRequestStatusCode(status);
967+
transportFactory.transport.setStatusCode(status);
966968
credentials.getUniverseDomain();
967969
fail("Should not be able to use credential without exception.");
968970
} catch (GoogleAuthException ex) {
@@ -1095,6 +1097,45 @@ public void idTokenWithAudience_license() throws IOException {
10951097
assertTrue(googleClaim.containsKey("license"));
10961098
}
10971099

1100+
@Test
1101+
public void idTokenWithAudience_404StatusCode() {
1102+
int statusCode = HttpStatusCodes.STATUS_CODE_NOT_FOUND;
1103+
MockMetadataServerTransportFactory transportFactory = new MockMetadataServerTransportFactory();
1104+
transportFactory.transport.setStatusCode(HttpStatusCodes.STATUS_CODE_NOT_FOUND);
1105+
ComputeEngineCredentials credentials =
1106+
ComputeEngineCredentials.newBuilder().setHttpTransportFactory(transportFactory).build();
1107+
IOException exception =
1108+
assertThrows(IOException.class, () -> credentials.idTokenWithAudience("Audience", null));
1109+
assertEquals(
1110+
String.format(
1111+
"Error code %s trying to get identity token from"
1112+
+ " Compute Engine metadata. This may be because the virtual machine instance"
1113+
+ " does not have permission scopes specified.",
1114+
statusCode),
1115+
exception.getMessage());
1116+
}
1117+
1118+
@Test
1119+
public void idTokenWithAudience_emptyContent() {
1120+
MockMetadataServerTransportFactory transportFactory = new MockMetadataServerTransportFactory();
1121+
transportFactory.transport.setEmptyContent(true);
1122+
ComputeEngineCredentials credentials =
1123+
ComputeEngineCredentials.newBuilder().setHttpTransportFactory(transportFactory).build();
1124+
IOException exception =
1125+
assertThrows(IOException.class, () -> credentials.idTokenWithAudience("Audience", null));
1126+
assertEquals(METADATA_RESPONSE_EMPTY_CONTENT_ERROR_MESSAGE, exception.getMessage());
1127+
}
1128+
1129+
@Test
1130+
public void idTokenWithAudience_503StatusCode() {
1131+
MockMetadataServerTransportFactory transportFactory = new MockMetadataServerTransportFactory();
1132+
transportFactory.transport.setStatusCode(HttpStatusCodes.STATUS_CODE_SERVICE_UNAVAILABLE);
1133+
ComputeEngineCredentials credentials =
1134+
ComputeEngineCredentials.newBuilder().setHttpTransportFactory(transportFactory).build();
1135+
assertThrows(
1136+
GoogleAuthException.class, () -> credentials.idTokenWithAudience("Audience", null));
1137+
}
1138+
10981139
static class MockMetadataServerTransportFactory implements HttpTransportFactory {
10991140

11001141
MockMetadataServerTransport transport =

oauth2_http/javatests/com/google/auth/oauth2/MockMetadataServerTransport.java

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131

3232
package com.google.auth.oauth2;
3333

34+
import com.google.api.client.http.HttpStatusCodes;
3435
import com.google.api.client.http.LowLevelHttpRequest;
3536
import com.google.api.client.http.LowLevelHttpResponse;
3637
import com.google.api.client.json.GenericJson;
@@ -55,7 +56,7 @@ public class MockMetadataServerTransport extends MockHttpTransport {
5556

5657
// key are scopes as in request url string following "?scopes="
5758
private Map<String, String> scopesToAccessToken;
58-
private Integer requestStatusCode;
59+
private Integer statusCode;
5960

6061
private String serviceAccountEmail;
6162

@@ -91,8 +92,8 @@ public void setAccessToken(String scopes, String accessToken) {
9192
scopesToAccessToken.put(scopes, accessToken);
9293
}
9394

94-
public void setRequestStatusCode(Integer requestStatusCode) {
95-
this.requestStatusCode = requestStatusCode;
95+
public void setStatusCode(Integer statusCode) {
96+
this.statusCode = statusCode;
9697
}
9798

9899
public void setServiceAccountEmail(String serviceAccountEmail) {
@@ -140,14 +141,15 @@ public LowLevelHttpRequest buildRequest(String method, String url) throws IOExce
140141
new MockLowLevelHttpRequest(url) {
141142
@Override
142143
public LowLevelHttpResponse execute() {
143-
if (requestStatusCode != null) {
144+
if (statusCode != null && (statusCode >= 400 && statusCode < 600)) {
144145
return new MockLowLevelHttpResponse()
145-
.setStatusCode(requestStatusCode)
146+
.setStatusCode(statusCode)
146147
.setContent("Metadata Error");
147148
}
148149

149150
MockLowLevelHttpResponse response = new MockLowLevelHttpResponse();
150151
response.addHeader("Metadata-Flavor", "Google");
152+
response.setStatusCode(HttpStatusCodes.STATUS_CODE_OK);
151153
return response;
152154
}
153155
};
@@ -195,9 +197,9 @@ private MockLowLevelHttpRequest getMockRequestForTokenEndpoint(String url) {
195197
@Override
196198
public LowLevelHttpResponse execute() throws IOException {
197199

198-
if (requestStatusCode != null) {
200+
if (statusCode != null && (statusCode >= 400 && statusCode < 600)) {
199201
return new MockLowLevelHttpResponse()
200-
.setStatusCode(requestStatusCode)
202+
.setStatusCode(statusCode)
201203
.setContent("Token Fetch Error");
202204
}
203205

@@ -224,20 +226,35 @@ public LowLevelHttpResponse execute() throws IOException {
224226

225227
return new MockLowLevelHttpResponse()
226228
.setContentType(Json.MEDIA_TYPE)
229+
.setStatusCode(HttpStatusCodes.STATUS_CODE_OK)
227230
.setContent(refreshText);
228231
}
229232
};
230233
}
231234

232235
private MockLowLevelHttpRequest getMockRequestForIdentityDocument(String url)
233236
throws MalformedURLException, UnsupportedEncodingException {
234-
if (idToken != null) {
237+
if (statusCode != null && statusCode != HttpStatusCodes.STATUS_CODE_OK) {
235238
return new MockLowLevelHttpRequest(url) {
236239
@Override
237-
public LowLevelHttpResponse execute() throws IOException {
240+
public LowLevelHttpResponse execute() {
241+
return new MockLowLevelHttpResponse().setStatusCode(statusCode);
242+
}
243+
};
244+
} else if (idToken != null) {
245+
return new MockLowLevelHttpRequest(url) {
246+
@Override
247+
public LowLevelHttpResponse execute() {
238248
return new MockLowLevelHttpResponse().setContent(idToken);
239249
}
240250
};
251+
} else if (emptyContent) {
252+
return new MockLowLevelHttpRequest(url) {
253+
@Override
254+
public LowLevelHttpResponse execute() {
255+
return new MockLowLevelHttpResponse();
256+
}
257+
};
241258
}
242259

243260
// https://cloud.google.com/compute/docs/instances/verifying-instance-identity#token_format
@@ -299,15 +316,15 @@ public LowLevelHttpResponse execute() throws IOException {
299316
// Create the JSON response
300317
GenericJson content = new GenericJson();
301318
content.setFactory(OAuth2Utils.JSON_FACTORY);
302-
if (requestStatusCode == 200) {
319+
if (statusCode == HttpStatusCodes.STATUS_CODE_OK) {
303320
content.put(SecureSessionAgent.S2A_JSON_KEY, s2aContentMap);
304321
}
305322
String contentText = content.toPrettyString();
306323

307324
MockLowLevelHttpResponse response = new MockLowLevelHttpResponse();
308325

309-
if (requestStatusCode != null) {
310-
response.setStatusCode(requestStatusCode);
326+
if (statusCode != null) {
327+
response.setStatusCode(statusCode);
311328
}
312329
if (emptyContent == true) {
313330
return response.setZeroContent();

0 commit comments

Comments
 (0)