diff --git a/clouddriver-cloudfoundry/src/main/java/com/netflix/spinnaker/clouddriver/cloudfoundry/client/CloudFoundryClientUtils.java b/clouddriver-cloudfoundry/src/main/java/com/netflix/spinnaker/clouddriver/cloudfoundry/client/CloudFoundryClientUtils.java index 1bd6da47172..0af1aa2be1c 100644 --- a/clouddriver-cloudfoundry/src/main/java/com/netflix/spinnaker/clouddriver/cloudfoundry/client/CloudFoundryClientUtils.java +++ b/clouddriver-cloudfoundry/src/main/java/com/netflix/spinnaker/clouddriver/cloudfoundry/client/CloudFoundryClientUtils.java @@ -43,6 +43,8 @@ static Optional safelyCall(RetrofitCallable r) throws CloudFoundryApiE return Optional.of(r.call()); } catch (RetrofitError retrofitError) { if (retrofitError.getResponse() != null && retrofitError.getResponse().getStatus() == 404) { + // FIXME: The oauthInterceptor could use a misconfigured endpoint and return 404 and + // this code would mask the issue. return Optional.empty(); } else { ErrorDescription errorDescription = diff --git a/clouddriver-cloudfoundry/src/main/java/com/netflix/spinnaker/clouddriver/cloudfoundry/client/HttpCloudFoundryClient.java b/clouddriver-cloudfoundry/src/main/java/com/netflix/spinnaker/clouddriver/cloudfoundry/client/HttpCloudFoundryClient.java index 95e8f6e1dcf..acf0a986487 100644 --- a/clouddriver-cloudfoundry/src/main/java/com/netflix/spinnaker/clouddriver/cloudfoundry/client/HttpCloudFoundryClient.java +++ b/clouddriver-cloudfoundry/src/main/java/com/netflix/spinnaker/clouddriver/cloudfoundry/client/HttpCloudFoundryClient.java @@ -41,6 +41,7 @@ import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; +import lombok.extern.slf4j.Slf4j; import okio.Buffer; import okio.BufferedSource; import retrofit.RequestInterceptor; @@ -48,6 +49,7 @@ import retrofit.client.OkClient; import retrofit.converter.JacksonConverter; +@Slf4j public class HttpCloudFoundryClient implements CloudFoundryClient { private final String apiHost; private final String user; @@ -149,31 +151,15 @@ public HttpCloudFoundryClient( String metricsUri, String apiHost, String user, - String password) { + String password, + boolean skipSslValidation) { this.apiHost = apiHost; this.user = user; this.password = password; - this.okHttpClient = new OkHttpClient(); - okHttpClient.interceptors().add(this::createRetryInterceptor); - - okHttpClient.setHostnameVerifier((s, sslSession) -> true); - - TrustManager[] trustAllCerts = - new TrustManager[] { - new X509TrustManager() { - @Override - public void checkClientTrusted(X509Certificate[] x509Certificates, String s) {} + this.okHttpClient = createHttpClient(skipSslValidation); - @Override - public void checkServerTrusted(X509Certificate[] x509Certificates, String s) {} - - @Override - public X509Certificate[] getAcceptedIssuers() { - return new X509Certificate[0]; - } - } - }; + okHttpClient.interceptors().add(this::createRetryInterceptor); ObjectMapper mapper = new ObjectMapper(); mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE); @@ -183,16 +169,6 @@ public X509Certificate[] getAcceptedIssuers() { this.jacksonConverter = new JacksonConverter(mapper); - SSLContext sslContext; - try { - sslContext = SSLContext.getInstance("SSL"); - sslContext.init(null, trustAllCerts, new SecureRandom()); - } catch (KeyManagementException | NoSuchAlgorithmException e) { - throw new RuntimeException(e); - } - - okHttpClient.setSslSocketFactory(sslContext.getSocketFactory()); - this.uaaService = new RestAdapter.Builder() .setEndpoint("https://" + apiHost.replaceAll("^api\\.", "login.")) @@ -218,6 +194,42 @@ public X509Certificate[] getAcceptedIssuers() { this.serviceKeys = new ServiceKeys(createService(ServiceKeyService.class), spaces); } + private static OkHttpClient createHttpClient(boolean skipSslValidation) { + OkHttpClient client = new OkHttpClient(); + + if (skipSslValidation) { + client.setHostnameVerifier((s, sslSession) -> true); + + TrustManager[] trustAllCerts = + new TrustManager[] { + new X509TrustManager() { + @Override + public void checkClientTrusted(X509Certificate[] x509Certificates, String s) {} + + @Override + public void checkServerTrusted(X509Certificate[] x509Certificates, String s) {} + + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } + } + }; + + SSLContext sslContext; + try { + sslContext = SSLContext.getInstance("SSL"); + sslContext.init(null, trustAllCerts, new SecureRandom()); + } catch (KeyManagementException | NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + + client.setSslSocketFactory(sslContext.getSocketFactory()); + } + + return client; + } + private void refreshTokenIfNecessary() { long currentExpiration = tokenExpirationNs.get(); long now = System.nanoTime(); @@ -228,7 +240,12 @@ private void refreshTokenIfNecessary() { } private void refreshToken() { - token = uaaService.passwordToken("password", user, password, "cf", ""); + try { + token = uaaService.passwordToken("password", user, password, "cf", ""); + } catch (Exception e) { + log.warn("Failed to obtain a token", e); + throw e; + } tokenExpirationNs.addAndGet(Duration.ofSeconds(token.getExpiresIn()).toNanos()); } diff --git a/clouddriver-cloudfoundry/src/main/java/com/netflix/spinnaker/clouddriver/cloudfoundry/config/CloudFoundryConfigurationProperties.java b/clouddriver-cloudfoundry/src/main/java/com/netflix/spinnaker/clouddriver/cloudfoundry/config/CloudFoundryConfigurationProperties.java index c10c3655821..8026b4cfc06 100644 --- a/clouddriver-cloudfoundry/src/main/java/com/netflix/spinnaker/clouddriver/cloudfoundry/config/CloudFoundryConfigurationProperties.java +++ b/clouddriver-cloudfoundry/src/main/java/com/netflix/spinnaker/clouddriver/cloudfoundry/config/CloudFoundryConfigurationProperties.java @@ -59,5 +59,6 @@ public static class ManagedAccount { private String user; private String password; private String environment; + private boolean skipSslValidation; } } diff --git a/clouddriver-cloudfoundry/src/main/java/com/netflix/spinnaker/clouddriver/cloudfoundry/security/CloudFoundryCredentials.java b/clouddriver-cloudfoundry/src/main/java/com/netflix/spinnaker/clouddriver/cloudfoundry/security/CloudFoundryCredentials.java index 3069625091c..aaeecda1e2d 100644 --- a/clouddriver-cloudfoundry/src/main/java/com/netflix/spinnaker/clouddriver/cloudfoundry/security/CloudFoundryCredentials.java +++ b/clouddriver-cloudfoundry/src/main/java/com/netflix/spinnaker/clouddriver/cloudfoundry/security/CloudFoundryCredentials.java @@ -16,21 +16,11 @@ package com.netflix.spinnaker.clouddriver.cloudfoundry.security; -import static java.util.Collections.emptyList; -import static java.util.Collections.singletonMap; -import static java.util.stream.Collectors.toList; - import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.netflix.spinnaker.clouddriver.cloudfoundry.client.CloudFoundryApiException; import com.netflix.spinnaker.clouddriver.cloudfoundry.client.CloudFoundryClient; import com.netflix.spinnaker.clouddriver.cloudfoundry.client.HttpCloudFoundryClient; import com.netflix.spinnaker.clouddriver.security.AccountCredentials; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; +import java.util.*; import javax.annotation.Nullable; import lombok.Getter; import lombok.extern.slf4j.Slf4j; @@ -54,6 +44,7 @@ public class CloudFoundryCredentials implements AccountCredentials requiredGroupMembership = Collections.emptyList(); + private final boolean skipSslValidation; private CloudFoundryClient credentials; @@ -64,7 +55,8 @@ public CloudFoundryCredentials( String apiHost, String userName, String password, - String environment) { + String environment, + boolean skipSslValidation) { this.name = name; this.appsManagerUri = appsManagerUri; this.metricsUri = metricsUri; @@ -72,12 +64,14 @@ public CloudFoundryCredentials( this.userName = userName; this.password = password; this.environment = Optional.ofNullable(environment).orElse("dev"); + this.skipSslValidation = skipSslValidation; } public CloudFoundryClient getCredentials() { if (this.credentials == null) { this.credentials = - new HttpCloudFoundryClient(name, appsManagerUri, metricsUri, apiHost, userName, password); + new HttpCloudFoundryClient( + name, appsManagerUri, metricsUri, apiHost, userName, password, skipSslValidation); } return credentials; } @@ -86,17 +80,6 @@ public CloudFoundryClient getClient() { return getCredentials(); } - public Collection> getRegions() { - try { - return getCredentials().getSpaces().all().stream() - .map(space -> singletonMap("name", space.getRegion())) - .collect(toList()); - } catch (CloudFoundryApiException e) { - log.warn("Unable to determine regions for Cloud Foundry account " + name, e); - return emptyList(); - } - } - @Override public boolean equals(Object o) { if (this == o) return true; @@ -109,11 +92,13 @@ public boolean equals(Object o) { && Objects.equals(metricsUri, that.metricsUri) && Objects.equals(userName, that.userName) && Objects.equals(password, that.password) - && Objects.equals(environment, that.environment); + && Objects.equals(environment, that.environment) + && Objects.equals(skipSslValidation, that.skipSslValidation); } @Override public int hashCode() { - return Objects.hash(name, appsManagerUri, metricsUri, userName, password, environment); + return Objects.hash( + name, appsManagerUri, metricsUri, userName, password, environment, skipSslValidation); } } diff --git a/clouddriver-cloudfoundry/src/main/java/com/netflix/spinnaker/clouddriver/cloudfoundry/security/CloudFoundryCredentialsSynchronizer.java b/clouddriver-cloudfoundry/src/main/java/com/netflix/spinnaker/clouddriver/cloudfoundry/security/CloudFoundryCredentialsSynchronizer.java index a460223c715..40f2f4abdb7 100644 --- a/clouddriver-cloudfoundry/src/main/java/com/netflix/spinnaker/clouddriver/cloudfoundry/security/CloudFoundryCredentialsSynchronizer.java +++ b/clouddriver-cloudfoundry/src/main/java/com/netflix/spinnaker/clouddriver/cloudfoundry/security/CloudFoundryCredentialsSynchronizer.java @@ -84,7 +84,8 @@ private List synchronizeRepository( managedAccount.getApi(), managedAccount.getUser(), managedAccount.getPassword(), - managedAccount.getEnvironment()); + managedAccount.getEnvironment(), + managedAccount.isSkipSslValidation()); AccountCredentials existingCredentials = accountCredentialsRepository.getOne(credentials.getName()); diff --git a/clouddriver-cloudfoundry/src/test/java/com/netflix/spinnaker/clouddriver/cloudfoundry/client/ApplicationsTest.java b/clouddriver-cloudfoundry/src/test/java/com/netflix/spinnaker/clouddriver/cloudfoundry/client/ApplicationsTest.java index ea7b75c7f57..40e7b4507b2 100644 --- a/clouddriver-cloudfoundry/src/test/java/com/netflix/spinnaker/clouddriver/cloudfoundry/client/ApplicationsTest.java +++ b/clouddriver-cloudfoundry/src/test/java/com/netflix/spinnaker/clouddriver/cloudfoundry/client/ApplicationsTest.java @@ -64,7 +64,8 @@ void errorHandling() { "some-metrics-uri", "api.run.pivotal.io", "baduser", - "badpassword"); + "badpassword", + false); assertThatThrownBy(() -> client.getApplications().all()) .isInstanceOf(CloudFoundryApiException.class); diff --git a/clouddriver-cloudfoundry/src/test/java/com/netflix/spinnaker/clouddriver/cloudfoundry/client/HttpCloudFoundryClientTest.java b/clouddriver-cloudfoundry/src/test/java/com/netflix/spinnaker/clouddriver/cloudfoundry/client/HttpCloudFoundryClientTest.java index 590d62550a8..d17a06b423f 100644 --- a/clouddriver-cloudfoundry/src/test/java/com/netflix/spinnaker/clouddriver/cloudfoundry/client/HttpCloudFoundryClientTest.java +++ b/clouddriver-cloudfoundry/src/test/java/com/netflix/spinnaker/clouddriver/cloudfoundry/client/HttpCloudFoundryClientTest.java @@ -53,7 +53,7 @@ void createRetryInterceptorShouldRetryOnInternalServerErrorsThenTimeOut() { HttpCloudFoundryClient cloudFoundryClient = new HttpCloudFoundryClient( - "account", "appsManUri", "metricsUri", "host", "user", "password"); + "account", "appsManUri", "metricsUri", "host", "user", "password", false); Response response = cloudFoundryClient.createRetryInterceptor(chain); try { @@ -82,7 +82,7 @@ void createRetryInterceptorShouldNotRefreshTokenOnBadCredentials() { HttpCloudFoundryClient cloudFoundryClient = new HttpCloudFoundryClient( - "account", "appsManUri", "metricsUri", "host", "user", "password"); + "account", "appsManUri", "metricsUri", "host", "user", "password", false); Response response = cloudFoundryClient.createRetryInterceptor(chain); try { @@ -111,7 +111,7 @@ void createRetryInterceptorShouldReturnOnEverythingElse() { HttpCloudFoundryClient cloudFoundryClient = new HttpCloudFoundryClient( - "account", "appsManUri", "metricsUri", "host", "user", "password"); + "account", "appsManUri", "metricsUri", "host", "user", "password", false); Response response = cloudFoundryClient.createRetryInterceptor(chain); try { diff --git a/clouddriver-cloudfoundry/src/test/java/com/netflix/spinnaker/clouddriver/cloudfoundry/deploy/converters/AbstractLoadBalancersAtomicOperationConverterTest.java b/clouddriver-cloudfoundry/src/test/java/com/netflix/spinnaker/clouddriver/cloudfoundry/deploy/converters/AbstractLoadBalancersAtomicOperationConverterTest.java index d501388c653..e6e0875d192 100644 --- a/clouddriver-cloudfoundry/src/test/java/com/netflix/spinnaker/clouddriver/cloudfoundry/deploy/converters/AbstractLoadBalancersAtomicOperationConverterTest.java +++ b/clouddriver-cloudfoundry/src/test/java/com/netflix/spinnaker/clouddriver/cloudfoundry/deploy/converters/AbstractLoadBalancersAtomicOperationConverterTest.java @@ -85,7 +85,7 @@ class AbstractLoadBalancersAtomicOperationConverterTest { } private final CloudFoundryCredentials cloudFoundryCredentials = - new CloudFoundryCredentials("test", "", "", "", "", "", "") { + new CloudFoundryCredentials("test", "", "", "", "", "", "", false) { public CloudFoundryClient getClient() { return cloudFoundryClient; } diff --git a/clouddriver-cloudfoundry/src/test/java/com/netflix/spinnaker/clouddriver/cloudfoundry/deploy/converters/CreateCloudFoundryServiceKeyAtomicOperationConverterTest.java b/clouddriver-cloudfoundry/src/test/java/com/netflix/spinnaker/clouddriver/cloudfoundry/deploy/converters/CreateCloudFoundryServiceKeyAtomicOperationConverterTest.java index 0df59d6a2f3..a3afa08707d 100644 --- a/clouddriver-cloudfoundry/src/test/java/com/netflix/spinnaker/clouddriver/cloudfoundry/deploy/converters/CreateCloudFoundryServiceKeyAtomicOperationConverterTest.java +++ b/clouddriver-cloudfoundry/src/test/java/com/netflix/spinnaker/clouddriver/cloudfoundry/deploy/converters/CreateCloudFoundryServiceKeyAtomicOperationConverterTest.java @@ -52,7 +52,7 @@ class CreateCloudFoundryServiceKeyAtomicOperationConverterTest { } private final CloudFoundryCredentials cloudFoundryCredentials = - new CloudFoundryCredentials("my-account", "", "", "", "", "", "") { + new CloudFoundryCredentials("my-account", "", "", "", "", "", "", false) { public CloudFoundryClient getClient() { return cloudFoundryClient; } diff --git a/clouddriver-cloudfoundry/src/test/java/com/netflix/spinnaker/clouddriver/cloudfoundry/deploy/converters/DeleteCloudFoundryServiceKeyAtomicOperationConverterTest.java b/clouddriver-cloudfoundry/src/test/java/com/netflix/spinnaker/clouddriver/cloudfoundry/deploy/converters/DeleteCloudFoundryServiceKeyAtomicOperationConverterTest.java index 0e2a378a0b5..af91e211ccd 100644 --- a/clouddriver-cloudfoundry/src/test/java/com/netflix/spinnaker/clouddriver/cloudfoundry/deploy/converters/DeleteCloudFoundryServiceKeyAtomicOperationConverterTest.java +++ b/clouddriver-cloudfoundry/src/test/java/com/netflix/spinnaker/clouddriver/cloudfoundry/deploy/converters/DeleteCloudFoundryServiceKeyAtomicOperationConverterTest.java @@ -57,7 +57,7 @@ class DeleteCloudFoundryServiceKeyAtomicOperationConverterTest { } private final CloudFoundryCredentials cloudFoundryCredentials = - new CloudFoundryCredentials("my-account", "", "", "", "", "", "") { + new CloudFoundryCredentials("my-account", "", "", "", "", "", "", false) { public CloudFoundryClient getClient() { return cloudFoundryClient; } diff --git a/clouddriver-cloudfoundry/src/test/java/com/netflix/spinnaker/clouddriver/cloudfoundry/deploy/converters/DeployCloudFoundryServerGroupAtomicOperationConverterTest.java b/clouddriver-cloudfoundry/src/test/java/com/netflix/spinnaker/clouddriver/cloudfoundry/deploy/converters/DeployCloudFoundryServerGroupAtomicOperationConverterTest.java index 1551d6b2e28..fe361e9d396 100644 --- a/clouddriver-cloudfoundry/src/test/java/com/netflix/spinnaker/clouddriver/cloudfoundry/deploy/converters/DeployCloudFoundryServerGroupAtomicOperationConverterTest.java +++ b/clouddriver-cloudfoundry/src/test/java/com/netflix/spinnaker/clouddriver/cloudfoundry/deploy/converters/DeployCloudFoundryServerGroupAtomicOperationConverterTest.java @@ -70,7 +70,7 @@ private static CloudFoundryCredentials createCredentials(String name) { .build())); } - return new CloudFoundryCredentials(name, "", "", "", "", "", "") { + return new CloudFoundryCredentials(name, "", "", "", "", "", "", false) { public CloudFoundryClient getClient() { return cloudFoundryClient; } diff --git a/clouddriver-cloudfoundry/src/test/java/com/netflix/spinnaker/clouddriver/cloudfoundry/deploy/converters/DeployCloudFoundryServiceAtomicOperationConverterTest.java b/clouddriver-cloudfoundry/src/test/java/com/netflix/spinnaker/clouddriver/cloudfoundry/deploy/converters/DeployCloudFoundryServiceAtomicOperationConverterTest.java index db7abf68b96..6491f3d76ff 100644 --- a/clouddriver-cloudfoundry/src/test/java/com/netflix/spinnaker/clouddriver/cloudfoundry/deploy/converters/DeployCloudFoundryServiceAtomicOperationConverterTest.java +++ b/clouddriver-cloudfoundry/src/test/java/com/netflix/spinnaker/clouddriver/cloudfoundry/deploy/converters/DeployCloudFoundryServiceAtomicOperationConverterTest.java @@ -72,7 +72,7 @@ class DeployCloudFoundryServiceAtomicOperationConverterTest { } private final CloudFoundryCredentials cloudFoundryCredentials = - new CloudFoundryCredentials("test", "", "", "", "", "", "") { + new CloudFoundryCredentials("test", "", "", "", "", "", "", false) { public CloudFoundryClient getClient() { return cloudFoundryClient; } diff --git a/clouddriver-cloudfoundry/src/test/java/com/netflix/spinnaker/clouddriver/cloudfoundry/deploy/converters/ScaleCloudFoundryServerGroupAtomicOperationConverterTest.java b/clouddriver-cloudfoundry/src/test/java/com/netflix/spinnaker/clouddriver/cloudfoundry/deploy/converters/ScaleCloudFoundryServerGroupAtomicOperationConverterTest.java index 00803484200..50bdc95c6a1 100644 --- a/clouddriver-cloudfoundry/src/test/java/com/netflix/spinnaker/clouddriver/cloudfoundry/deploy/converters/ScaleCloudFoundryServerGroupAtomicOperationConverterTest.java +++ b/clouddriver-cloudfoundry/src/test/java/com/netflix/spinnaker/clouddriver/cloudfoundry/deploy/converters/ScaleCloudFoundryServerGroupAtomicOperationConverterTest.java @@ -60,7 +60,7 @@ class ScaleCloudFoundryServerGroupAtomicOperationConverterTest { } private final CloudFoundryCredentials cloudFoundryCredentials = - new CloudFoundryCredentials("test", "", "", "", "", "", "") { + new CloudFoundryCredentials("test", "", "", "", "", "", "", false) { public CloudFoundryClient getClient() { return cloudFoundryClient; } diff --git a/clouddriver-cloudfoundry/src/test/java/com/netflix/spinnaker/clouddriver/cloudfoundry/security/CloudFoundryCredentialsSynchronizerTest.java b/clouddriver-cloudfoundry/src/test/java/com/netflix/spinnaker/clouddriver/cloudfoundry/security/CloudFoundryCredentialsSynchronizerTest.java index 9d36698a6f1..728d8672e99 100644 --- a/clouddriver-cloudfoundry/src/test/java/com/netflix/spinnaker/clouddriver/cloudfoundry/security/CloudFoundryCredentialsSynchronizerTest.java +++ b/clouddriver-cloudfoundry/src/test/java/com/netflix/spinnaker/clouddriver/cloudfoundry/security/CloudFoundryCredentialsSynchronizerTest.java @@ -115,7 +115,7 @@ private CloudFoundryConfigurationProperties.ManagedAccount createAccount(String private CloudFoundryCredentials createCredentials(String name) { return new CloudFoundryCredentials( - name, null, null, "api." + name, "user-" + name, "pwd-" + name, null); + name, null, null, "api." + name, "user-" + name, "pwd-" + name, null, false); } private void loadProviderFromRepository() {