diff --git a/spring-vault-core/src/main/java/org/springframework/vault/authentication/DefaultGcpCredentialAccessors.java b/spring-vault-core/src/main/java/org/springframework/vault/authentication/DefaultGcpCredentialAccessors.java new file mode 100644 index 00000000..bc59dae7 --- /dev/null +++ b/spring-vault-core/src/main/java/org/springframework/vault/authentication/DefaultGcpCredentialAccessors.java @@ -0,0 +1,68 @@ +/* + * Copyright 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.vault.authentication; + +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; + +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; + +/** + * Default implementation of{@link GcpProjectIdAccessor} and + * {@link GcpServiceAccountIdAccessor}. Used by {@link GcpIamAuthentication}. + * + * @author Magnus Jungsbluth + * @author Mark Paluch + * @since 2.1 + * @see GcpIamAuthentication + */ +enum DefaultGcpCredentialAccessors implements GcpProjectIdAccessor, + GcpServiceAccountIdAccessor { + + INSTANCE; + + /** + * Get a the service account id (email) to be placed in the signed JWT. + * + * @param credential credential object to obtain the service account id from. + * @return the service account id to use. + */ + @Override + public String getServiceAccountId(GoogleCredential credential) { + + Assert.notNull(credential, "GoogleCredential must not be null"); + Assert.notNull( + credential.getServiceAccountId(), + "The configured GoogleCredential does not represent a service account. Configure the service account id with GcpIamAuthenticationOptionsBuilder#serviceAccountId(String)."); + + return credential.getServiceAccountId(); + } + + /** + * Get a the GCP project id to used in Google Cloud IAM API calls. + * + * @param credential the credential object to obtain the project id from. + * @return the service account id to use. + */ + @Override + public String getProjectId(GoogleCredential credential) { + + Assert.notNull(credential, "GoogleCredential must not be null"); + + return StringUtils.isEmpty(credential.getServiceAccountProjectId()) ? "-" + : credential.getServiceAccountProjectId(); + } +} diff --git a/spring-vault-core/src/main/java/org/springframework/vault/authentication/DefaultGcpProjectIdProvider.java b/spring-vault-core/src/main/java/org/springframework/vault/authentication/DefaultGcpProjectIdProvider.java deleted file mode 100644 index 15067a5c..00000000 --- a/spring-vault-core/src/main/java/org/springframework/vault/authentication/DefaultGcpProjectIdProvider.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.vault.authentication; - -import org.springframework.util.StringUtils; - -import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; - -/** - * Default implementation to obtain a GCP project id for GCP IAM authentication. - * Used by {@link GcpIamAuthentication}. - * - * @author Magnus Jungsbluth - * @since 2.1 - * @see GcpIamAuthentication - */ -public class DefaultGcpProjectIdProvider implements GcpProjectIdProvider { - - @Override - public String getProjectId(GoogleCredential credential) { - if (StringUtils.isEmpty(credential.getServiceAccountProjectId())) { - return "-"; - } else { - return credential.getServiceAccountProjectId(); - } - } -} diff --git a/spring-vault-core/src/main/java/org/springframework/vault/authentication/DefaultGcpServiceAccountIdProvider.java b/spring-vault-core/src/main/java/org/springframework/vault/authentication/DefaultGcpServiceAccountIdProvider.java deleted file mode 100644 index 78f1e2f4..00000000 --- a/spring-vault-core/src/main/java/org/springframework/vault/authentication/DefaultGcpServiceAccountIdProvider.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.vault.authentication; - -import org.springframework.util.Assert; - -import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; - -/** - * Default implementation to obtain a service account id for GCP IAM authentication. - * Used by {@link GcpIamAuthentication}. - * - * @author Magnus Jungsbluth - * @since 2.1 - * @see GcpIamAuthentication - */ -public class DefaultGcpServiceAccountIdProvider implements GcpServiceAccountIdProvider { - - @Override - public String getServiceAccountId(GoogleCredential credential) { - Assert.notNull(credential.getServiceAccountId(), "The configured GoogleCredential does not represent a service account. Configure the service account id manually"); - - return credential.getServiceAccountId(); - } - -} diff --git a/spring-vault-core/src/main/java/org/springframework/vault/authentication/GcpIamAuthentication.java b/spring-vault-core/src/main/java/org/springframework/vault/authentication/GcpIamAuthentication.java index 80944a16..8455e822 100644 --- a/spring-vault-core/src/main/java/org/springframework/vault/authentication/GcpIamAuthentication.java +++ b/spring-vault-core/src/main/java/org/springframework/vault/authentication/GcpIamAuthentication.java @@ -50,6 +50,7 @@ import org.springframework.web.client.RestOperations; * {@link GcpIamAuthentication} uses Google Java API that uses synchronous API. * * @author Mark Paluch + * @author Magnus Jungsbluth * @since 2.1 * @see GcpIamAuthenticationOptions * @see HttpTransport @@ -125,8 +126,8 @@ public class GcpIamAuthentication extends GcpJwtAuthenticationSupport implements protected String signJwt() { - String projectId = options.getProjectIdProvider().getProjectId(credential); - String serviceAccount = options.getServiceAccountIdProvider().getServiceAccountId(credential); + String projectId = getProjectId(); + String serviceAccount = getServiceAccountId(); Map jwtPayload = getJwtPayload(options, serviceAccount); Iam iam = new Builder(httpTransport, JSON_FACTORY, credential) @@ -154,6 +155,14 @@ public class GcpIamAuthentication extends GcpJwtAuthenticationSupport implements } } + private String getServiceAccountId() { + return options.getServiceAccountIdAccessor().getServiceAccountId(credential); + } + + private String getProjectId() { + return options.getProjectIdAccessor().getProjectId(credential); + } + private static Map getJwtPayload(GcpIamAuthenticationOptions options, String serviceAccount) { diff --git a/spring-vault-core/src/main/java/org/springframework/vault/authentication/GcpIamAuthenticationOptions.java b/spring-vault-core/src/main/java/org/springframework/vault/authentication/GcpIamAuthenticationOptions.java index 28c52942..52ce25e1 100644 --- a/spring-vault-core/src/main/java/org/springframework/vault/authentication/GcpIamAuthenticationOptions.java +++ b/spring-vault-core/src/main/java/org/springframework/vault/authentication/GcpIamAuthenticationOptions.java @@ -32,6 +32,7 @@ import org.springframework.util.Assert; * constructed. * * @author Mark Paluch + * @author Magnus Jungsbluth * @see GcpIamAuthentication * @see #builder() * @since 2.1 @@ -65,26 +66,27 @@ public class GcpIamAuthenticationOptions { private final Clock clock; /** - * Provide the service account id to use as sub/iss claims + * Provide the service account id to use as sub/iss claims. */ - private final GcpServiceAccountIdProvider serviceAccountIdSupplier; + private final GcpServiceAccountIdAccessor serviceAccountIdAccessor; /** - * The GCP project id to use in GCP IAM API calls + * The GCP project id to use in GCP IAM API calls. */ - private final GcpProjectIdProvider projectIdSupplier; + private final GcpProjectIdAccessor projectIdAccessor; private GcpIamAuthenticationOptions(String path, GcpCredentialSupplier credentialSupplier, String role, Duration jwtValidity, - Clock clock, GcpServiceAccountIdProvider serviceAccountIdSupplier, GcpProjectIdProvider projectIdSupplier) { + Clock clock, GcpServiceAccountIdAccessor serviceAccountIdSupplier, + GcpProjectIdAccessor projectIdAccessor) { this.path = path; this.credentialSupplier = credentialSupplier; this.role = role; this.jwtValidity = jwtValidity; this.clock = clock; - this.serviceAccountIdSupplier = serviceAccountIdSupplier; - this.projectIdSupplier = projectIdSupplier; + this.serviceAccountIdAccessor = serviceAccountIdSupplier; + this.projectIdAccessor = projectIdAccessor; } /** @@ -130,17 +132,19 @@ public class GcpIamAuthenticationOptions { } /** - * Provide the service account id to use as sub/iss claims + * @return the service account id to use as sub/iss claims. + * @since 2.1 */ - public GcpServiceAccountIdProvider getServiceAccountIdProvider() { - return serviceAccountIdSupplier; + public GcpServiceAccountIdAccessor getServiceAccountIdAccessor() { + return serviceAccountIdAccessor; } /** - * The GCP project id to use in GCP IAM API calls + * @return GCP project id accessor to obtain the project id of GCP IAM API calls. + * @since 2.1 */ - public GcpProjectIdProvider getProjectIdProvider() { - return projectIdSupplier; + public GcpProjectIdAccessor getProjectIdAccessor() { + return projectIdAccessor; } /** @@ -160,9 +164,9 @@ public class GcpIamAuthenticationOptions { private Clock clock = Clock.systemDefaultZone(); - private GcpServiceAccountIdProvider serviceAccountIdProvider = new DefaultGcpServiceAccountIdProvider(); + private GcpServiceAccountIdAccessor serviceAccountIdAccessor = DefaultGcpCredentialAccessors.INSTANCE; - private GcpProjectIdProvider projectIdProvider = new DefaultGcpProjectIdProvider(); + private GcpProjectIdAccessor projectIdAccessor = DefaultGcpCredentialAccessors.INSTANCE; GcpIamAuthenticationOptionsBuilder() { } @@ -198,7 +202,7 @@ public class GcpIamAuthenticationOptions { } /** - * Configure an {@link GcpCredentialSupplier}, required to create a signed JWT. + * Configure a {@link GcpCredentialSupplier}, required to create a signed JWT. * Alternatively, configure static {@link #credential(GoogleCredential) * credentials}. * @@ -216,57 +220,72 @@ public class GcpIamAuthenticationOptions { } /** - * Configure an explicit service account id to use in GCP IAM calls. If none is configured, falls back to using - * {@link GoogleCredential#getServiceAccountId()}. + * Configure an explicit service account id to use in GCP IAM calls. If none is + * configured, falls back to using {@link GoogleCredential#getServiceAccountId()}. * * @param serviceAccountId the service account id (email) to use * @return {@code this} {@link GcpIamAuthenticationOptionsBuilder}. + * @since 2.1 */ public GcpIamAuthenticationOptionsBuilder serviceAccountId(String serviceAccountId) { + Assert.notNull(serviceAccountId, "Service account id may not be null"); - return serviceAccountIdProvider((GoogleCredential credential) -> serviceAccountId); + return serviceAccountIdAccessor((GoogleCredential credential) -> serviceAccountId); } /** - * Configure an {@link GcpServiceAccountIdProvider} to obtain the service account id used in GCP IAM calls. - * If none is configured, falls back to using {@link GoogleCredential#getServiceAccountId()}. + * Configure an {@link GcpServiceAccountIdAccessor} to obtain the service account + * id used in GCP IAM calls. If none is configured, falls back to using + * {@link GoogleCredential#getServiceAccountId()}. * - * @param serviceAccountIdProvider the service account id provider to use + * @param serviceAccountIdAccessor the service account id provider to use * @return {@code this} {@link GcpIamAuthenticationOptionsBuilder}. - * @see GcpServiceAccountIdProvider + * @see GcpServiceAccountIdAccessor + * @since 2.1 */ - public GcpIamAuthenticationOptionsBuilder serviceAccountIdProvider(GcpServiceAccountIdProvider serviceAccountIdProvider) { - Assert.notNull(serviceAccountIdProvider, "GcpServiceAccountIdProvider must not be null"); + GcpIamAuthenticationOptionsBuilder serviceAccountIdAccessor( + GcpServiceAccountIdAccessor serviceAccountIdAccessor) { - this.serviceAccountIdProvider = serviceAccountIdProvider; + Assert.notNull(serviceAccountIdAccessor, + "GcpServiceAccountIdAccessor must not be null"); + + this.serviceAccountIdAccessor = serviceAccountIdAccessor; return this; } /** - * Configure an explicit GCP project id to use in GCP IAM API calls. If none is configured, falls back using + * Configure an explicit GCP project id to use in GCP IAM API calls. If none is + * configured, falls back using * {@link GoogleCredential#getServiceAccountProjectId()}. * * @param projectId the GCP project id to use in GCP IAM API calls * @return {@code this} {@link GcpIamAuthenticationOptionsBuilder}. + * @since 2.1 */ public GcpIamAuthenticationOptionsBuilder projectId(String projectId) { + Assert.notNull(projectId, "GCP project id must not be null"); - return projectIdProvider((GoogleCredential credential) -> projectId); + return projectIdAccessor((GoogleCredential credential) -> projectId); } /** - * Configure an {@link GcpProjectIdProvider} to use in GCP IAM API calls. If none is configured, falls back using + * Configure an {@link GcpProjectIdAccessor} to use in GCP IAM API calls. If none + * is configured, falls back using * {@link GoogleCredential#getServiceAccountProjectId()}. * - * @param projectIdProvider the GCP project id supplier to use in GCP IAM API calls + * @param projectIdAccessor the GCP project id supplier to use in GCP IAM API + * calls * @return {@code this} {@link GcpIamAuthenticationOptionsBuilder}. + * @since 2.1 */ - public GcpIamAuthenticationOptionsBuilder projectIdProvider(GcpProjectIdProvider projectIdProvider) { - Assert.notNull(projectIdProvider, "GcpProjectIdProvider must not be null"); + GcpIamAuthenticationOptionsBuilder projectIdAccessor( + GcpProjectIdAccessor projectIdAccessor) { - this.projectIdProvider = projectIdProvider; + Assert.notNull(projectIdAccessor, "GcpProjectIdAccessor must not be null"); + + this.projectIdAccessor = projectIdAccessor; return this; } @@ -325,7 +344,7 @@ public class GcpIamAuthenticationOptions { Assert.notNull(role, "Role must not be null"); return new GcpIamAuthenticationOptions(path, credentialSupplier, role, - jwtValidity, clock, serviceAccountIdProvider, projectIdProvider); + jwtValidity, clock, serviceAccountIdAccessor, projectIdAccessor); } } } diff --git a/spring-vault-core/src/main/java/org/springframework/vault/authentication/GcpProjectIdProvider.java b/spring-vault-core/src/main/java/org/springframework/vault/authentication/GcpProjectIdAccessor.java similarity index 84% rename from spring-vault-core/src/main/java/org/springframework/vault/authentication/GcpProjectIdProvider.java rename to spring-vault-core/src/main/java/org/springframework/vault/authentication/GcpProjectIdAccessor.java index 765038c4..295be860 100644 --- a/spring-vault-core/src/main/java/org/springframework/vault/authentication/GcpProjectIdProvider.java +++ b/spring-vault-core/src/main/java/org/springframework/vault/authentication/GcpProjectIdAccessor.java @@ -18,19 +18,21 @@ package org.springframework.vault.authentication; import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; /** - * Interface to obtain a GCP project id for GCP IAM authentication. - * Implementations are used by {@link GcpIamAuthentication}. + * Interface to obtain a GCP project id for GCP IAM authentication. Implementations are + * used by {@link GcpIamAuthentication}. * * @author Magnus Jungsbluth + * @author Mark Paluch * @since 2.1 * @see GcpIamAuthentication */ @FunctionalInterface -public interface GcpProjectIdProvider { +public interface GcpProjectIdAccessor { /** * Get a the GCP project id to used in Google Cloud IAM API calls. * + * @param credential the credential object to obtain the project id from. * @return the service account id to use. */ String getProjectId(GoogleCredential credential); diff --git a/spring-vault-core/src/main/java/org/springframework/vault/authentication/GcpServiceAccountIdProvider.java b/spring-vault-core/src/main/java/org/springframework/vault/authentication/GcpServiceAccountIdAccessor.java similarity index 90% rename from spring-vault-core/src/main/java/org/springframework/vault/authentication/GcpServiceAccountIdProvider.java rename to spring-vault-core/src/main/java/org/springframework/vault/authentication/GcpServiceAccountIdAccessor.java index 369228ce..2e5eaa55 100644 --- a/spring-vault-core/src/main/java/org/springframework/vault/authentication/GcpServiceAccountIdProvider.java +++ b/spring-vault-core/src/main/java/org/springframework/vault/authentication/GcpServiceAccountIdAccessor.java @@ -26,11 +26,12 @@ import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; * @see GcpIamAuthentication */ @FunctionalInterface -public interface GcpServiceAccountIdProvider { +public interface GcpServiceAccountIdAccessor { /** * Get a the service account id (email) to be placed in the signed JWT. * + * @param credential credential object to obtain the service account id from. * @return the service account id to use. */ String getServiceAccountId(GoogleCredential credential); diff --git a/spring-vault-core/src/test/java/org/springframework/vault/authentication/GcpIamAuthenticationOptionsBuilderUnitTests.java b/spring-vault-core/src/test/java/org/springframework/vault/authentication/GcpIamAuthenticationOptionsBuilderUnitTests.java index 855b1635..9aa931ed 100644 --- a/spring-vault-core/src/test/java/org/springframework/vault/authentication/GcpIamAuthenticationOptionsBuilderUnitTests.java +++ b/spring-vault-core/src/test/java/org/springframework/vault/authentication/GcpIamAuthenticationOptionsBuilderUnitTests.java @@ -1,96 +1,124 @@ +/* + * Copyright 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.springframework.vault.authentication; +import java.security.PrivateKey; + +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import org.junit.Test; + import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; -import java.security.PrivateKey; - -import org.junit.Test; - -import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; - /** - * Unit tests for {@link GcpIamAuthenticationOptions.GcpIamAuthenticationOptionsBuilder} + * Unit tests for {@link GcpIamAuthenticationOptions}. + * + * @author Magnus Jungsbluth */ public class GcpIamAuthenticationOptionsBuilderUnitTests { - private GoogleCredential createGoogleCredential() { - GoogleCredential credential = new GoogleCredential.Builder().setServiceAccountId("hello@world") - .setServiceAccountProjectId("foobar") - .setServiceAccountPrivateKey(mock(PrivateKey.class)) - .setServiceAccountPrivateKeyId("key-id").build(); - credential.setAccessToken("foobar"); - return credential; - } - @Test public void shouldDefaultToCredentialServiceAccountId() { - GoogleCredential credential = createGoogleCredential(); - GcpIamAuthenticationOptions options = GcpIamAuthenticationOptions.builder() - .credential(credential) - .role("foo") - .build(); - assertThat(options.getServiceAccountIdProvider().getServiceAccountId(credential)).isEqualTo("hello@world"); + GoogleCredential credential = createGoogleCredential(); + + GcpIamAuthenticationOptions options = GcpIamAuthenticationOptions.builder() + .credential(credential).role("foo").build(); + + assertThat(options.getServiceAccountIdAccessor().getServiceAccountId(credential)) + .isEqualTo("hello@world"); } @Test public void shouldAllowServiceAccountIdOverride() { - GoogleCredential credential = createGoogleCredential(); + + GoogleCredential credential = createGoogleCredential(); + GcpIamAuthenticationOptions options = GcpIamAuthenticationOptions.builder() - .credential(credential) - .serviceAccountId("override@foo.com") - .role("foo") + .credential(credential).serviceAccountId("override@foo.com").role("foo") .build(); - assertThat(options.getServiceAccountIdProvider().getServiceAccountId(credential)).isEqualTo("override@foo.com"); + assertThat(options.getServiceAccountIdAccessor().getServiceAccountId(credential)) + .isEqualTo("override@foo.com"); } - @Test - public void shouldAllowServiceAccountIdProviderOverride() { - GoogleCredential credential = createGoogleCredential(); - GcpIamAuthenticationOptions options = GcpIamAuthenticationOptions.builder() - .credential(credential) - .serviceAccountIdProvider((GoogleCredential googleCredential) -> "override@foo.com") - .role("foo") - .build(); + @Test + public void shouldAllowServiceAccountIdProviderOverride() { - assertThat(options.getServiceAccountIdProvider().getServiceAccountId(credential)).isEqualTo("override@foo.com"); - } + GoogleCredential credential = createGoogleCredential(); - @Test - public void shouldDefaultToCredentialProjectId() { - GoogleCredential credential = createGoogleCredential(); - GcpIamAuthenticationOptions options = GcpIamAuthenticationOptions.builder() - .credential(credential) - .role("foo") - .build(); + GcpIamAuthenticationOptions options = GcpIamAuthenticationOptions + .builder() + .credential(credential) + .serviceAccountIdAccessor( + (GoogleCredential googleCredential) -> "override@foo.com") + .role("foo").build(); - assertThat(options.getProjectIdProvider().getProjectId(credential)).isEqualTo("foobar"); - } + assertThat(options.getServiceAccountIdAccessor().getServiceAccountId(credential)) + .isEqualTo("override@foo.com"); + } - @Test - public void shouldAllowProjectIdOverride() { - GoogleCredential credential = createGoogleCredential(); - GcpIamAuthenticationOptions options = GcpIamAuthenticationOptions.builder() - .credential(credential) - .projectId("my-project") - .role("foo") - .build(); + @Test + public void shouldDefaultToCredentialProjectId() { - assertThat(options.getProjectIdProvider().getProjectId(credential)).isEqualTo("my-project"); - } + GoogleCredential credential = createGoogleCredential(); - @Test - public void shouldAllowProjectIdProviderOverride() { - GoogleCredential credential = createGoogleCredential(); - GcpIamAuthenticationOptions options = GcpIamAuthenticationOptions.builder() - .credential(credential) - .projectIdProvider((GoogleCredential googleCredential) -> "my-project") - .role("foo") - .build(); + GcpIamAuthenticationOptions options = GcpIamAuthenticationOptions.builder() + .credential(credential).role("foo").build(); - assertThat(options.getProjectIdProvider().getProjectId(credential)).isEqualTo("my-project"); - } + assertThat(options.getProjectIdAccessor().getProjectId(credential)).isEqualTo( + "project-id"); + } + @Test + public void shouldAllowProjectIdOverride() { + + GoogleCredential credential = createGoogleCredential(); + + GcpIamAuthenticationOptions options = GcpIamAuthenticationOptions.builder() + .credential(credential).projectId("my-project").role("foo").build(); + + assertThat(options.getProjectIdAccessor().getProjectId(credential)).isEqualTo( + "my-project"); + } + + @Test + public void shouldAllowProjectIdProviderOverride() { + + GoogleCredential credential = createGoogleCredential(); + + GcpIamAuthenticationOptions options = GcpIamAuthenticationOptions.builder() + .credential(credential) + .projectIdAccessor((GoogleCredential googleCredential) -> "my-project") + .role("foo").build(); + + assertThat(options.getProjectIdAccessor().getProjectId(credential)).isEqualTo( + "my-project"); + } + + private static GoogleCredential createGoogleCredential() { + + GoogleCredential credential = new GoogleCredential.Builder() + .setServiceAccountId("hello@world") + .setServiceAccountProjectId("project-id") + .setServiceAccountPrivateKey(mock(PrivateKey.class)) + .setServiceAccountPrivateKeyId("key-id").build(); + + credential.setAccessToken("foobar"); + + return credential; + } }