All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.quarkiverse.googlecloudservices.common.GcpCredentialProducer Maven / Gradle / Ivy

package io.quarkiverse.googlecloudservices.common;

import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Base64;

import jakarta.annotation.PostConstruct;
import jakarta.enterprise.context.ContextNotActiveException;
import jakarta.enterprise.inject.Default;
import jakarta.enterprise.inject.Instance;
import jakarta.enterprise.inject.Produces;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;

import com.google.auth.oauth2.AccessToken;
import com.google.auth.oauth2.GoogleCredentials;

import io.quarkus.security.credential.Credential;
import io.quarkus.security.credential.TokenCredential;
import io.quarkus.security.identity.SecurityIdentity;

@Singleton
public class GcpCredentialProducer {

    private static final String CLOUD_OAUTH_SCOPE = "https://www.googleapis.com/auth/cloud-platform";

    @Inject
    Instance securityIdentity;

    @Inject
    GcpConfigHolder gcpConfigHolder;

    @PostConstruct
    public void verifySecurityIdentity() {
        if (securityIdentity.isResolvable() && securityIdentity.isAmbiguous()) {
            throw new IllegalStateException("Multiple " + SecurityIdentity.class + " beans registered");
        }
    }

    @Produces
    @Singleton
    @Default
    public GoogleCredentials googleCredential() throws IOException {
        GcpBootstrapConfiguration gcpConfiguration = gcpConfigHolder.getBootstrapConfig();
        if (gcpConfiguration.serviceAccountLocation.isPresent()) {
            try (FileInputStream is = new FileInputStream(gcpConfiguration.serviceAccountLocation.get())) {
                return GoogleCredentials.fromStream(is).createScoped(CLOUD_OAUTH_SCOPE);
            }
        } else if (gcpConfiguration.serviceAccountEncodedKey.isPresent()) {
            byte[] decode = Base64.getDecoder().decode(gcpConfiguration.serviceAccountEncodedKey.get());
            try (ByteArrayInputStream is = new ByteArrayInputStream(decode)) {
                return GoogleCredentials.fromStream(is).createScoped(CLOUD_OAUTH_SCOPE);
            }
        } else if (gcpConfiguration.accessTokenEnabled && securityIdentity.isResolvable()
                && !isAnonymous(securityIdentity.get())) {
            for (Credential cred : securityIdentity.get().getCredentials()) {
                if (cred instanceof TokenCredential && "bearer".equals(((TokenCredential) cred).getType())) {
                    return GoogleCredentials
                            .create(new AccessToken(((TokenCredential) cred).getToken(), null))
                            .createScoped(CLOUD_OAUTH_SCOPE);
                }
            }
        }

        return GoogleCredentials.getApplicationDefault().createScoped(CLOUD_OAUTH_SCOPE);
    }

    private boolean isAnonymous(SecurityIdentity securityIdentity) {
        try {
            return securityIdentity.isAnonymous();
        } catch (ContextNotActiveException e) {
            // this is less than ideal but currently when the credential is returned out of a request context
            // (for eg at configuration time for a config source) this exception can arise.
            return true;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy