github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/swarmkit/manager/controlapi/cluster_test.go (about) 1 package controlapi 2 3 import ( 4 "context" 5 "fmt" 6 "testing" 7 "time" 8 9 "github.com/docker/swarmkit/api" 10 "github.com/docker/swarmkit/ca" 11 "github.com/docker/swarmkit/ca/testutils" 12 "github.com/docker/swarmkit/manager/state/store" 13 "github.com/docker/swarmkit/protobuf/ptypes" 14 grpcutils "github.com/docker/swarmkit/testutils" 15 gogotypes "github.com/gogo/protobuf/types" 16 "github.com/stretchr/testify/assert" 17 "github.com/stretchr/testify/require" 18 "google.golang.org/grpc/codes" 19 ) 20 21 func createClusterSpec(name string) *api.ClusterSpec { 22 return &api.ClusterSpec{ 23 Annotations: api.Annotations{ 24 Name: name, 25 }, 26 CAConfig: api.CAConfig{ 27 NodeCertExpiry: gogotypes.DurationProto(ca.DefaultNodeCertExpiration), 28 }, 29 } 30 } 31 32 func createClusterObj(id, name string, policy api.AcceptancePolicy, rootCA *ca.RootCA) *api.Cluster { 33 spec := createClusterSpec(name) 34 spec.AcceptancePolicy = policy 35 36 var key []byte 37 if s, err := rootCA.Signer(); err == nil { 38 key = s.Key 39 } 40 41 return &api.Cluster{ 42 ID: id, 43 Spec: *spec, 44 RootCA: api.RootCA{ 45 CACert: rootCA.Certs, 46 CAKey: key, 47 CACertHash: rootCA.Digest.String(), 48 JoinTokens: api.JoinTokens{ 49 Worker: ca.GenerateJoinToken(rootCA, false), 50 Manager: ca.GenerateJoinToken(rootCA, false), 51 }, 52 }, 53 } 54 } 55 56 func createCluster(t *testing.T, ts *testServer, id, name string, policy api.AcceptancePolicy, rootCA *ca.RootCA) *api.Cluster { 57 cluster := createClusterObj(id, name, policy, rootCA) 58 assert.NoError(t, ts.Store.Update(func(tx store.Tx) error { 59 return store.CreateCluster(tx, cluster) 60 })) 61 return cluster 62 } 63 64 func TestValidateClusterSpec(t *testing.T) { 65 type BadClusterSpec struct { 66 spec *api.ClusterSpec 67 c codes.Code 68 } 69 70 for _, bad := range []BadClusterSpec{ 71 { 72 spec: nil, 73 c: codes.InvalidArgument, 74 }, 75 { 76 spec: &api.ClusterSpec{ 77 Annotations: api.Annotations{ 78 Name: store.DefaultClusterName, 79 }, 80 CAConfig: api.CAConfig{ 81 NodeCertExpiry: gogotypes.DurationProto(29 * time.Minute), 82 }, 83 }, 84 c: codes.InvalidArgument, 85 }, 86 { 87 spec: &api.ClusterSpec{ 88 Annotations: api.Annotations{ 89 Name: store.DefaultClusterName, 90 }, 91 Dispatcher: api.DispatcherConfig{ 92 HeartbeatPeriod: gogotypes.DurationProto(-29 * time.Minute), 93 }, 94 }, 95 c: codes.InvalidArgument, 96 }, 97 { 98 spec: &api.ClusterSpec{ 99 Annotations: api.Annotations{ 100 Name: "", 101 }, 102 }, 103 c: codes.InvalidArgument, 104 }, 105 { 106 spec: &api.ClusterSpec{ 107 Annotations: api.Annotations{ 108 Name: "blah", 109 }, 110 }, 111 c: codes.InvalidArgument, 112 }, 113 } { 114 err := validateClusterSpec(bad.spec) 115 assert.Error(t, err) 116 assert.Equal(t, bad.c, grpcutils.ErrorCode(err)) 117 } 118 119 for _, good := range []*api.ClusterSpec{ 120 createClusterSpec(store.DefaultClusterName), 121 } { 122 err := validateClusterSpec(good) 123 assert.NoError(t, err) 124 } 125 126 } 127 128 func TestGetCluster(t *testing.T) { 129 ts := newTestServer(t) 130 defer ts.Stop() 131 _, err := ts.Client.GetCluster(context.Background(), &api.GetClusterRequest{}) 132 assert.Error(t, err) 133 assert.Equal(t, codes.InvalidArgument, grpcutils.ErrorCode(err)) 134 135 _, err = ts.Client.GetCluster(context.Background(), &api.GetClusterRequest{ClusterID: "invalid"}) 136 assert.Error(t, err) 137 assert.Equal(t, codes.NotFound, grpcutils.ErrorCode(err)) 138 139 cluster := createCluster(t, ts, "name", "name", api.AcceptancePolicy{}, ts.Server.securityConfig.RootCA()) 140 r, err := ts.Client.GetCluster(context.Background(), &api.GetClusterRequest{ClusterID: cluster.ID}) 141 assert.NoError(t, err) 142 cluster.Meta.Version = r.Cluster.Meta.Version 143 // Only public fields should be available 144 assert.Equal(t, cluster.ID, r.Cluster.ID) 145 assert.Equal(t, cluster.Meta, r.Cluster.Meta) 146 assert.Equal(t, cluster.Spec, r.Cluster.Spec) 147 assert.Equal(t, cluster.RootCA.CACert, r.Cluster.RootCA.CACert) 148 assert.Equal(t, cluster.RootCA.CACertHash, r.Cluster.RootCA.CACertHash) 149 // CAKey and network keys should be nil 150 assert.Nil(t, r.Cluster.RootCA.CAKey) 151 assert.Nil(t, r.Cluster.NetworkBootstrapKeys) 152 } 153 154 func TestGetClusterWithSecret(t *testing.T) { 155 ts := newTestServer(t) 156 defer ts.Stop() 157 _, err := ts.Client.GetCluster(context.Background(), &api.GetClusterRequest{}) 158 assert.Error(t, err) 159 assert.Equal(t, codes.InvalidArgument, grpcutils.ErrorCode(err)) 160 161 _, err = ts.Client.GetCluster(context.Background(), &api.GetClusterRequest{ClusterID: "invalid"}) 162 assert.Error(t, err) 163 assert.Equal(t, codes.NotFound, grpcutils.ErrorCode(err)) 164 165 policy := api.AcceptancePolicy{Policies: []*api.AcceptancePolicy_RoleAdmissionPolicy{{Secret: &api.AcceptancePolicy_RoleAdmissionPolicy_Secret{Data: []byte("secret")}}}} 166 cluster := createCluster(t, ts, "name", "name", policy, ts.Server.securityConfig.RootCA()) 167 r, err := ts.Client.GetCluster(context.Background(), &api.GetClusterRequest{ClusterID: cluster.ID}) 168 assert.NoError(t, err) 169 cluster.Meta.Version = r.Cluster.Meta.Version 170 assert.NotEqual(t, cluster, r.Cluster) 171 assert.NotContains(t, r.Cluster.String(), "secret") 172 assert.NotContains(t, r.Cluster.String(), "PRIVATE") 173 assert.NotNil(t, r.Cluster.Spec.AcceptancePolicy.Policies[0].Secret.Data) 174 } 175 176 func TestUpdateCluster(t *testing.T) { 177 ts := newTestServer(t) 178 defer ts.Stop() 179 cluster := createCluster(t, ts, "name", store.DefaultClusterName, api.AcceptancePolicy{}, ts.Server.securityConfig.RootCA()) 180 181 _, err := ts.Client.UpdateCluster(context.Background(), &api.UpdateClusterRequest{}) 182 assert.Error(t, err) 183 assert.Equal(t, codes.InvalidArgument, grpcutils.ErrorCode(err)) 184 185 _, err = ts.Client.UpdateCluster(context.Background(), &api.UpdateClusterRequest{ClusterID: "invalid", Spec: &cluster.Spec, ClusterVersion: &api.Version{}}) 186 assert.Error(t, err) 187 assert.Equal(t, codes.NotFound, grpcutils.ErrorCode(err)) 188 189 // No update options. 190 _, err = ts.Client.UpdateCluster(context.Background(), &api.UpdateClusterRequest{ClusterID: cluster.ID, Spec: &cluster.Spec}) 191 assert.Error(t, err) 192 assert.Equal(t, codes.InvalidArgument, grpcutils.ErrorCode(err)) 193 194 _, err = ts.Client.UpdateCluster(context.Background(), &api.UpdateClusterRequest{ClusterID: cluster.ID, Spec: &cluster.Spec, ClusterVersion: &cluster.Meta.Version}) 195 assert.NoError(t, err) 196 197 r, err := ts.Client.ListClusters(context.Background(), &api.ListClustersRequest{ 198 Filters: &api.ListClustersRequest_Filters{ 199 NamePrefixes: []string{store.DefaultClusterName}, 200 }, 201 }) 202 assert.NoError(t, err) 203 assert.Len(t, r.Clusters, 1) 204 assert.Equal(t, cluster.Spec.Annotations.Name, r.Clusters[0].Spec.Annotations.Name) 205 assert.Len(t, r.Clusters[0].Spec.AcceptancePolicy.Policies, 0) 206 207 r.Clusters[0].Spec.AcceptancePolicy = api.AcceptancePolicy{Policies: []*api.AcceptancePolicy_RoleAdmissionPolicy{{Secret: &api.AcceptancePolicy_RoleAdmissionPolicy_Secret{Alg: "bcrypt", Data: []byte("secret")}}}} 208 _, err = ts.Client.UpdateCluster(context.Background(), &api.UpdateClusterRequest{ 209 ClusterID: cluster.ID, 210 Spec: &r.Clusters[0].Spec, 211 ClusterVersion: &r.Clusters[0].Meta.Version, 212 }) 213 assert.NoError(t, err) 214 215 r, err = ts.Client.ListClusters(context.Background(), &api.ListClustersRequest{ 216 Filters: &api.ListClustersRequest_Filters{ 217 NamePrefixes: []string{store.DefaultClusterName}, 218 }, 219 }) 220 assert.NoError(t, err) 221 assert.Len(t, r.Clusters, 1) 222 assert.Equal(t, cluster.Spec.Annotations.Name, r.Clusters[0].Spec.Annotations.Name) 223 assert.Len(t, r.Clusters[0].Spec.AcceptancePolicy.Policies, 1) 224 225 r.Clusters[0].Spec.AcceptancePolicy = api.AcceptancePolicy{Policies: []*api.AcceptancePolicy_RoleAdmissionPolicy{{Secret: &api.AcceptancePolicy_RoleAdmissionPolicy_Secret{Alg: "bcrypt", Data: []byte("secret")}}}} 226 returnedCluster, err := ts.Client.UpdateCluster(context.Background(), &api.UpdateClusterRequest{ 227 ClusterID: cluster.ID, 228 Spec: &r.Clusters[0].Spec, 229 ClusterVersion: &r.Clusters[0].Meta.Version, 230 }) 231 assert.NoError(t, err) 232 assert.NotContains(t, returnedCluster.String(), "secret") 233 assert.NotContains(t, returnedCluster.String(), "PRIVATE") 234 assert.NotNil(t, returnedCluster.Cluster.Spec.AcceptancePolicy.Policies[0].Secret.Data) 235 236 // Versioning. 237 assert.NoError(t, err) 238 version := &returnedCluster.Cluster.Meta.Version 239 240 _, err = ts.Client.UpdateCluster(context.Background(), &api.UpdateClusterRequest{ 241 ClusterID: cluster.ID, 242 Spec: &r.Clusters[0].Spec, 243 ClusterVersion: version, 244 }) 245 assert.NoError(t, err) 246 247 // Perform an update with the "old" version. 248 _, err = ts.Client.UpdateCluster(context.Background(), &api.UpdateClusterRequest{ 249 ClusterID: cluster.ID, 250 Spec: &r.Clusters[0].Spec, 251 ClusterVersion: version, 252 }) 253 assert.Error(t, err) 254 } 255 256 func TestUpdateClusterRotateToken(t *testing.T) { 257 ts := newTestServer(t) 258 defer ts.Stop() 259 cluster := createCluster(t, ts, "name", store.DefaultClusterName, api.AcceptancePolicy{}, ts.Server.securityConfig.RootCA()) 260 261 r, err := ts.Client.ListClusters(context.Background(), &api.ListClustersRequest{ 262 Filters: &api.ListClustersRequest_Filters{ 263 NamePrefixes: []string{store.DefaultClusterName}, 264 }, 265 }) 266 267 assert.NoError(t, err) 268 assert.Len(t, r.Clusters, 1) 269 workerToken := r.Clusters[0].RootCA.JoinTokens.Worker 270 managerToken := r.Clusters[0].RootCA.JoinTokens.Manager 271 272 // Rotate worker token 273 _, err = ts.Client.UpdateCluster(context.Background(), &api.UpdateClusterRequest{ 274 ClusterID: cluster.ID, 275 Spec: &cluster.Spec, 276 ClusterVersion: &cluster.Meta.Version, 277 Rotation: api.KeyRotation{ 278 WorkerJoinToken: true, 279 }, 280 }) 281 assert.NoError(t, err) 282 283 r, err = ts.Client.ListClusters(context.Background(), &api.ListClustersRequest{ 284 Filters: &api.ListClustersRequest_Filters{ 285 NamePrefixes: []string{store.DefaultClusterName}, 286 }, 287 }) 288 assert.NoError(t, err) 289 assert.Len(t, r.Clusters, 1) 290 assert.NotEqual(t, workerToken, r.Clusters[0].RootCA.JoinTokens.Worker) 291 assert.Equal(t, managerToken, r.Clusters[0].RootCA.JoinTokens.Manager) 292 workerToken = r.Clusters[0].RootCA.JoinTokens.Worker 293 294 // Rotate manager token 295 _, err = ts.Client.UpdateCluster(context.Background(), &api.UpdateClusterRequest{ 296 ClusterID: cluster.ID, 297 Spec: &cluster.Spec, 298 ClusterVersion: &r.Clusters[0].Meta.Version, 299 Rotation: api.KeyRotation{ 300 ManagerJoinToken: true, 301 }, 302 }) 303 assert.NoError(t, err) 304 305 r, err = ts.Client.ListClusters(context.Background(), &api.ListClustersRequest{ 306 Filters: &api.ListClustersRequest_Filters{ 307 NamePrefixes: []string{store.DefaultClusterName}, 308 }, 309 }) 310 assert.NoError(t, err) 311 assert.Len(t, r.Clusters, 1) 312 assert.Equal(t, workerToken, r.Clusters[0].RootCA.JoinTokens.Worker) 313 assert.NotEqual(t, managerToken, r.Clusters[0].RootCA.JoinTokens.Manager) 314 managerToken = r.Clusters[0].RootCA.JoinTokens.Manager 315 316 // Rotate both tokens 317 _, err = ts.Client.UpdateCluster(context.Background(), &api.UpdateClusterRequest{ 318 ClusterID: cluster.ID, 319 Spec: &cluster.Spec, 320 ClusterVersion: &r.Clusters[0].Meta.Version, 321 Rotation: api.KeyRotation{ 322 WorkerJoinToken: true, 323 ManagerJoinToken: true, 324 }, 325 }) 326 assert.NoError(t, err) 327 328 r, err = ts.Client.ListClusters(context.Background(), &api.ListClustersRequest{ 329 Filters: &api.ListClustersRequest_Filters{ 330 NamePrefixes: []string{store.DefaultClusterName}, 331 }, 332 }) 333 assert.NoError(t, err) 334 assert.Len(t, r.Clusters, 1) 335 assert.NotEqual(t, workerToken, r.Clusters[0].RootCA.JoinTokens.Worker) 336 assert.NotEqual(t, managerToken, r.Clusters[0].RootCA.JoinTokens.Manager) 337 } 338 339 func TestUpdateClusterRotateUnlockKey(t *testing.T) { 340 ts := newTestServer(t) 341 defer ts.Stop() 342 // create a cluster with extra encryption keys, to make sure they exist 343 cluster := createClusterObj("id", store.DefaultClusterName, api.AcceptancePolicy{}, ts.Server.securityConfig.RootCA()) 344 expected := make(map[string]*api.EncryptionKey) 345 for i := 1; i <= 2; i++ { 346 value := fmt.Sprintf("fake%d", i) 347 expected[value] = &api.EncryptionKey{Subsystem: value, Key: []byte(value)} 348 cluster.UnlockKeys = append(cluster.UnlockKeys, expected[value]) 349 } 350 require.NoError(t, ts.Store.Update(func(tx store.Tx) error { 351 return store.CreateCluster(tx, cluster) 352 })) 353 354 // we have to get the key from the memory store, since the cluster returned by the API is redacted 355 getManagerKey := func() (managerKey *api.EncryptionKey) { 356 ts.Store.View(func(tx store.ReadTx) { 357 viewCluster := store.GetCluster(tx, cluster.ID) 358 // no matter whether there's a manager key or not, the other keys should not have been affected 359 foundKeys := make(map[string]*api.EncryptionKey) 360 for _, eKey := range viewCluster.UnlockKeys { 361 foundKeys[eKey.Subsystem] = eKey 362 } 363 for v, key := range expected { 364 foundKey, ok := foundKeys[v] 365 require.True(t, ok) 366 require.Equal(t, key, foundKey) 367 } 368 managerKey = foundKeys[ca.ManagerRole] 369 }) 370 return 371 } 372 373 validateListResult := func(expectedLocked bool) api.Version { 374 r, err := ts.Client.ListClusters(context.Background(), &api.ListClustersRequest{ 375 Filters: &api.ListClustersRequest_Filters{ 376 NamePrefixes: []string{store.DefaultClusterName}, 377 }, 378 }) 379 380 require.NoError(t, err) 381 require.Len(t, r.Clusters, 1) 382 require.Equal(t, expectedLocked, r.Clusters[0].Spec.EncryptionConfig.AutoLockManagers) 383 require.Nil(t, r.Clusters[0].UnlockKeys) // redacted 384 385 return r.Clusters[0].Meta.Version 386 } 387 388 // we start off with manager autolocking turned off 389 version := validateListResult(false) 390 require.Nil(t, getManagerKey()) 391 392 // Rotate unlock key without turning auto-lock on - key should still be nil 393 _, err := ts.Client.UpdateCluster(context.Background(), &api.UpdateClusterRequest{ 394 ClusterID: cluster.ID, 395 Spec: &cluster.Spec, 396 ClusterVersion: &version, 397 Rotation: api.KeyRotation{ 398 ManagerUnlockKey: true, 399 }, 400 }) 401 require.NoError(t, err) 402 version = validateListResult(false) 403 require.Nil(t, getManagerKey()) 404 405 // Enable auto-lock only, no rotation boolean 406 spec := cluster.Spec.Copy() 407 spec.EncryptionConfig.AutoLockManagers = true 408 _, err = ts.Client.UpdateCluster(context.Background(), &api.UpdateClusterRequest{ 409 ClusterID: cluster.ID, 410 Spec: spec, 411 ClusterVersion: &version, 412 }) 413 require.NoError(t, err) 414 version = validateListResult(true) 415 managerKey := getManagerKey() 416 require.NotNil(t, managerKey) 417 418 // Rotate the manager key 419 _, err = ts.Client.UpdateCluster(context.Background(), &api.UpdateClusterRequest{ 420 ClusterID: cluster.ID, 421 Spec: spec, 422 ClusterVersion: &version, 423 Rotation: api.KeyRotation{ 424 ManagerUnlockKey: true, 425 }, 426 }) 427 require.NoError(t, err) 428 version = validateListResult(true) 429 newManagerKey := getManagerKey() 430 require.NotNil(t, managerKey) 431 require.NotEqual(t, managerKey, newManagerKey) 432 managerKey = newManagerKey 433 434 // Just update the cluster without modifying unlock keys 435 _, err = ts.Client.UpdateCluster(context.Background(), &api.UpdateClusterRequest{ 436 ClusterID: cluster.ID, 437 Spec: spec, 438 ClusterVersion: &version, 439 }) 440 require.NoError(t, err) 441 version = validateListResult(true) 442 newManagerKey = getManagerKey() 443 require.Equal(t, managerKey, newManagerKey) 444 445 // Disable auto lock 446 _, err = ts.Client.UpdateCluster(context.Background(), &api.UpdateClusterRequest{ 447 ClusterID: cluster.ID, 448 Spec: &cluster.Spec, // set back to original spec 449 ClusterVersion: &version, 450 Rotation: api.KeyRotation{ 451 ManagerUnlockKey: true, // this will be ignored because we disable the auto-lock 452 }, 453 }) 454 require.NoError(t, err) 455 validateListResult(false) 456 require.Nil(t, getManagerKey()) 457 } 458 459 // root rotation tests have already been covered by ca_rotation_test.go - this test only makes sure that the function tested in those 460 // tests is actually called by `UpdateCluster`, and that the results of GetCluster and ListCluster have the CA keys 461 // and the spec key and cert redacted 462 func TestUpdateClusterRootRotation(t *testing.T) { 463 ts := newTestServer(t) 464 defer ts.Stop() 465 466 cluster := createCluster(t, ts, "id", store.DefaultClusterName, api.AcceptancePolicy{}, ts.Server.securityConfig.RootCA()) 467 response, err := ts.Client.GetCluster(context.Background(), &api.GetClusterRequest{ClusterID: cluster.ID}) 468 require.NoError(t, err) 469 require.NotNil(t, response.Cluster) 470 cluster = response.Cluster 471 472 updatedSpec := cluster.Spec.Copy() 473 updatedSpec.CAConfig.SigningCACert = testutils.ECDSA256SHA256Cert 474 updatedSpec.CAConfig.SigningCAKey = testutils.ECDSA256Key 475 updatedSpec.CAConfig.ForceRotate = 5 476 477 _, err = ts.Client.UpdateCluster(context.Background(), &api.UpdateClusterRequest{ 478 ClusterID: cluster.ID, 479 Spec: updatedSpec, 480 ClusterVersion: &cluster.Meta.Version, 481 }) 482 require.NoError(t, err) 483 484 checkCluster := func() *api.Cluster { 485 response, err = ts.Client.GetCluster(context.Background(), &api.GetClusterRequest{ClusterID: cluster.ID}) 486 require.NoError(t, err) 487 require.NotNil(t, response.Cluster) 488 489 listResponse, err := ts.Client.ListClusters(context.Background(), &api.ListClustersRequest{}) 490 require.NoError(t, err) 491 require.Len(t, listResponse.Clusters, 1) 492 493 require.Equal(t, response.Cluster, listResponse.Clusters[0]) 494 495 c := response.Cluster 496 require.NotNil(t, c.RootCA.RootRotation) 497 498 // check that all keys are redacted, and that the spec signing cert is also redacted (not because 499 // the cert is a secret, but because that makes it easier to get-and-update) 500 require.Len(t, c.RootCA.CAKey, 0) 501 require.Len(t, c.RootCA.RootRotation.CAKey, 0) 502 require.Len(t, c.Spec.CAConfig.SigningCAKey, 0) 503 require.Len(t, c.Spec.CAConfig.SigningCACert, 0) 504 505 return c 506 } 507 508 getUnredactedRootCA := func() (rootCA *api.RootCA) { 509 ts.Store.View(func(tx store.ReadTx) { 510 c := store.GetCluster(tx, cluster.ID) 511 require.NotNil(t, c) 512 rootCA = &c.RootCA 513 }) 514 return 515 } 516 517 cluster = checkCluster() 518 unredactedRootCA := getUnredactedRootCA() 519 520 // update something else, but make sure this doesn't the root CA rotation doesn't change 521 updatedSpec = cluster.Spec.Copy() 522 updatedSpec.CAConfig.NodeCertExpiry = gogotypes.DurationProto(time.Hour) 523 _, err = ts.Client.UpdateCluster(context.Background(), &api.UpdateClusterRequest{ 524 ClusterID: cluster.ID, 525 Spec: updatedSpec, 526 ClusterVersion: &cluster.Meta.Version, 527 }) 528 require.NoError(t, err) 529 530 updatedCluster := checkCluster() 531 require.NotEqual(t, cluster.Spec.CAConfig.NodeCertExpiry, updatedCluster.Spec.CAConfig.NodeCertExpiry) 532 updatedUnredactedRootCA := getUnredactedRootCA() 533 534 require.Equal(t, unredactedRootCA, updatedUnredactedRootCA) 535 } 536 537 func TestListClusters(t *testing.T) { 538 ts := newTestServer(t) 539 defer ts.Stop() 540 r, err := ts.Client.ListClusters(context.Background(), &api.ListClustersRequest{}) 541 assert.NoError(t, err) 542 assert.Empty(t, r.Clusters) 543 544 createCluster(t, ts, "id1", "name1", api.AcceptancePolicy{}, ts.Server.securityConfig.RootCA()) 545 r, err = ts.Client.ListClusters(context.Background(), &api.ListClustersRequest{}) 546 assert.NoError(t, err) 547 assert.Equal(t, 1, len(r.Clusters)) 548 549 createCluster(t, ts, "id2", "name2", api.AcceptancePolicy{}, ts.Server.securityConfig.RootCA()) 550 createCluster(t, ts, "id3", "name3", api.AcceptancePolicy{}, ts.Server.securityConfig.RootCA()) 551 r, err = ts.Client.ListClusters(context.Background(), &api.ListClustersRequest{}) 552 assert.NoError(t, err) 553 assert.Equal(t, 3, len(r.Clusters)) 554 } 555 556 func TestListClustersWithSecrets(t *testing.T) { 557 ts := newTestServer(t) 558 defer ts.Stop() 559 r, err := ts.Client.ListClusters(context.Background(), &api.ListClustersRequest{}) 560 assert.NoError(t, err) 561 assert.Empty(t, r.Clusters) 562 563 policy := api.AcceptancePolicy{Policies: []*api.AcceptancePolicy_RoleAdmissionPolicy{{Secret: &api.AcceptancePolicy_RoleAdmissionPolicy_Secret{Alg: "bcrypt", Data: []byte("secret")}}}} 564 565 createCluster(t, ts, "id1", "name1", policy, ts.Server.securityConfig.RootCA()) 566 r, err = ts.Client.ListClusters(context.Background(), &api.ListClustersRequest{}) 567 assert.NoError(t, err) 568 assert.Equal(t, 1, len(r.Clusters)) 569 570 createCluster(t, ts, "id2", "name2", policy, ts.Server.securityConfig.RootCA()) 571 createCluster(t, ts, "id3", "name3", policy, ts.Server.securityConfig.RootCA()) 572 r, err = ts.Client.ListClusters(context.Background(), &api.ListClustersRequest{}) 573 assert.NoError(t, err) 574 assert.Equal(t, 3, len(r.Clusters)) 575 for _, cluster := range r.Clusters { 576 assert.NotContains(t, cluster.String(), policy.Policies[0].Secret) 577 assert.NotContains(t, cluster.String(), "PRIVATE") 578 assert.NotNil(t, cluster.Spec.AcceptancePolicy.Policies[0].Secret.Data) 579 } 580 } 581 582 func TestExpireBlacklistedCerts(t *testing.T) { 583 now := time.Now() 584 585 longAgo := now.Add(-24 * time.Hour * 1000) 586 justBeforeGrace := now.Add(-expiredCertGrace - 5*time.Minute) 587 justAfterGrace := now.Add(-expiredCertGrace + 5*time.Minute) 588 future := now.Add(time.Hour) 589 590 cluster := &api.Cluster{ 591 BlacklistedCertificates: map[string]*api.BlacklistedCertificate{ 592 "longAgo": {Expiry: ptypes.MustTimestampProto(longAgo)}, 593 "justBeforeGrace": {Expiry: ptypes.MustTimestampProto(justBeforeGrace)}, 594 "justAfterGrace": {Expiry: ptypes.MustTimestampProto(justAfterGrace)}, 595 "future": {Expiry: ptypes.MustTimestampProto(future)}, 596 }, 597 } 598 599 expireBlacklistedCerts(cluster) 600 601 assert.Len(t, cluster.BlacklistedCertificates, 2) 602 603 _, hasJustAfterGrace := cluster.BlacklistedCertificates["justAfterGrace"] 604 assert.True(t, hasJustAfterGrace) 605 606 _, hasFuture := cluster.BlacklistedCertificates["future"] 607 assert.True(t, hasFuture) 608 }