17
17
18
18
package com .netflix .spinnaker .orca .webhook .config ;
19
19
20
+ import com .netflix .spinnaker .kork .crypto .X509Identity ;
21
+ import com .netflix .spinnaker .kork .crypto .X509IdentitySource ;
20
22
import com .netflix .spinnaker .okhttp .OkHttpClientConfigurationProperties ;
21
23
import com .netflix .spinnaker .orca .config .UserConfiguredUrlRestrictions ;
22
24
import com .netflix .spinnaker .orca .webhook .util .UnionX509TrustManager ;
25
27
import java .io .UnsupportedEncodingException ;
26
28
import java .net .URLEncoder ;
27
29
import java .nio .charset .Charset ;
30
+ import java .nio .file .Path ;
28
31
import java .security .KeyManagementException ;
29
32
import java .security .KeyStore ;
30
33
import java .security .KeyStoreException ;
31
34
import java .security .NoSuchAlgorithmException ;
32
35
import java .security .cert .CertificateException ;
36
+ import java .security .cert .X509Certificate ;
33
37
import java .util .ArrayList ;
34
- import java .util .List ;
35
38
import java .util .Map ;
36
39
import java .util .Optional ;
37
40
import javax .net .ssl .*;
51
54
import org .springframework .http .client .ClientHttpRequestFactory ;
52
55
import org .springframework .http .client .OkHttp3ClientHttpRequestFactory ;
53
56
import org .springframework .http .converter .AbstractHttpMessageConverter ;
54
- import org .springframework .http .converter .HttpMessageConverter ;
55
57
import org .springframework .http .converter .HttpMessageNotReadableException ;
56
58
import org .springframework .http .converter .HttpMessageNotWritableException ;
57
59
import org .springframework .http .converter .StringHttpMessageConverter ;
@@ -73,9 +75,9 @@ public WebhookConfiguration(WebhookProperties webhookProperties) {
73
75
@ Bean
74
76
@ ConditionalOnMissingBean (RestTemplate .class )
75
77
public RestTemplate restTemplate (ClientHttpRequestFactory webhookRequestFactory ) {
76
- RestTemplate restTemplate = new RestTemplate (webhookRequestFactory );
78
+ var restTemplate = new RestTemplate (webhookRequestFactory );
77
79
78
- List < HttpMessageConverter <?>> converters = restTemplate .getMessageConverters ();
80
+ var converters = restTemplate .getMessageConverters ();
79
81
converters .add (new ObjectStringHttpMessageConverter ());
80
82
converters .add (new MapToStringHttpMessageConverter ());
81
83
restTemplate .setMessageConverters (converters );
@@ -86,10 +88,11 @@ public RestTemplate restTemplate(ClientHttpRequestFactory webhookRequestFactory)
86
88
@ Bean
87
89
public ClientHttpRequestFactory webhookRequestFactory (
88
90
OkHttpClientConfigurationProperties okHttpClientConfigurationProperties ,
89
- UserConfiguredUrlRestrictions userConfiguredUrlRestrictions ) {
90
- X509TrustManager trustManager = webhookX509TrustManager ();
91
- SSLSocketFactory sslSocketFactory = getSSLSocketFactory (trustManager );
92
- OkHttpClient client =
91
+ UserConfiguredUrlRestrictions userConfiguredUrlRestrictions )
92
+ throws IOException {
93
+ var trustManager = webhookX509TrustManager ();
94
+ var sslSocketFactory = getSSLSocketFactory (trustManager );
95
+ var builder =
93
96
new OkHttpClient .Builder ()
94
97
.sslSocketFactory (sslSocketFactory , trustManager )
95
98
.addNetworkInterceptor (
@@ -105,9 +108,14 @@ public ClientHttpRequestFactory webhookRequestFactory(
105
108
}
106
109
107
110
return response ;
108
- })
109
- .build ();
110
- OkHttp3ClientHttpRequestFactory requestFactory = new OkHttp3ClientHttpRequestFactory (client );
111
+ });
112
+
113
+ if (webhookProperties .isInsecureSkipHostnameVerification ()) {
114
+ builder .hostnameVerifier ((hostname , session ) -> true );
115
+ }
116
+
117
+ var client = builder .build ();
118
+ var requestFactory = new OkHttp3ClientHttpRequestFactory (client );
111
119
requestFactory .setReadTimeout (
112
120
Math .toIntExact (okHttpClientConfigurationProperties .getReadTimeoutMs ()));
113
121
requestFactory .setConnectTimeout (
@@ -116,38 +124,83 @@ public ClientHttpRequestFactory webhookRequestFactory(
116
124
}
117
125
118
126
private X509TrustManager webhookX509TrustManager () {
119
- List < X509TrustManager > trustManagers = new ArrayList <>();
127
+ var trustManagers = new ArrayList <X509TrustManager >();
120
128
121
129
trustManagers .add (getTrustManager (null ));
122
- getCustomKeyStore ().ifPresent (keyStore -> trustManagers .add (getTrustManager (keyStore )));
130
+ getCustomTrustStore ().ifPresent (keyStore -> trustManagers .add (getTrustManager (keyStore )));
131
+
132
+ if (webhookProperties .isInsecureTrustSelfSigned ()) {
133
+ trustManagers .add (
134
+ new X509TrustManager () {
135
+ @ Override
136
+ public void checkClientTrusted (X509Certificate [] chain , String authType ) {}
137
+
138
+ @ Override
139
+ public void checkServerTrusted (X509Certificate [] chain , String authType ) {}
140
+
141
+ @ Override
142
+ public X509Certificate [] getAcceptedIssuers () {
143
+ return new X509Certificate [0 ];
144
+ }
145
+ });
146
+ }
123
147
124
148
return new UnionX509TrustManager (trustManagers );
125
149
}
126
150
127
- private SSLSocketFactory getSSLSocketFactory (X509TrustManager trustManager ) {
151
+ private SSLSocketFactory getSSLSocketFactory (X509TrustManager trustManager ) throws IOException {
128
152
try {
129
- SSLContext sslContext = SSLContext .getInstance ("TLS" );
130
- sslContext .init (null , new X509TrustManager [] {trustManager }, null );
131
- return sslContext .getSocketFactory ();
153
+ var identityOpt = getCustomIdentity ();
154
+ if (identityOpt .isPresent ()) {
155
+ var identity = identityOpt .get ();
156
+ return identity .createSSLContext (trustManager ).getSocketFactory ();
157
+ } else {
158
+ var sslContext = SSLContext .getInstance ("TLS" );
159
+ sslContext .init (null , new X509TrustManager [] {trustManager }, null );
160
+ return sslContext .getSocketFactory ();
161
+ }
132
162
} catch (KeyManagementException | NoSuchAlgorithmException e ) {
133
163
throw new RuntimeException (e );
134
164
}
135
165
}
136
166
137
167
private X509TrustManager getTrustManager (KeyStore keyStore ) {
138
168
try {
139
- TrustManagerFactory trustManagerFactory =
169
+ var trustManagerFactory =
140
170
TrustManagerFactory .getInstance (TrustManagerFactory .getDefaultAlgorithm ());
141
171
trustManagerFactory .init (keyStore );
142
- TrustManager [] trustManagers = trustManagerFactory .getTrustManagers ();
172
+ var trustManagers = trustManagerFactory .getTrustManagers ();
143
173
return (X509TrustManager ) trustManagers [0 ];
144
174
} catch (KeyStoreException | NoSuchAlgorithmException e ) {
145
175
throw new RuntimeException (e );
146
176
}
147
177
}
148
178
149
- private Optional <KeyStore > getCustomKeyStore () {
150
- WebhookProperties .TrustSettings trustSettings = webhookProperties .getTrust ();
179
+ private Optional <X509Identity > getCustomIdentity () throws IOException {
180
+ var identitySettings = webhookProperties .getIdentity ();
181
+ if (identitySettings == null
182
+ || !identitySettings .isEnabled ()
183
+ || StringUtils .isEmpty (identitySettings .getIdentityStore ())) {
184
+ return Optional .empty ();
185
+ }
186
+
187
+ var identity =
188
+ X509IdentitySource .fromKeyStore (
189
+ Path .of (identitySettings .getIdentityStore ()),
190
+ identitySettings .getIdentityStoreType (),
191
+ () -> {
192
+ var password = identitySettings .getIdentityStorePassword ();
193
+ return password == null ? new char [0 ] : password .toCharArray ();
194
+ },
195
+ () -> {
196
+ var password = identitySettings .getIdentityKeyPassword ();
197
+ return password == null ? new char [0 ] : password .toCharArray ();
198
+ });
199
+ return Optional .of (identity .load ());
200
+ }
201
+
202
+ private Optional <KeyStore > getCustomTrustStore () {
203
+ var trustSettings = webhookProperties .getTrust ();
151
204
if (trustSettings == null
152
205
|| !trustSettings .isEnabled ()
153
206
|| StringUtils .isEmpty (trustSettings .getTrustStore ())) {
@@ -156,7 +209,7 @@ private Optional<KeyStore> getCustomKeyStore() {
156
209
157
210
KeyStore keyStore ;
158
211
try {
159
- keyStore = KeyStore .getInstance (KeyStore . getDefaultType ());
212
+ keyStore = KeyStore .getInstance (trustSettings . getTrustStoreType ());
160
213
} catch (KeyStoreException e ) {
161
214
throw new RuntimeException (e );
162
215
}
0 commit comments