Skip to content

Commit

Permalink
feat(rest): introduces a new configuration option,insecure which cr…
Browse files Browse the repository at this point in the history
…eates a https client which is insecure by ignoring host verification and does not validate certificate chains. (#148)
  • Loading branch information
imosquera authored and Matt Duftler committed Jun 19, 2017
1 parent 7e127d4 commit a8cecd0
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.netflix.spinnaker.echo.config

import com.netflix.spinnaker.echo.events.RestClientFactory
import com.netflix.spinnaker.echo.rest.RestService
import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
Expand Down Expand Up @@ -45,12 +46,6 @@ import static retrofit.Endpoints.newFixedEndpoint
@SuppressWarnings('GStringExpressionWithinString')
class RestConfig {

@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
Client retrofitClient() {
new OkClient()
}

@Bean
LogLevel retrofitLogLevel(@Value('${retrofit.logLevel:BASIC}') String retrofitLogLevel) {
return LogLevel.valueOf(retrofitLogLevel)
Expand Down Expand Up @@ -93,7 +88,7 @@ class RestConfig {
}

@Bean
RestUrls restServices(RestProperties restProperties, Client retrofitClient, LogLevel retrofitLogLevel, RequestInterceptorAttacher requestInterceptorAttacher, HeadersFromFile headersFromFile) {
RestUrls restServices(RestProperties restProperties, RestClientFactory clientFactory, LogLevel retrofitLogLevel, RequestInterceptorAttacher requestInterceptorAttacher, HeadersFromFile headersFromFile) {

RestUrls restUrls = new RestUrls()

Expand All @@ -102,7 +97,7 @@ class RestConfig {
restProperties.endpoints.each { RestProperties.RestEndpointConfiguration endpoint ->
RestAdapter.Builder restAdapterBuilder = new RestAdapter.Builder()
.setEndpoint(newFixedEndpoint(endpoint.url as String))
.setClient(retrofitClient)
.setClient(clientFactory.getClient(endpoint.insecure))
.setLogLevel(retrofitLogLevel)
.setConverter(new JacksonConverter())

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class RestProperties {
Boolean wrap = false
@NotEmpty
String url
Boolean insecure = false
String username
String password
Map<String, String> headers
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright 2017 Armory, Inc.
*
* 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 com.netflix.spinnaker.echo.events

import com.squareup.okhttp.OkHttpClient
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Component
import retrofit.client.Client
import retrofit.client.OkClient

import javax.net.ssl.HostnameVerifier
import javax.net.ssl.SSLContext
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.TrustManager
import javax.net.ssl.X509TrustManager


interface OkHttpClientFactory {
OkHttpClient getInsecureClient()
}

@Component
class OkHttpClientFactoryImpl implements OkHttpClientFactory {

OkHttpClient getInsecureClient() {
// Create a trust manager that does not validate certificate chains
def trustAllCerts = [
checkClientTrusted: { chain, authType -> },
checkServerTrusted: { chain, authType -> },
getAcceptedIssuers: { null }
]

def nullHostnameVerifier = [
verify: { hostname, session -> true }
]

SSLContext sc = SSLContext.getInstance("SSL")
sc.init(null, [trustAllCerts as X509TrustManager] as TrustManager[], null)

SSLSocketFactory sslSocketFactory = sc.getSocketFactory()
OkHttpClient okHttpClient = new OkHttpClient()
okHttpClient.setSslSocketFactory(sslSocketFactory)
okHttpClient.setHostnameVerifier(nullHostnameVerifier as HostnameVerifier)
return okHttpClient
}
}

@Component
class RestClientFactory {

@Autowired
OkHttpClientFactory httpClientFactory

Client getClient(Boolean insecure) {
if (insecure) {
return new OkClient(httpClientFactory.getInsecureClient())
} else {
return new OkClient()
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.netflix.spinnaker.echo.config

import com.netflix.spinnaker.echo.events.RestClientFactory
import retrofit.RequestInterceptor
import retrofit.RestAdapter
import spock.lang.Specification
Expand All @@ -22,7 +23,7 @@ class RestConfigSpec extends Specification {

void configureRestServices(RestProperties.RestEndpointConfiguration endpoint, RestConfig.HeadersFromFile headersFromFile) {
RestProperties restProperties = new RestProperties(endpoints: [endpoint])
config.restServices(restProperties, config.retrofitClient(), config.retrofitLogLevel("BASIC"), attacher, headersFromFile)
config.restServices(restProperties, new RestClientFactory(), config.retrofitLogLevel("BASIC"), attacher, headersFromFile)
}

void "Generate basic auth header"() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.netflix.spinnaker.echo.events

import com.squareup.okhttp.OkHttpClient
import spock.lang.Specification
import spock.lang.Subject

import javax.net.ssl.HostnameVerifier

class OkHttpClientFactorySpec extends Specification {

@Subject
OkHttpClientFactory clientFactory = new OkHttpClientFactoryImpl()
OkHttpClient insecureClient

void 'insecure client does not verify hostname'() {

when:
insecureClient = clientFactory.getInsecureClient()

then:
insecureClient.getHostnameVerifier().verify("mockdomain", null)

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.netflix.spinnaker.echo.events

import com.squareup.okhttp.OkHttpClient
import retrofit.client.Client
import spock.lang.Specification
import spock.lang.Subject

class RestClientFactorySpec extends Specification{

@Subject
RestClientFactory clientFactory = new RestClientFactory()

Boolean insecure

OkHttpClientFactory httpClientFactory

void setup() {
httpClientFactory = Mock(OkHttpClientFactory)
clientFactory.httpClientFactory = httpClientFactory
}

void 'returns insecure client'() {
given:
insecure = true

when:
clientFactory.getClient(insecure)

then:
1 * httpClientFactory.getInsecureClient() >> new OkHttpClient()
}

void 'returns secure client'() {
given:
insecure = false

when:
clientFactory.getClient(insecure)

then:
0 * httpClientFactory.getInsecureClient() >> new OkHttpClient()
}
}

0 comments on commit a8cecd0

Please sign in to comment.