Skip to content

Commit 773f1d3

Browse files
committed
Add Google Drive readonly scope to all auth mechanisms
1 parent 8095342 commit 773f1d3

1 file changed

Lines changed: 94 additions & 39 deletions

File tree

java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcOAuthUtility.java

Lines changed: 94 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,17 @@ static Map<String, String> parseOAuthProperties(DataSource ds, String callerClas
117117
throw new IllegalArgumentException(OAUTH_TYPE_ERROR_MESSAGE);
118118
}
119119
oauthProperties.put(BigQueryJdbcUrlUtility.OAUTH_TYPE_PROPERTY_NAME, String.valueOf(authType));
120+
121+
Integer reqGoogleDriveScope = ds.getRequestGoogleDriveScope();
122+
if( reqGoogleDriveScope != null){
123+
Boolean reqGoogleDriveScopeBool = BigQueryJdbcUrlUtility.convertIntToBoolean(String.valueOf(reqGoogleDriveScope), BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME);
124+
oauthProperties.put(
125+
BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME,
126+
String.valueOf(reqGoogleDriveScopeBool));
127+
LOG.fine("RequestGoogleDriveScope parsed.");
128+
}
129+
130+
120131
switch (authType) {
121132
case GOOGLE_SERVICE_ACCOUNT:
122133
// For using a Google Service Account (OAuth Type 0)
@@ -144,11 +155,6 @@ static Map<String, String> parseOAuthProperties(DataSource ds, String callerClas
144155
BigQueryJdbcUrlUtility.OAUTH_CLIENT_ID_PROPERTY_NAME, ds.getOAuthClientId());
145156
oauthProperties.put(
146157
BigQueryJdbcUrlUtility.OAUTH_CLIENT_SECRET_PROPERTY_NAME, ds.getOAuthClientSecret());
147-
int reqGoogleDriveScope = ds.getRequestGoogleDriveScope();
148-
oauthProperties.put(
149-
BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME,
150-
String.valueOf(reqGoogleDriveScope));
151-
LOG.fine("RequestGoogleDriveScope parsed.");
152158
break;
153159
case PRE_GENERATED_TOKEN:
154160
String refreshToken = ds.getOAuthRefreshToken();
@@ -280,7 +286,7 @@ static GoogleCredentials getCredentials(
280286
break;
281287
case APPLICATION_DEFAULT_CREDENTIALS:
282288
// This auth method doesn't support service account impersonation
283-
return getApplicationDefaultCredentials(callerClassName);
289+
return getApplicationDefaultCredentials(authProperties, callerClassName);
284290
case EXTERNAL_ACCOUNT_AUTH:
285291
// This auth method doesn't support service account impersonation
286292
return getExternalAccountAuthCredentials(authProperties, callerClassName);
@@ -373,6 +379,13 @@ private static GoogleCredentials getGoogleServiceAccountCredentials(
373379
builder.setUniverseDomain(
374380
overrideProperties.get(BigQueryJdbcUrlUtility.UNIVERSE_DOMAIN_OVERRIDE_PROPERTY_NAME));
375381
}
382+
if ("true".equals(authProperties.get(BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME))){
383+
builder.setScopes(
384+
Arrays.asList(
385+
"https://www.googleapis.com/auth/bigquery",
386+
"https://www.googleapis.com/auth/drive.readonly"));
387+
LOG.fine("Added Google Drive read-only scope to Service Account builder.");
388+
}
376389
} catch (URISyntaxException | IOException e) {
377390
LOG.severe("Validation failure for Service Account credentials.");
378391
throw new BigQueryJdbcRuntimeException(e);
@@ -388,28 +401,6 @@ static UserAuthorizer getUserAuthorizer(
388401
String callerClassName)
389402
throws URISyntaxException {
390403
LOG.finest("++enter++\t" + callerClassName);
391-
List<String> scopes = new ArrayList<>();
392-
scopes.add("https://www.googleapis.com/auth/bigquery");
393-
394-
// Add Google Drive scope conditionally
395-
if (authProperties.containsKey(
396-
BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME)) {
397-
try {
398-
int driveScopeValue =
399-
Integer.parseInt(
400-
authProperties.get(
401-
BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME));
402-
if (driveScopeValue == 1) {
403-
scopes.add("https://www.googleapis.com/auth/drive.readonly");
404-
LOG.fine("Added Google Drive read-only scope. Caller: " + callerClassName);
405-
}
406-
} catch (NumberFormatException e) {
407-
LOG.severe(
408-
"Invalid value for RequestGoogleDriveScope, defaulting to not request Drive scope."
409-
+ " Caller: "
410-
+ callerClassName);
411-
}
412-
}
413404

414405
List<String> responseTypes = new ArrayList<>();
415406
responseTypes.add("code");
@@ -421,13 +412,21 @@ static UserAuthorizer getUserAuthorizer(
421412
UserAuthorizer.Builder userAuthorizerBuilder =
422413
UserAuthorizer.newBuilder()
423414
.setClientId(clientId)
424-
.setScopes(scopes)
425415
.setCallbackUri(URI.create("http://localhost:" + port));
426416

427417
if (overrideProperties.containsKey(BigQueryJdbcUrlUtility.OAUTH2_TOKEN_URI_PROPERTY_NAME)) {
428418
userAuthorizerBuilder.setTokenServerUri(
429419
new URI(overrideProperties.get(BigQueryJdbcUrlUtility.OAUTH2_TOKEN_URI_PROPERTY_NAME)));
430420
}
421+
List<String> scopes = new ArrayList<>();
422+
scopes.add("https://www.googleapis.com/auth/bigquery");
423+
424+
if ("true".equals(authProperties.get(BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME))) {
425+
scopes.add("https://www.googleapis.com/auth/drive.readonly");
426+
LOG.fine("Added Google Drive read-only scope to User Account builder.");
427+
}
428+
429+
userAuthorizerBuilder.setScopes(scopes);
431430

432431
return userAuthorizerBuilder.build();
433432
}
@@ -500,14 +499,27 @@ private static GoogleCredentials getPreGeneratedAccessTokenCredentials(
500499
builder.setUniverseDomain(
501500
overrideProperties.get(BigQueryJdbcUrlUtility.UNIVERSE_DOMAIN_OVERRIDE_PROPERTY_NAME));
502501
}
502+
503503
LOG.info("Connection established. Auth Method: Pre-generated Access Token.");
504-
return builder
504+
GoogleCredentials credentials = builder
505505
.setAccessToken(
506506
AccessToken.newBuilder()
507507
.setTokenValue(
508508
authProperties.get(BigQueryJdbcUrlUtility.OAUTH_ACCESS_TOKEN_PROPERTY_NAME))
509509
.build())
510510
.build();
511+
512+
513+
if ("true".equals(authProperties.get(BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME))) {
514+
credentials = credentials.createScoped(
515+
Arrays.asList(
516+
"https://www.googleapis.com/auth/bigquery",
517+
"https://www.googleapis.com/auth/drive.readonly"
518+
)
519+
);
520+
}
521+
522+
return credentials;
511523
}
512524

513525
static GoogleCredentials getPreGeneratedTokensCredentials(
@@ -552,11 +564,22 @@ static UserCredentials getPreGeneratedRefreshTokenCredentials(
552564
userCredentialsBuilder.setUniverseDomain(
553565
overrideProperties.get(BigQueryJdbcUrlUtility.UNIVERSE_DOMAIN_OVERRIDE_PROPERTY_NAME));
554566
}
567+
568+
UserCredentials userCredentials = userCredentialsBuilder.build();
569+
570+
if ("true".equals(authProperties.get(BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME))) {
571+
userCredentials = (UserCredentials) userCredentials.createScoped(
572+
Arrays.asList(
573+
"https://www.googleapis.com/auth/bigquery",
574+
"https://www.googleapis.com/auth/drive.readonly"
575+
)
576+
);
577+
}
555578
LOG.info("Connection established. Auth Method: Pre-generated Refresh Token.");
556-
return userCredentialsBuilder.build();
579+
return userCredentials;
557580
}
558581

559-
private static GoogleCredentials getApplicationDefaultCredentials(String callerClassName) {
582+
private static GoogleCredentials getApplicationDefaultCredentials(Map<String, String> authProperties, String callerClassName) {
560583
LOG.finest("++enter++\t" + callerClassName);
561584
try {
562585
GoogleCredentials credentials = GoogleCredentials.getApplicationDefault();
@@ -571,6 +594,17 @@ private static GoogleCredentials getApplicationDefaultCredentials(String callerC
571594
LOG.info(
572595
"Connection established. Auth Method: Application Default Credentials, Principal: %s.",
573596
principal);
597+
598+
if ("true".equals(authProperties.get(BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME))) {
599+
credentials = credentials.createScoped(
600+
Arrays.asList(
601+
"https://www.googleapis.com/auth/bigquery",
602+
"https://www.googleapis.com/auth/drive.readonly"
603+
)
604+
);
605+
LOG.fine("Added Google Drive read-only scope to ADC credentials.");
606+
}
607+
574608
return credentials;
575609
} catch (IOException exception) {
576610
// TODO throw exception
@@ -616,16 +650,29 @@ private static GoogleCredentials getExternalAccountAuthCredentials(
616650
}
617651
}
618652

653+
GoogleCredentials credentials;
619654
if (credentialsPath != null) {
620-
return ExternalAccountCredentials.fromStream(
655+
credentials = ExternalAccountCredentials.fromStream(
621656
Files.newInputStream(Paths.get(credentialsPath)));
622657
} else if (jsonObject != null) {
623-
return ExternalAccountCredentials.fromStream(
658+
credentials = ExternalAccountCredentials.fromStream(
624659
new ByteArrayInputStream(jsonObject.toString().getBytes()));
625660
} else {
626661
throw new IllegalArgumentException(
627662
"Insufficient info provided for external authentication");
628663
}
664+
665+
if ("true".equals(authProperties.get(BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME))) {
666+
credentials = credentials.createScoped(
667+
Arrays.asList(
668+
"https://www.googleapis.com/auth/bigquery",
669+
"https://www.googleapis.com/auth/drive.readonly"
670+
)
671+
);
672+
LOG.fine("Added Google Drive read-only scope to External Account credentials.");
673+
}
674+
675+
return credentials;
629676
} catch (IOException e) {
630677
throw new BigQueryJdbcRuntimeException(e);
631678
}
@@ -634,7 +681,7 @@ private static GoogleCredentials getExternalAccountAuthCredentials(
634681
// This function checks if connection string contains configuration for
635682
// credentials impersonation. If not, it returns regular credentials object.
636683
// If impersonated service account is provided, returns Credentials object
637-
// accomodating this information.
684+
// accommodating this information.
638685
private static GoogleCredentials getServiceAccountImpersonatedCredentials(
639686
GoogleCredentials credentials, Map<String, String> authProperties) {
640687

@@ -653,10 +700,18 @@ private static GoogleCredentials getServiceAccountImpersonatedCredentials(
653700

654701
// Scopes has a default value, so it should never be null
655702
List<String> impersonationScopes =
656-
Arrays.asList(
657-
authProperties
658-
.get(BigQueryJdbcUrlUtility.OAUTH_SA_IMPERSONATION_SCOPES_PROPERTY_NAME)
659-
.split(","));
703+
new java.util.ArrayList<>(
704+
Arrays.asList(
705+
authProperties
706+
.get(BigQueryJdbcUrlUtility.OAUTH_SA_IMPERSONATION_SCOPES_PROPERTY_NAME)
707+
.split(",")));
708+
709+
if ("true".equals(authProperties.get(BigQueryJdbcUrlUtility.REQUEST_GOOGLE_DRIVE_SCOPE_PROPERTY_NAME))) {
710+
if (!impersonationScopes.contains("https://www.googleapis.com/auth/drive.readonly")) {
711+
impersonationScopes.add("https://www.googleapis.com/auth/drive.readonly");
712+
LOG.fine("Added Google Drive read-only scope to impersonation scopes.");
713+
}
714+
}
660715

661716
// Token lifetime has a default value, so it should never be null
662717
String impersonationLifetime =

0 commit comments

Comments
 (0)