Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Service Account Impersonation option for credentials #3516

Open
Antrakos opened this issue Feb 3, 2025 · 0 comments
Open

Service Account Impersonation option for credentials #3516

Antrakos opened this issue Feb 3, 2025 · 0 comments
Labels
priority: p3 type: enhancement New feature or request

Comments

@Antrakos
Copy link
Contributor

Antrakos commented Feb 3, 2025

Is your feature request related to a problem? Please describe.
We are starting to heavily use GCP Auth in our applications, primarily when working with GCS buckets. We have a development model where developers start applications locally and they connect to all Dev env resources, including databases, buckets, regular services from dev cluster, etc. This works fine for resource with static credentials, like username:password for databases, but when it comes to GCP Auth at the moment we are left with two choices neither of which we like:

  • static application json credentials via spring.cloud.gcp.credentials.encoded-key. This would require to generate a static creds for each service which will pollute our SecretManager and also poses a security risk of having static creds to service account.
  • rely on developer's user credentials. This option doesn't suit us primarily because it breaks the principle of reproducing dev environment locally, because it forces us to implicitly provide devs with full access to all dev resources and they can easily forget to add the necessary permissions for dev service account so their code works locally, but will fail once deployed to dev env.

Ideally we want to use real dev service accounts locally, but avoid the hassle of provisioning static creds. This is where service account impersonation comes into place.

Describe the solution you'd like
I would like to see a spring.cloud.gcp.credentials.impersonate-account property supported, which takes a service account email and uses default user credentials to impersonate this service account. Hence all the other GCP components would use ImpersonatedCredentials implicitly. We would enable this only locally (via spring profiles) and rely on default creds in GKE.

We've experimented with a potential implementation and it seems like a few lines of code (barring any docs). It is possible to implement this in our custom library with a additional AutoConfiguration, but we would greatly appreciate if this were to be supported out of the box so we don't need to maintain extra library for one class. Here's the example we ended up with:

import com.google.api.gax.core.CredentialsProvider;
import com.google.auth.Credentials;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.auth.oauth2.ImpersonatedCredentials;

import java.io.IOException;
import java.util.List;

public class ImpersonatedCredentialsProvider implements CredentialsProvider {
    private final String serviceAccount;
    private final List<String> scopes;

    public ImpersonatedCredentialsProvider(String serviceAccount, List<String> scopes) {
        this.serviceAccount = serviceAccount;
        this.scopes = scopes;
    }

    @Override
    public Credentials getCredentials() throws IOException {
        var sourceCredentials = GoogleCredentials.getApplicationDefault();
        return ImpersonatedCredentials.create(sourceCredentials, serviceAccount, null, scopes, 0);
    }
}
@AutoConfiguration
@ConditionalOnProperty({"spring.cloud.gcp.credentials.impersonate-account", "spring.cloud.gcp.core.enabled" })
public class GcpAutoConfiguration {
    @Bean
    @ConditionalOnMissingBean
    public CredentialsProvider credentialsProvider(
        @Value("${spring.cloud.gcp.credentials.impersonate-account}") String serviceAccount,
        @Value("${spring.cloud.gcp.credentials.scopes}") List<String> scopes
    ) {
        return new ImpersonatedCredentialsProvider(serviceAccount, resolveScopes(scopes));
    }
}

Describe alternatives you've considered
Technically there's an option to generate impersonated credentials in a gradle task before bootRun and expose base64 decoded json as env var so that spring-cloud-gcp would treat it as regular static creds, but this looks like an over-engineering to me considering spring-cloud-gcp already has multiple auth options.

Additional context
I think that adding this property will cover all GCP services we use. We are considering switching to CloudSQL IAM auth, but spring-cloud-gcp already supports account impersonation natively with another sql-specific property spring.cloud.gcp.sql.targetPrincipal.

@zhumin8 zhumin8 added type: enhancement New feature or request priority: p3 labels Feb 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
priority: p3 type: enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants