36
36
import java .security .cert .X509Certificate ;
37
37
import java .time .Duration ;
38
38
import java .time .Instant ;
39
+ import java .util .Collection ;
39
40
import java .util .Collections ;
41
+ import javax .naming .NameNotFoundException ;
40
42
import javax .net .ssl .SSLHandshakeException ;
41
43
import org .junit .After ;
42
44
import org .junit .Before ;
@@ -71,7 +73,8 @@ public void create_throwsErrorForInvalidInstanceName() throws IOException {
71
73
.withIpTypes ("PRIMARY" )
72
74
.build ();
73
75
74
- Connector c = newConnector (config .getConnectorConfig (), DEFAULT_SERVER_PROXY_PORT );
76
+ Connector c =
77
+ newConnector (config .getConnectorConfig (), DEFAULT_SERVER_PROXY_PORT , null , null , false );
75
78
IllegalArgumentException ex =
76
79
assertThrows (IllegalArgumentException .class , () -> c .connect (config , TEST_MAX_REFRESH_MS ));
77
80
@@ -96,7 +99,7 @@ public void create_throwsErrorForInvalidTlsCommonNameMismatch()
96
99
97
100
int port = sslServer .start (PUBLIC_IP );
98
101
99
- Connector connector = newConnector (config .getConnectorConfig (), port );
102
+ Connector connector = newConnector (config .getConnectorConfig (), port , null , null , false );
100
103
SSLHandshakeException ex =
101
104
assertThrows (
102
105
SSLHandshakeException .class , () -> connector .connect (config , TEST_MAX_REFRESH_MS ));
@@ -124,30 +127,25 @@ public void create_successfulPrivateConnection() throws IOException, Interrupted
124
127
125
128
int port = sslServer .start (PRIVATE_IP );
126
129
127
- Connector connector = newConnector (config .getConnectorConfig (), port );
130
+ Connector connector = newConnector (config .getConnectorConfig (), port , null , null , false );
128
131
129
132
Socket socket = connector .connect (config , TEST_MAX_REFRESH_MS );
130
133
131
134
assertThat (readLine (socket )).isEqualTo (SERVER_MESSAGE );
132
135
}
133
136
134
137
@ Test
135
- public void create_successfulPublicConnectionWithDomainName ()
136
- throws IOException , InterruptedException {
138
+ public void create_successfulPublicConnection () throws IOException , InterruptedException {
137
139
FakeSslServer sslServer = new FakeSslServer ();
138
140
ConnectionConfig config =
139
141
new ConnectionConfig .Builder ()
140
- .withDomainName ( "db.example.com " )
142
+ .withCloudSqlInstance ( "myProject:myRegion:myInstance " )
141
143
.withIpTypes ("PRIMARY" )
142
- .withConnectorConfig (
143
- new ConnectorConfig .Builder ()
144
- .withInstanceNameResolver ((domainName ) -> "myProject:myRegion:myInstance" )
145
- .build ())
146
144
.build ();
147
145
148
146
int port = sslServer .start (PUBLIC_IP );
149
147
150
- Connector connector = newConnector (config .getConnectorConfig (), port );
148
+ Connector connector = newConnector (config .getConnectorConfig (), port , null , null , false );
151
149
152
150
Socket socket = connector .connect (config , TEST_MAX_REFRESH_MS );
153
151
@@ -167,7 +165,7 @@ public void create_successfulPrivateConnection_UsesInstanceName_DomainNameIgnore
167
165
168
166
int port = sslServer .start (PRIVATE_IP );
169
167
170
- Connector connector = newConnector (config .getConnectorConfig (), port );
168
+ Connector connector = newConnector (config .getConnectorConfig (), port , null , null , false );
171
169
172
170
Socket socket = connector .connect (config , TEST_MAX_REFRESH_MS );
173
171
@@ -187,17 +185,16 @@ public void create_successfulPrivateConnection_UsesInstanceName_EmptyDomainNameI
187
185
188
186
int port = sslServer .start (PRIVATE_IP );
189
187
190
- Connector connector = newConnector (config .getConnectorConfig (), port );
188
+ Connector connector = newConnector (config .getConnectorConfig (), port , null , null , false );
191
189
192
190
Socket socket = connector .connect (config , TEST_MAX_REFRESH_MS );
193
191
194
192
assertThat (readLine (socket )).isEqualTo (SERVER_MESSAGE );
195
193
}
196
194
197
195
@ Test
198
- public void create_throwsErrorForDomainNameWithNoResolver ()
196
+ public void create_successfulPublicConnectionWithDomainName ()
199
197
throws IOException , InterruptedException {
200
- // The server TLS certificate matches myProject:myRegion:myInstance
201
198
FakeSslServer sslServer = new FakeSslServer ();
202
199
ConnectionConfig config =
203
200
new ConnectionConfig .Builder ()
@@ -207,30 +204,81 @@ public void create_throwsErrorForDomainNameWithNoResolver()
207
204
208
205
int port = sslServer .start (PUBLIC_IP );
209
206
210
- Connector connector = newConnector (config .getConnectorConfig (), port );
211
- IllegalStateException ex =
212
- assertThrows (
213
- IllegalStateException .class , () -> connector .connect (config , TEST_MAX_REFRESH_MS ));
207
+ Connector connector =
208
+ newConnector (
209
+ config .getConnectorConfig (),
210
+ port ,
211
+ "db.example.com" ,
212
+ "myProject:myRegion:myInstance" ,
213
+ false );
214
+
215
+ Socket socket = connector .connect (config , TEST_MAX_REFRESH_MS );
214
216
215
- assertThat (ex ). hasMessageThat (). contains ( "ConnectorConfig.resolver is not set" );
217
+ assertThat (readLine ( socket )). isEqualTo ( SERVER_MESSAGE );
216
218
}
217
219
218
220
@ Test
219
- public void create_successfulPublicConnection () throws IOException , InterruptedException {
221
+ public void create_throwsErrorForUnresolvedDomainName () throws IOException {
222
+ ConnectionConfig config =
223
+ new ConnectionConfig .Builder ()
224
+ .withDomainName ("baddomain.example.com" )
225
+ .withIpTypes ("PRIMARY" )
226
+ .build ();
227
+ Connector c =
228
+ newConnector (
229
+ config .getConnectorConfig (),
230
+ DEFAULT_SERVER_PROXY_PORT ,
231
+ "baddomain.example.com" ,
232
+ "invalid-name" ,
233
+ false );
234
+ RuntimeException ex =
235
+ assertThrows (RuntimeException .class , () -> c .connect (config , TEST_MAX_REFRESH_MS ));
236
+
237
+ assertThat (ex )
238
+ .hasMessageThat ()
239
+ .contains ("Cloud SQL connection name is invalid: \" baddomain.example.com\" " );
240
+ }
241
+
242
+ @ Test
243
+ public void create_throwsErrorForDomainNameBadTargetValue () throws IOException {
244
+ ConnectionConfig config =
245
+ new ConnectionConfig .Builder ()
246
+ .withDomainName ("badvalue.example.com" )
247
+ .withIpTypes ("PRIMARY" )
248
+ .build ();
249
+ Connector c =
250
+ newConnector (config .getConnectorConfig (), DEFAULT_SERVER_PROXY_PORT , null , null , false );
251
+ RuntimeException ex =
252
+ assertThrows (RuntimeException .class , () -> c .connect (config , TEST_MAX_REFRESH_MS ));
253
+
254
+ assertThat (ex )
255
+ .hasMessageThat ()
256
+ .contains ("Cloud SQL connection name is invalid: \" badvalue.example.com\" " );
257
+ }
258
+
259
+ @ Test
260
+ public void create_throwsErrorForDomainNameDoesntMatchServerCert () throws Exception {
220
261
FakeSslServer sslServer = new FakeSslServer ();
221
262
ConnectionConfig config =
222
263
new ConnectionConfig .Builder ()
223
- .withCloudSqlInstance ( "myProject:myRegion:myInstance " )
264
+ .withDomainName ( "not-in-san.example.com " )
224
265
.withIpTypes ("PRIMARY" )
225
266
.build ();
226
267
227
268
int port = sslServer .start (PUBLIC_IP );
228
269
229
- Connector connector = newConnector (config .getConnectorConfig (), port );
270
+ Connector c =
271
+ newConnector (
272
+ config .getConnectorConfig (),
273
+ port ,
274
+ "db.example.com" ,
275
+ "myProject:myRegion:myInstance" ,
276
+ true );
230
277
231
- Socket socket = connector .connect (config , TEST_MAX_REFRESH_MS );
278
+ SSLHandshakeException ex =
279
+ assertThrows (SSLHandshakeException .class , () -> c .connect (config , TEST_MAX_REFRESH_MS ));
232
280
233
- assertThat (readLine ( socket )). isEqualTo ( SERVER_MESSAGE );
281
+ assertThat (ex ). hasMessageThat (). contains ( "Server certificate does not contain expected name" );
234
282
}
235
283
236
284
@ Test
@@ -259,7 +307,8 @@ public void create_successfulPublicCasConnection() throws IOException, Interrupt
259
307
clientKeyPair ,
260
308
10 ,
261
309
TEST_MAX_REFRESH_MS ,
262
- port );
310
+ port ,
311
+ null );
263
312
264
313
Socket socket = connector .connect (config , TEST_MAX_REFRESH_MS );
265
314
@@ -293,7 +342,7 @@ public void create_successfulUnixSocketConnection() throws IOException, Interrup
293
342
294
343
unixSocketServer .start ();
295
344
296
- Connector connector = newConnector (config .getConnectorConfig (), 10000 );
345
+ Connector connector = newConnector (config .getConnectorConfig (), 10000 , null , null , false );
297
346
298
347
Socket socket = connector .connect (config , TEST_MAX_REFRESH_MS );
299
348
@@ -329,7 +378,8 @@ public void create_successfulDomainScopedConnection() throws IOException, Interr
329
378
clientKeyPair ,
330
379
10 ,
331
380
TEST_MAX_REFRESH_MS ,
332
- port );
381
+ port ,
382
+ new DnsInstanceConnectionNameResolver (new MockDnsResolver ()));
333
383
334
384
Socket socket = c .connect (config , TEST_MAX_REFRESH_MS );
335
385
@@ -343,7 +393,8 @@ public void create_throwsErrorForInvalidInstanceRegion() throws IOException {
343
393
.withCloudSqlInstance ("myProject:notMyRegion:myInstance" )
344
394
.withIpTypes ("PRIMARY" )
345
395
.build ();
346
- Connector c = newConnector (config .getConnectorConfig (), DEFAULT_SERVER_PROXY_PORT );
396
+ Connector c =
397
+ newConnector (config .getConnectorConfig (), DEFAULT_SERVER_PROXY_PORT , null , null , false );
347
398
RuntimeException ex =
348
399
assertThrows (RuntimeException .class , () -> c .connect (config , TEST_MAX_REFRESH_MS ));
349
400
@@ -367,7 +418,9 @@ public void create_failOnEmptyTargetPrincipal() throws IOException, InterruptedE
367
418
IllegalArgumentException ex =
368
419
assertThrows (
369
420
IllegalArgumentException .class ,
370
- () -> newConnector (config .getConnectorConfig (), DEFAULT_SERVER_PROXY_PORT ));
421
+ () ->
422
+ newConnector (
423
+ config .getConnectorConfig (), DEFAULT_SERVER_PROXY_PORT , null , null , false ));
371
424
372
425
assertThat (ex .getMessage ()).contains (ConnectionConfig .CLOUD_SQL_TARGET_PRINCIPAL_PROPERTY );
373
426
}
@@ -390,7 +443,8 @@ public void create_throwsException_adminApiNotEnabled() throws IOException {
390
443
clientKeyPair ,
391
444
10 ,
392
445
TEST_MAX_REFRESH_MS ,
393
- DEFAULT_SERVER_PROXY_PORT );
446
+ DEFAULT_SERVER_PROXY_PORT ,
447
+ new DnsInstanceConnectionNameResolver (new MockDnsResolver ()));
394
448
395
449
// Use a different project to get Api Not Enabled Error.
396
450
TerminalException ex =
@@ -422,7 +476,8 @@ public void create_throwsException_adminApiReturnsNotAuthorized() throws IOExcep
422
476
clientKeyPair ,
423
477
10 ,
424
478
TEST_MAX_REFRESH_MS ,
425
- DEFAULT_SERVER_PROXY_PORT );
479
+ DEFAULT_SERVER_PROXY_PORT ,
480
+ new DnsInstanceConnectionNameResolver (new MockDnsResolver ()));
426
481
427
482
// Use a different instance to simulate incorrect permissions.
428
483
TerminalException ex =
@@ -454,7 +509,8 @@ public void create_throwsException_badGateway() throws IOException {
454
509
clientKeyPair ,
455
510
10 ,
456
511
TEST_MAX_REFRESH_MS ,
457
- DEFAULT_SERVER_PROXY_PORT );
512
+ DEFAULT_SERVER_PROXY_PORT ,
513
+ new DnsInstanceConnectionNameResolver (new MockDnsResolver ()));
458
514
459
515
// If the gateway is down, then this is a temporary error, not a fatal error.
460
516
RuntimeException ex =
@@ -496,7 +552,8 @@ public void create_successfulPublicConnection_withIntermittentBadGatewayErrors()
496
552
clientKeyPair ,
497
553
10 ,
498
554
TEST_MAX_REFRESH_MS ,
499
- port );
555
+ port ,
556
+ new DnsInstanceConnectionNameResolver (new MockDnsResolver ()));
500
557
501
558
Socket socket = c .connect (config , TEST_MAX_REFRESH_MS );
502
559
@@ -529,7 +586,8 @@ public void supportsCustomCredentialFactoryWithIAM() throws InterruptedException
529
586
clientKeyPair ,
530
587
10 ,
531
588
TEST_MAX_REFRESH_MS ,
532
- port );
589
+ port ,
590
+ new DnsInstanceConnectionNameResolver (new MockDnsResolver ()));
533
591
534
592
Socket socket = c .connect (config , TEST_MAX_REFRESH_MS );
535
593
@@ -561,7 +619,8 @@ public void supportsCustomCredentialFactoryWithNoExpirationTime()
561
619
clientKeyPair ,
562
620
10 ,
563
621
TEST_MAX_REFRESH_MS ,
564
- port );
622
+ port ,
623
+ new DnsInstanceConnectionNameResolver (new MockDnsResolver ()));
565
624
566
625
Socket socket = c .connect (config , TEST_MAX_REFRESH_MS );
567
626
@@ -599,14 +658,18 @@ public HttpRequestInitializer create() {
599
658
clientKeyPair ,
600
659
10 ,
601
660
TEST_MAX_REFRESH_MS ,
602
- DEFAULT_SERVER_PROXY_PORT );
661
+ DEFAULT_SERVER_PROXY_PORT ,
662
+ new DnsInstanceConnectionNameResolver (new MockDnsResolver ()));
603
663
604
664
assertThrows (RuntimeException .class , () -> c .connect (config , TEST_MAX_REFRESH_MS ));
605
665
}
606
666
607
- private Connector newConnector (ConnectorConfig config , int port ) {
667
+ private Connector newConnector (
668
+ ConnectorConfig config , int port , String domainName , String instanceName , boolean cas ) {
608
669
ConnectionInfoRepositoryFactory factory =
609
- new StubConnectionInfoRepositoryFactory (fakeSuccessHttpTransport (Duration .ofSeconds (0 )));
670
+ new StubConnectionInfoRepositoryFactory (
671
+ fakeSuccessHttpTransport (
672
+ TestKeys .getServerCertPem (), Duration .ofSeconds (0 ), null , cas , false ));
610
673
Connector connector =
611
674
new Connector (
612
675
config ,
@@ -616,7 +679,8 @@ private Connector newConnector(ConnectorConfig config, int port) {
616
679
clientKeyPair ,
617
680
10 ,
618
681
TEST_MAX_REFRESH_MS ,
619
- port );
682
+ port ,
683
+ new DnsInstanceConnectionNameResolver (new MockDnsResolver (domainName , instanceName )));
620
684
return connector ;
621
685
}
622
686
@@ -625,4 +689,33 @@ private String readLine(Socket socket) throws IOException {
625
689
new BufferedReader (new InputStreamReader (socket .getInputStream (), UTF_8 ));
626
690
return bufferedReader .readLine ();
627
691
}
692
+
693
+ private static class MockDnsResolver implements DnsResolver {
694
+ private final String domainName ;
695
+ private final String instanceName ;
696
+
697
+ public MockDnsResolver () {
698
+ this .domainName = null ;
699
+ this .instanceName = null ;
700
+ }
701
+
702
+ public MockDnsResolver (String domainName , String instanceName ) {
703
+ this .domainName = domainName ;
704
+ this .instanceName = instanceName ;
705
+ }
706
+
707
+ @ Override
708
+ public Collection <String > resolveTxt (String domainName ) throws NameNotFoundException {
709
+ if (this .domainName != null && this .domainName .equals (domainName )) {
710
+ return Collections .singletonList (this .instanceName );
711
+ }
712
+ if ("not-in-san.example.com" .equals (domainName )) {
713
+ return Collections .singletonList (this .instanceName );
714
+ }
715
+ if ("badvalue.example.com" .equals (domainName )) {
716
+ return Collections .singletonList ("not-an-instance-name" );
717
+ }
718
+ throw new NameNotFoundException ("Not found: " + domainName );
719
+ }
720
+ }
628
721
}
0 commit comments