From 4ae1bee2c1fc3662583e9ba54191f840022b4413 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Fri, 27 May 2022 15:14:56 +0200 Subject: [PATCH] Upgrade to HttpCore 4.4.15, Jetty Reactive HttpClient 3.0.5, Google IAM Credential 2.2.0, Google Auth OAuth2 1.7.0, BouncyCastle 1.70 Closes gh-704 --- .../authentication/GcpIamAuthentication.java | 13 ++-- .../GcpIamCredentialsAuthentication.java | 20 +++---- .../vault/authentication/GoogleJsonUtil.java | 59 +++++++++++++++++++ .../GcpIamAuthenticationUnitTests.java | 5 +- spring-vault-dependencies/pom.xml | 10 ++-- 5 files changed, 80 insertions(+), 27 deletions(-) create mode 100644 spring-vault-core/src/main/java/org/springframework/vault/authentication/GoogleJsonUtil.java 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 60637087..172af6c7 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 @@ -26,7 +26,6 @@ import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; import com.google.api.client.http.HttpTransport; import com.google.api.client.http.javanet.NetHttpTransport; import com.google.api.client.json.JsonFactory; -import com.google.api.client.json.jackson2.JacksonFactory; import com.google.api.services.iam.v1.Iam; import com.google.api.services.iam.v1.Iam.Builder; import com.google.api.services.iam.v1.Iam.Projects.ServiceAccounts.SignJwt; @@ -34,7 +33,9 @@ import com.google.api.services.iam.v1.model.SignJwtRequest; import com.google.api.services.iam.v1.model.SignJwtResponse; import com.google.auth.oauth2.GoogleCredentials; +import org.springframework.beans.BeanUtils; import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; import org.springframework.vault.VaultException; import org.springframework.vault.support.VaultToken; import org.springframework.web.client.RestOperations; @@ -70,8 +71,6 @@ import org.springframework.web.client.RestOperations; @Deprecated public class GcpIamAuthentication extends GcpJwtAuthenticationSupport implements ClientAuthentication { - private static final JsonFactory JSON_FACTORY = new JacksonFactory(); - private static final String SCOPE = "https://www.googleapis.com/auth/iam"; private final GcpIamAuthenticationOptions options; @@ -85,7 +84,7 @@ public class GcpIamAuthentication extends GcpJwtAuthenticationSupport implements * {@link GcpIamAuthenticationOptions} and {@link RestOperations}. This constructor * initializes {@link GoogleApacheHttpTransport} for Google API usage. * @param options must not be {@literal null}. - * @param restOperations HTTP client for for Vault login, must not be {@literal null}. + * @param restOperations HTTP client for Vault login, must not be {@literal null}. */ public GcpIamAuthentication(GcpIamAuthenticationOptions options, RestOperations restOperations) { this(options, restOperations, new NetHttpTransport()); @@ -96,7 +95,7 @@ public class GcpIamAuthentication extends GcpJwtAuthenticationSupport implements * {@link GcpIamAuthenticationOptions}, {@link RestOperations} and * {@link HttpTransport}. * @param options must not be {@literal null}. - * @param restOperations HTTP client for for Vault login, must not be {@literal null}. + * @param restOperations HTTP client for Vault login, must not be {@literal null}. * @param httpTransport HTTP client for Google API use, must not be {@literal null}. */ public GcpIamAuthentication(GcpIamAuthenticationOptions options, RestOperations restOperations, @@ -127,12 +126,12 @@ public class GcpIamAuthentication extends GcpJwtAuthenticationSupport implements String serviceAccount = getServiceAccountId(); Map jwtPayload = getJwtPayload(this.options, serviceAccount); - Iam iam = new Builder(this.httpTransport, JSON_FACTORY, this.credential) + Iam iam = new Builder(this.httpTransport, GoogleJsonUtil.JSON_FACTORY, this.credential) .setApplicationName("Spring Vault/" + getClass().getName()).build(); try { - String payload = JSON_FACTORY.toString(jwtPayload); + String payload = GoogleJsonUtil.JSON_FACTORY.toString(jwtPayload); SignJwtRequest request = new SignJwtRequest(); request.setPayload(payload); diff --git a/spring-vault-core/src/main/java/org/springframework/vault/authentication/GcpIamCredentialsAuthentication.java b/spring-vault-core/src/main/java/org/springframework/vault/authentication/GcpIamCredentialsAuthentication.java index cdf5d49a..8c68cfe7 100644 --- a/spring-vault-core/src/main/java/org/springframework/vault/authentication/GcpIamCredentialsAuthentication.java +++ b/spring-vault-core/src/main/java/org/springframework/vault/authentication/GcpIamCredentialsAuthentication.java @@ -21,14 +21,7 @@ import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; -import org.springframework.util.Assert; -import org.springframework.vault.VaultException; -import org.springframework.vault.support.VaultToken; -import org.springframework.web.client.RestOperations; - import com.google.api.client.http.HttpTransport; -import com.google.api.client.json.JsonFactory; -import com.google.api.client.json.jackson2.JacksonFactory; import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider; import com.google.api.gax.rpc.TransportChannelProvider; import com.google.auth.oauth2.GoogleCredentials; @@ -38,6 +31,11 @@ import com.google.cloud.iam.credentials.v1.ServiceAccountName; import com.google.cloud.iam.credentials.v1.SignJwtResponse; import com.google.cloud.iam.credentials.v1.stub.IamCredentialsStubSettings; +import org.springframework.util.Assert; +import org.springframework.vault.VaultException; +import org.springframework.vault.support.VaultToken; +import org.springframework.web.client.RestOperations; + /** * Google Cloud IAM credentials login implementation using GCP IAM service accounts to * legitimate its authenticity via JSON Web Token using the IAM Credentials @@ -66,8 +64,6 @@ import com.google.cloud.iam.credentials.v1.stub.IamCredentialsStubSettings; */ public class GcpIamCredentialsAuthentication extends GcpJwtAuthenticationSupport implements ClientAuthentication { - private static final JsonFactory JSON_FACTORY = new JacksonFactory(); - private final GcpIamCredentialsAuthenticationOptions options; private final TransportChannelProvider transportChannelProvider; @@ -80,7 +76,7 @@ public class GcpIamCredentialsAuthentication extends GcpJwtAuthenticationSupport * constructor initializes {@link InstantiatingGrpcChannelProvider} for Google API * usage. * @param options must not be {@literal null}. - * @param restOperations HTTP client for for Vault login, must not be {@literal null}. + * @param restOperations HTTP client for Vault login, must not be {@literal null}. */ public GcpIamCredentialsAuthentication(GcpIamCredentialsAuthenticationOptions options, RestOperations restOperations) { @@ -92,7 +88,7 @@ public class GcpIamCredentialsAuthentication extends GcpJwtAuthenticationSupport * {@link GcpIamCredentialsAuthenticationOptions}, {@link RestOperations} and * {@link TransportChannelProvider}. * @param options must not be {@literal null}. - * @param restOperations HTTP client for for Vault login, must not be {@literal null}. + * @param restOperations HTTP client for Vault login, must not be {@literal null}. * @param transportChannelProvider Provider for transport channel Google API use, must * not be {@literal null}. */ @@ -128,7 +124,7 @@ public class GcpIamCredentialsAuthentication extends GcpJwtAuthenticationSupport .setCredentialsProvider(() -> this.credentials) .setTransportChannelProvider(this.transportChannelProvider).build(); try (IamCredentialsClient iamCredentialsClient = IamCredentialsClient.create(credentialsSettings)) { - String payload = JSON_FACTORY.toString(jwtPayload); + String payload = GoogleJsonUtil.JSON_FACTORY.toString(jwtPayload); ServiceAccountName serviceAccountName = ServiceAccountName.of("-", serviceAccount); SignJwtResponse response = iamCredentialsClient.signJwt(serviceAccountName, Collections.emptyList(), payload); diff --git a/spring-vault-core/src/main/java/org/springframework/vault/authentication/GoogleJsonUtil.java b/spring-vault-core/src/main/java/org/springframework/vault/authentication/GoogleJsonUtil.java new file mode 100644 index 00000000..ed229fb4 --- /dev/null +++ b/spring-vault-core/src/main/java/org/springframework/vault/authentication/GoogleJsonUtil.java @@ -0,0 +1,59 @@ +/* + * Copyright 2022 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 + * + * https://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.json.JsonFactory; + +import org.springframework.beans.BeanUtils; +import org.springframework.util.ClassUtils; + +/** + * Utility to provide JSON-functionality for Google integrations. + * + * @author Mark Paluch + * @since 2.4 + */ +class GoogleJsonUtil { + + static final JsonFactory JSON_FACTORY; + + static final String JACKSON = "com.google.api.client.json.jackson2.JacksonFactory"; + + static final String GSON = "com.google.api.client.json.gson.GsonFactory"; + + static { + + try { + + if (ClassUtils.isPresent(JACKSON, null)) { + JSON_FACTORY = instantiate(JACKSON); + } + else { + JSON_FACTORY = instantiate(GSON); + } + } + catch (ClassNotFoundException e) { + throw new IllegalStateException(String.format( + "No com.google.api.client.json.JsonFactory implementation available. Make sure to include either %s or %s on your classpath.", + JACKSON, GSON), e); + } + } + + private static JsonFactory instantiate(String name) throws ClassNotFoundException { + return (JsonFactory) BeanUtils.instantiateClass(ClassUtils.forName(name, null)); + } + +} diff --git a/spring-vault-core/src/test/java/org/springframework/vault/authentication/GcpIamAuthenticationUnitTests.java b/spring-vault-core/src/test/java/org/springframework/vault/authentication/GcpIamAuthenticationUnitTests.java index 97aee431..d8104c11 100644 --- a/spring-vault-core/src/test/java/org/springframework/vault/authentication/GcpIamAuthenticationUnitTests.java +++ b/spring-vault-core/src/test/java/org/springframework/vault/authentication/GcpIamAuthenticationUnitTests.java @@ -26,10 +26,9 @@ import java.time.Duration; import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; import com.google.api.client.googleapis.auth.oauth2.GoogleCredential.Builder; import com.google.api.client.googleapis.testing.auth.oauth2.MockGoogleCredential; -import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.client.json.gson.GsonFactory; import com.google.api.client.testing.http.MockHttpTransport; import com.google.api.client.testing.http.MockLowLevelHttpResponse; -import com.google.api.client.testing.json.MockJsonFactory; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -81,7 +80,7 @@ class GcpIamAuthenticationUnitTests { GoogleCredential credential = new MockGoogleCredential.Builder().setServiceAccountId("hello@world") .setServiceAccountProjectId("foobar").setServiceAccountPrivateKey(key.getPrivate()) - .setServiceAccountPrivateKeyId("key-id").setJsonFactory(new JacksonFactory()) + .setServiceAccountPrivateKeyId("key-id").setJsonFactory(new GsonFactory()) .setTransport(new MockHttpTransport.Builder().setLowLevelHttpResponse(createMockHttpResponse()).build()) .build(); credential.setAccessToken("foobar"); diff --git a/spring-vault-dependencies/pom.xml b/spring-vault-dependencies/pom.xml index 537d6a2a..14433151 100644 --- a/spring-vault-dependencies/pom.xml +++ b/spring-vault-dependencies/pom.xml @@ -58,16 +58,16 @@ 4.5.13 - 4.4.14 + 4.4.15 1.1.6 4.1.77.Final 3.14.9 2.13.3 1.11.975 - v1-rev20210226-1.31.0 - 1.2.2 - 0.22.2 - 1.68 + v1-rev20220511-1.32.1 + 2.2.0 + 1.7.0 + 1.70