Skip to content

Auth: Support impersonate service account with gcloud cli #454

@rebaz94

Description

@rebaz94

Hi,
It will be great if we can use impersonate service account with gcloud cli, so that it can test google service locally without downloading a service account.

currently clientViaApplicationDefaultCredentials will not use source_credentials when running this command

gcloud auth application-default login --impersonate-service-account=principal@example.iam.gserviceaccount.com

the parsing credentials here does not check for source_credentials. as a workaround I just added some code and work properly.

Modified code of fromApplicationsCredentialsFile

Future<AutoRefreshingAuthClient> fromApplicationsCredentialsFile(

Future<AutoRefreshingAuthClient> fromApplicationsCredentialsFile(
  File file,
  String fileSource,
  List<String> scopes,
  Client baseClient,
) async {
  Object? credentials;
  try {
    credentials = json.decode(await file.readAsString());
  } on IOException {
    throw Exception(
      'Failed to read credentials file from $fileSource',
    );
  } on FormatException {
    throw Exception(
      'Failed to parse JSON from credentials file from $fileSource',
    );
  }

  if (credentials is Map && credentials['type'] == 'authorized_user') {
    final clientId = ClientId(
      credentials['client_id'] as String,
      credentials['client_secret'] as String?,
    );
    return AutoRefreshingClient(
      baseClient,
      clientId,
      await refreshCredentials(
        clientId,
        AccessCredentials(
          // Hack: Create empty credentials that have expired.
          AccessToken('Bearer', '', DateTime(0).toUtc()),
          credentials['refresh_token'] as String?,
          scopes,
        ),
        baseClient,
      ),
      quotaProject: credentials['quota_project_id'] as String?,
    );
  }

  if (credentials is Map && credentials['source_credentials']?['type'] == 'authorized_user') {
    final clientId = ClientId(
      credentials['source_credentials']['client_id'] as String,
      credentials['source_credentials']['client_secret'] as String?,
    );
    return AutoRefreshingClient(
      baseClient,
      clientId,
      await refreshCredentials(
        clientId,
        AccessCredentials(
          // Hack: Create empty credentials that have expired.
          AccessToken('Bearer', '', DateTime(0).toUtc()),
          credentials['source_credentials']['refresh_token'] as String?,
          scopes,
        ),
        baseClient,
      ),
      quotaProject: credentials['quota_project_id'] as String?,
    );
  }

  return await clientViaServiceAccount(
    ServiceAccountCredentials.fromJson(credentials),
    scopes,
    baseClient: baseClient,
  );
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions