in sources/src/main/java/com/google/solutions/jitaccess/ApplicationRuntime.java [108:219]
public static ApplicationRuntime detect(
@NotNull Set<String> requiredOauthScopes
) throws IOException {
if (isRunningOnAppEngine() || isRunningOnCloudRun()) {
//
// Initialize using service account attached to AppEngine or Cloud Run.
//
var projectMetadata = getMetadata().parseAs(GenericData.class);
var projectId = (String) projectMetadata.get("projectId");
var projectNumber = projectMetadata.get("numericProjectId").toString();
var defaultCredentials = (ComputeEngineCredentials)GoogleCredentials.getApplicationDefault();
var applicationPrincipal = ServiceAccountId
.parse(ServiceAccountId.TYPE + ":" + defaultCredentials.getAccount())
.orElseThrow(() -> new IllegalArgumentException(
String.format("'%s' is not a valid service account email address",
defaultCredentials.getAccount())));
GoogleCredentials applicationCredentials;
if (defaultCredentials.getScopes().containsAll(requiredOauthScopes)) {
//
// Default credential has all the right scopes, use it as-is.
//
applicationCredentials = defaultCredentials;
}
else {
//
// Extend the set of scopes to include required non-cloud APIs by
// letting the service account impersonate itself.
//
applicationCredentials = ImpersonatedCredentials.create(
defaultCredentials,
applicationPrincipal.value(),
null,
requiredOauthScopes.stream().toList(),
0);
}
return new ApplicationRuntime(
isRunningOnAppEngine() ? Type.APPENGINE : Type.CLOUDRUN,
new ProjectId(projectId),
projectNumber,
applicationCredentials,
applicationPrincipal);
}
else if (isDebugModeEnabled()) {
//
// Initialize using development settings and credential.
//
var defaultCredentials = GoogleCredentials.getApplicationDefault();
var impersonateServiceAccount = ServiceAccountId.parse(
ServiceAccountId.TYPE + ":" + System.getProperty(CONFIG_IMPERSONATE_SA));
GoogleCredentials applicationCredentials;
ServiceAccountId applicationPrincipal;
if (impersonateServiceAccount.isPresent()) {
//
// Use the application default credentials (ADC) to impersonate a
// service account. This step is necessary to ensure we have a
// credential for the right set of scopes, and that we're not running
// with end-user credentials.
//
applicationCredentials = ImpersonatedCredentials.create(
defaultCredentials,
impersonateServiceAccount.get().value(),
null,
requiredOauthScopes.stream().toList(),
0);
//
// If we lack impersonation permissions, ImpersonatedCredentials
// will keep retrying until the call timeout expires. The effect
// is that the application seems hung.
//
// To prevent this from happening, force a refresh here. If the
// refresh fails, fail application startup.
//
applicationCredentials.refresh();
applicationPrincipal = impersonateServiceAccount.get();
}
else if (defaultCredentials instanceof ServiceAccountCredentials saCredentials) {
//
// Use ADC as-is.
//
applicationCredentials = defaultCredentials;
applicationPrincipal = ServiceAccountId
.parse(saCredentials.getServiceAccountUser())
.orElseThrow(() -> new RuntimeException(String.format(
"The email '%s' is not a valid service account email address",
saCredentials.getServiceAccountUser())));
}
else {
throw new IllegalArgumentException(String.format(
"You're using user credentials as application default "
+ "credentials (ADC). Use -D%s=<service-account-email> to impersonate "
+ "a service account during development",
CONFIG_IMPERSONATE_SA));
}
return new ApplicationRuntime(
Type.DEVELOPMENT,
new ProjectId(System.getProperty(CONFIG_PROJECT, "dev")),
"0",
applicationCredentials,
applicationPrincipal);
}
else {
throw new RuntimeException(
"Application is not running on AppEngine or Cloud Run, and debug mode is disabled. Aborting startup");
}
}