@@ -1175,127 +1175,119 @@ func TestDialerChecksSubjectAlternativeNameAndFails(t *testing.T) {
11751175 }
11761176}
11771177
1178- func TestDialerRefreshesAfterRotateClientCA (t * testing.T ) {
1179- inst := mock .NewFakeCSQLInstanceWithSan (
1180- "my-project" , "my-region" , "my-instance" , []string {"db.example.com" },
1181- mock .WithDNS ("db.example.com" ),
1182- mock .WithServerCAMode ("GOOGLE_MANAGED_CAS_CA" ),
1183- )
1184-
1185- d := setupDialer (t , setupConfig {
1186- skipServer : true ,
1187- testInstance : inst ,
1188- reqs : []* mock.Request {
1189- mock .InstanceGetSuccess (inst , 2 ),
1190- mock .CreateEphemeralSuccess (inst , 2 ),
1178+ func TestDialerRefreshesAfterRotateCACerts (t * testing.T ) {
1179+ tcs := []struct {
1180+ desc string
1181+ rotateClientCA bool
1182+ wantErrorOnDial bool
1183+ wantErrorOnRead bool
1184+ useLazyRefresh bool
1185+ }{{
1186+ desc : "Rotating Client CA causes error on read, then refresh" ,
1187+ rotateClientCA : true ,
1188+ wantErrorOnRead : true ,
1189+ },
1190+ {
1191+ desc : "Rotating all CAs causes error on dial, then refresh" ,
1192+ wantErrorOnDial : true ,
1193+ wantErrorOnRead : false ,
11911194 },
1192- dialerOptions : []Option {
1193- WithTokenSource (mock.EmptyTokenSource {}),
1194- WithDebugLogger (& dialerTestLogger {t : t }),
1195- //WithLazyRefresh(),
1196- // Note: this succeeds with lazy refresh, but fails with lazy.
1197- // because dialer.ForceRefresh does not block connections while the
1198- // refresh is in progress.
1195+ {
1196+ desc : "Rotating Client CA with lazy refresh causes error on read" ,
1197+ rotateClientCA : true ,
1198+ wantErrorOnRead : true ,
1199+ useLazyRefresh : true ,
1200+ },
1201+ {
1202+ desc : "Rotating all CAs with lazy refresh causes error on dial" ,
1203+ wantErrorOnDial : true ,
1204+ useLazyRefresh : true ,
11991205 },
1200- })
1201- cancel1 := mock .StartServerProxy (t , inst )
1202- t .Log ("First attempt..." )
1203- testSuccessfulDial (
1204- context .Background (), t , d ,
1205- "my-project:my-region:my-instance" ,
1206- )
1207- t .Log ("First attempt OK. Resetting client cert." )
1208-
1209- // Close the server
1210- cancel1 ()
1211-
1212- mock .RotateClientCA (inst )
1213-
1214- // Start the server with new certificates
1215- cancel2 := mock .StartServerProxy (t , inst )
1216- defer cancel2 ()
1217-
1218- // Dial a second time. We expect no error on dial, but TLS error on read.
1219- t .Log ("Second attempt should fail..." )
1220- conn , err := d .Dial (context .Background (), "my-project:my-region:my-instance" )
1221- if err != nil {
1222- t .Fatal ("Should be no certificate error after, got " , err )
12231206 }
1207+ for _ , tc := range tcs {
1208+ t .Run (tc .desc , func (t * testing.T ) {
1209+ inst := mock .NewFakeCSQLInstanceWithSan (
1210+ "my-project" , "my-region" , "my-instance" , []string {"db.example.com" },
1211+ mock .WithDNS ("db.example.com" ),
1212+ mock .WithServerCAMode ("GOOGLE_MANAGED_CAS_CA" ),
1213+ )
12241214
1225- // Expect an error on read. This should trigger the dialer to refresh.
1226- _ , err = io .ReadAll (conn )
1227- if err != nil {
1228- t .Log ("Got error on read as expected." , err )
1229- } else {
1230- t .Fatal ("Want read error, got no error" )
1231- }
1232- t .Log ("Second attempt done" )
1215+ opts := []Option {
1216+ WithTokenSource (mock.EmptyTokenSource {}),
1217+ WithDebugLogger (& dialerTestLogger {t : t }),
1218+ }
1219+ if tc .useLazyRefresh {
1220+ opts = append (opts , WithLazyRefresh ())
1221+ }
12331222
1234- // Dial again. This should complete after the refresh.
1235- t .Log ("Third attempt..." )
1236- testSuccessfulDial (
1237- context .Background (), t , d ,
1238- "my-project:my-region:my-instance" ,
1239- )
1240- t .Log ("Third attempt OK." )
1241- }
1223+ d := setupDialer (t , setupConfig {
1224+ skipServer : true ,
1225+ testInstance : inst ,
1226+ reqs : []* mock.Request {
1227+ mock .InstanceGetSuccess (inst , 2 ),
1228+ mock .CreateEphemeralSuccess (inst , 2 ),
1229+ },
1230+ dialerOptions : opts ,
1231+ })
1232+ cancel1 := mock .StartServerProxy (t , inst )
1233+ t .Log ("First attempt..." )
1234+ testSuccessfulDial (
1235+ context .Background (), t , d ,
1236+ "my-project:my-region:my-instance" ,
1237+ )
1238+ t .Log ("First attempt OK. Resetting client cert." )
12421239
1243- func TestDialerRefreshesAfterRotateServerCA (t * testing.T ) {
1244- inst := mock .NewFakeCSQLInstanceWithSan (
1245- "my-project" , "my-region" , "my-instance" , []string {"db.example.com" },
1246- mock .WithDNS ("db.example.com" ),
1247- mock .WithServerCAMode ("GOOGLE_MANAGED_CAS_CA" ),
1248- )
1240+ // Close the server
1241+ cancel1 ()
12491242
1250- d := setupDialer (t , setupConfig {
1251- skipServer : true ,
1252- testInstance : inst ,
1253- reqs : []* mock.Request {
1254- mock .InstanceGetSuccess (inst , 2 ),
1255- mock .CreateEphemeralSuccess (inst , 2 ),
1256- },
1257- dialerOptions : []Option {
1258- WithTokenSource (mock.EmptyTokenSource {}),
1259- WithDebugLogger (& dialerTestLogger {t : t }),
1260- WithLazyRefresh (),
1261- // Note: this succeeds with lazy refresh, but fails with lazy.
1262- // because dialer.ForceRefresh does not block connections while the
1263- // refresh is in progress.
1264- },
1265- })
1266- cancel1 := mock .StartServerProxy (t , inst )
1267- t .Log ("First attempt..." )
1268- testSuccessfulDial (
1269- context .Background (), t , d ,
1270- "my-project:my-region:my-instance" ,
1271- )
1272- t .Log ("First attempt OK. Resetting client cert." )
1243+ if tc .rotateClientCA {
1244+ mock .RotateClientCA (inst )
1245+ } else {
1246+ mock .RotateCA (inst )
1247+ }
12731248
1274- // Close the server
1275- cancel1 ()
1249+ // Start the server with new certificates
1250+ cancel2 := mock .StartServerProxy (t , inst )
1251+ defer cancel2 ()
12761252
1277- mock .RotateCA (inst )
1253+ // Dial a second time.
1254+ t .Log ("Second attempt should fail..." )
1255+ conn , err := d .Dial (context .Background (), "my-project:my-region:my-instance" )
1256+ if err != nil {
1257+ if tc .wantErrorOnDial {
1258+ t .Logf ("got error on dial as expected: %v" , err )
1259+ } else {
1260+ t .Fatalf ("want no dial error, got: %v" , err )
1261+ }
1262+ } else if tc .wantErrorOnDial {
1263+ t .Fatal ("want dial error, got no error" )
1264+ }
12781265
1279- // Start the server with new certificates
1280- cancel2 := mock .StartServerProxy (t , inst )
1281- defer cancel2 ()
1266+ // If no error expected on dial, then attempt to read.
1267+ if ! tc .wantErrorOnDial {
1268+ _ , err = io .ReadAll (conn )
1269+ if err != nil {
1270+ if tc .wantErrorOnRead {
1271+ t .Logf ("got error on read as expected: %v" , err )
1272+ } else {
1273+ t .Fatalf ("want no read error, got: %v" , err )
1274+ }
1275+ } else if tc .wantErrorOnRead {
1276+ t .Fatal ("want read error, got no error" )
1277+ }
1278+ }
1279+ t .Log ("Second attempt done" )
12821280
1283- // Dial a second time. We expect no error on dial, but TLS error on read.
1284- t .Log ("Second attempt should fail..." )
1285- _ , err := d .Dial (context .Background (), "my-project:my-region:my-instance" )
1286- if err != nil {
1287- t .Log ("Got error on dial as expected." , err )
1288- } else {
1289- t .Fatal ("Want dial error, got no error" )
1281+ // Dial again. This should complete after the refresh.
1282+ t .Log ("Third attempt..." )
1283+ testSuccessfulDial (
1284+ context .Background (), t , d ,
1285+ "my-project:my-region:my-instance" ,
1286+ )
1287+ t .Log ("Third attempt OK." )
1288+ })
12901289 }
12911290
1292- // Dial again. This should occur after the refresh has completed.
1293- t .Log ("Third attempt..." )
1294- testSuccessfulDial (
1295- context .Background (), t , d ,
1296- "my-project:my-region:my-instance" ,
1297- )
1298- t .Log ("Third attempt OK." )
12991291}
13001292
13011293type dialerTestLogger struct {
0 commit comments