func TestNodeCertificateRenewalsDoNotRequireToken(t *testing.T) { tc := testutils.NewTestCA(t) defer tc.Stop() csr, _, err := ca.GenerateNewCSR() assert.NoError(t, err) role := api.NodeRoleManager issueRequest := &api.IssueNodeCertificateRequest{CSR: csr, Role: role} issueResponse, err := tc.NodeCAClients[2].IssueNodeCertificate(context.Background(), issueRequest) assert.NoError(t, err) assert.NotNil(t, issueResponse.NodeID) assert.Equal(t, api.NodeMembershipAccepted, issueResponse.NodeMembership) statusRequest := &api.NodeCertificateStatusRequest{NodeID: issueResponse.NodeID} statusResponse, err := tc.NodeCAClients[2].NodeCertificateStatus(context.Background(), statusRequest) assert.NoError(t, err) assert.Equal(t, api.IssuanceStateIssued, statusResponse.Status.State) assert.NotNil(t, statusResponse.Certificate.Certificate) assert.Equal(t, role, statusResponse.Certificate.Role) role = api.NodeRoleWorker issueRequest = &api.IssueNodeCertificateRequest{CSR: csr, Role: role} issueResponse, err = tc.NodeCAClients[1].IssueNodeCertificate(context.Background(), issueRequest) require.NoError(t, err) assert.NotNil(t, issueResponse.NodeID) assert.Equal(t, api.NodeMembershipAccepted, issueResponse.NodeMembership) statusRequest = &api.NodeCertificateStatusRequest{NodeID: issueResponse.NodeID} statusResponse, err = tc.NodeCAClients[2].NodeCertificateStatus(context.Background(), statusRequest) require.NoError(t, err) assert.Equal(t, api.IssuanceStateIssued, statusResponse.Status.State) assert.NotNil(t, statusResponse.Certificate.Certificate) assert.Equal(t, role, statusResponse.Certificate.Role) }
func TestNodeCertificateWithEmptyPolicies(t *testing.T) { policy := api.AcceptancePolicy{ Policies: []*api.AcceptancePolicy_RoleAdmissionPolicy{}, } tc := testutils.NewTestCA(t, policy) defer tc.Stop() csr, _, err := ca.GenerateAndWriteNewKey(tc.Paths.Node) assert.NoError(t, err) assert.NotNil(t, csr) role := api.NodeRoleWorker issueRequest := &api.IssueNodeCertificateRequest{CSR: csr, Role: role} issueResponse, err := tc.NodeCAClients[0].IssueNodeCertificate(context.Background(), issueRequest) require.NoError(t, err) assert.NotNil(t, issueResponse.NodeID) assert.Equal(t, api.NodeMembershipPending, issueResponse.NodeMembership) role = api.NodeRoleManager issueRequest = &api.IssueNodeCertificateRequest{CSR: csr, Role: role} issueResponse, err = tc.NodeCAClients[0].IssueNodeCertificate(context.Background(), issueRequest) require.NoError(t, err) assert.NotNil(t, issueResponse.NodeID) assert.Equal(t, api.NodeMembershipPending, issueResponse.NodeMembership) }
func TestIssueNodeCertificateAgentFromDifferentOrgRenewal(t *testing.T) { tc := testutils.NewTestCA(t, ca.DefaultAcceptancePolicy()) defer tc.Stop() csr, _, err := ca.GenerateAndWriteNewKey(tc.Paths.Node) assert.NoError(t, err) // Since we're using a client that has a different Organization, this request will be treated // as a new certificate request, not allowing auto-renewal role := api.NodeRoleManager issueRequest := &api.IssueNodeCertificateRequest{CSR: csr, Role: role} issueResponse, err := tc.NodeCAClients[3].IssueNodeCertificate(context.Background(), issueRequest) assert.NoError(t, err) assert.NotNil(t, issueResponse.NodeID) assert.Equal(t, api.NodeMembershipPending, issueResponse.NodeMembership) tc.MemoryStore.View(func(readTx store.ReadTx) { storeNodes, err := store.FindNodes(readTx, store.All) assert.NoError(t, err) assert.NotEmpty(t, storeNodes) found := false for _, node := range storeNodes { if node.ID == issueResponse.NodeID { found = true assert.Equal(t, api.IssuanceStatePending, node.Certificate.Status.State) } } assert.True(t, found) }) }
func TestDownloadRootCAWrongCAHash(t *testing.T) { tc := testutils.NewTestCA(t) defer tc.Stop() // Remove the CA cert os.RemoveAll(tc.Paths.RootCA.Cert) // invalid token for _, invalid := range []string{ "invalidtoken", // completely invalid "SWMTKN-1-3wkodtpeoipd1u1hi0ykdcdwhw16dk73ulqqtn14b3indz68rf-4myj5xihyto11dg1cn55w8p6", // mistyped } { _, err := ca.DownloadRootCA(tc.Context, tc.Paths.RootCA, invalid, tc.ConnBroker) require.Error(t, err) require.Contains(t, err.Error(), "invalid join token") } // invalid hash token splitToken := strings.Split(tc.ManagerToken, "-") splitToken[2] = "1kxftv4ofnc6mt30lmgipg6ngf9luhwqopfk1tz6bdmnkubg0e" replacementToken := strings.Join(splitToken, "-") os.RemoveAll(tc.Paths.RootCA.Cert) _, err := ca.DownloadRootCA(tc.Context, tc.Paths.RootCA, replacementToken, tc.ConnBroker) require.Error(t, err) require.Contains(t, err.Error(), "remote CA does not match fingerprint.") }
func TestForceRenewTLSConfig(t *testing.T) { t.Parallel() tc := testutils.NewTestCA(t) defer tc.Stop() ctx, cancel := context.WithCancel(context.Background()) defer cancel() // Get a new managerConfig with a TLS cert that has 15 minutes to live nodeConfig, err := tc.WriteNewNodeConfig(ca.ManagerRole) assert.NoError(t, err) renew := make(chan struct{}, 1) updates := ca.RenewTLSConfig(ctx, nodeConfig, tc.Remotes, renew) renew <- struct{}{} select { case <-time.After(10 * time.Second): assert.Fail(t, "TestForceRenewTLSConfig timed-out") case certUpdate := <-updates: assert.NoError(t, certUpdate.Err) assert.NotNil(t, certUpdate) assert.Equal(t, certUpdate.Role, ca.ManagerRole) } }
func TestGetRemoteSignedCertificateWithPending(t *testing.T) { tc := testutils.NewTestCA(t) defer tc.Stop() // Create a new CSR to be signed csr, _, err := ca.GenerateAndWriteNewKey(tc.Paths.Node) assert.NoError(t, err) updates, cancel := state.Watch(tc.MemoryStore.WatchQueue(), state.EventCreateNode{}) defer cancel() completed := make(chan error) go func() { _, err := ca.GetRemoteSignedCertificate(context.Background(), csr, tc.WorkerToken, tc.RootCA.Pool, tc.Remotes, nil, nil) completed <- err }() event := <-updates node := event.(state.EventCreateNode).Node.Copy() // Directly update the status of the store err = tc.MemoryStore.Update(func(tx store.Tx) error { node.Certificate.Status.State = api.IssuanceStateIssued return store.UpdateNode(tx, node) }) assert.NoError(t, err) // Make sure GetRemoteSignedCertificate didn't return an error assert.NoError(t, <-completed) }
func TestForceRenewTLSConfig(t *testing.T) { tc := testutils.NewTestCA(t) defer tc.Stop() ctx, cancel := context.WithCancel(context.Background()) defer cancel() // Get a new managerConfig with a TLS cert that has 15 minutes to live nodeConfig, err := tc.WriteNewNodeConfig(ca.ManagerRole) assert.NoError(t, err) var success, timeout bool renew := make(chan struct{}, 1) updates := ca.RenewTLSConfig(ctx, nodeConfig, tc.TempDir, tc.Picker, renew) for { renew <- struct{}{} select { case <-time.After(2 * time.Second): timeout = true case certUpdate := <-updates: assert.NoError(t, certUpdate.Err) assert.NotNil(t, certUpdate) assert.Equal(t, certUpdate.Role, ca.ManagerRole) success = true } if timeout { assert.Fail(t, "TestForceRenewTLSConfig timed-out") break } if success { break } } }
func TestCreateSecurityConfigNoCerts(t *testing.T) { tc := testutils.NewTestCA(t) defer tc.Stop() // Remove only the node certificates form the directory, and attest that we get // new certificates that are locally signed os.RemoveAll(tc.Paths.Node.Cert) krw := ca.NewKeyReadWriter(tc.Paths.Node, nil, nil) nodeConfig, err := tc.RootCA.CreateSecurityConfig(tc.Context, krw, ca.CertificateRequestConfig{ Token: tc.WorkerToken, Remotes: tc.Remotes, }) assert.NoError(t, err) assert.NotNil(t, nodeConfig) assert.NotNil(t, nodeConfig.ClientTLSCreds) assert.NotNil(t, nodeConfig.ServerTLSCreds) assert.Equal(t, tc.RootCA, *nodeConfig.RootCA()) // Remove only the node certificates form the directory, get a new rootCA, and attest that we get // new certificates that are issued by the remote CA os.RemoveAll(tc.Paths.Node.Cert) rootCA, err := ca.GetLocalRootCA(tc.Paths.RootCA) assert.NoError(t, err) nodeConfig, err = rootCA.CreateSecurityConfig(tc.Context, krw, ca.CertificateRequestConfig{ Token: tc.WorkerToken, Remotes: tc.Remotes, }) assert.NoError(t, err) assert.NotNil(t, nodeConfig) assert.NotNil(t, nodeConfig.ClientTLSCreds) assert.NotNil(t, nodeConfig.ServerTLSCreds) assert.Equal(t, rootCA, *nodeConfig.RootCA()) }
func TestDownloadRootCASuccess(t *testing.T) { tc := testutils.NewTestCA(t) defer tc.Stop() // Remove the CA cert os.RemoveAll(tc.Paths.RootCA.Cert) rootCA, err := ca.DownloadRootCA(tc.Context, tc.Paths.RootCA, tc.WorkerToken, tc.Remotes) require.NoError(t, err) require.NotNil(t, rootCA.Pool) require.NotNil(t, rootCA.Cert) require.Nil(t, rootCA.Signer) require.False(t, rootCA.CanSign()) require.Equal(t, tc.RootCA.Cert, rootCA.Cert) // Remove the CA cert os.RemoveAll(tc.Paths.RootCA.Cert) // downloading without a join token also succeeds rootCA, err = ca.DownloadRootCA(tc.Context, tc.Paths.RootCA, "", tc.Remotes) require.NoError(t, err) require.NotNil(t, rootCA.Pool) require.NotNil(t, rootCA.Cert) require.Nil(t, rootCA.Signer) require.False(t, rootCA.CanSign()) require.Equal(t, tc.RootCA.Cert, rootCA.Cert) }
func TestRenewTLSConfigWithNoNode(t *testing.T) { t.Parallel() tc := testutils.NewTestCA(t) defer tc.Stop() ctx, cancel := context.WithCancel(context.Background()) defer cancel() // Get a new nodeConfig with a TLS cert that has the default Cert duration nodeConfig, err := tc.WriteNewNodeConfig(ca.ManagerRole) assert.NoError(t, err) // Create a new RootCA, and change the policy to issue 6 minute certificates. // Because of the default backdate of 5 minutes, this issues certificates // valid for 1 minute. newRootCA, err := ca.NewRootCA(tc.RootCA.Cert, tc.RootCA.Key, ca.DefaultNodeCertExpiration) assert.NoError(t, err) newRootCA.Signer.SetPolicy(&cfconfig.Signing{ Default: &cfconfig.SigningProfile{ Usage: []string{"signing", "key encipherment", "server auth", "client auth"}, Expiry: 6 * time.Minute, }, }) // Create a new CSR and overwrite the key on disk csr, key, err := ca.GenerateNewCSR() assert.NoError(t, err) // Issue a new certificate with the same details as the current config, but with 1 min expiration time c := nodeConfig.ClientTLSCreds signedCert, err := newRootCA.ParseValidateAndSignCSR(csr, c.NodeID(), c.Role(), c.Organization()) assert.NoError(t, err) assert.NotNil(t, signedCert) // Overwrite the certificate on disk with one that expires in 1 minute err = ioutils.AtomicWriteFile(tc.Paths.Node.Cert, signedCert, 0644) assert.NoError(t, err) err = ioutils.AtomicWriteFile(tc.Paths.Node.Key, key, 0600) assert.NoError(t, err) // Delete the node from the backend store err = tc.MemoryStore.Update(func(tx store.Tx) error { node := store.GetNode(tx, nodeConfig.ClientTLSCreds.NodeID()) assert.NotNil(t, node) return store.DeleteNode(tx, nodeConfig.ClientTLSCreds.NodeID()) }) assert.NoError(t, err) renew := make(chan struct{}) updates := ca.RenewTLSConfig(ctx, nodeConfig, tc.Remotes, renew) select { case <-time.After(10 * time.Second): assert.Fail(t, "TestRenewTLSConfig timed-out") case certUpdate := <-updates: assert.Error(t, certUpdate.Err) assert.Contains(t, certUpdate.Err.Error(), "not found when attempting to renew certificate") } }
func TestGetRemoteCAInvalidHash(t *testing.T) { tc := testutils.NewTestCA(t) defer tc.Stop() _, err := ca.GetRemoteCA(tc.Context, "sha256:2d2f968475269f0dde5299427cf74348ee1d6115b95c6e3f283e5a4de8da445b", tc.Remotes) assert.Error(t, err) }
func TestLoadSecurityConfigInvalidCert(t *testing.T) { tc := testutils.NewTestCA(t) defer tc.Stop() // Write some garbage to the cert ioutil.WriteFile(tc.Paths.Node.Cert, []byte(`-----BEGIN CERTIFICATE-----\n some random garbage\n -----END CERTIFICATE-----`), 0644) krw := ca.NewKeyReadWriter(tc.Paths.Node, nil, nil) _, err := ca.LoadSecurityConfig(tc.Context, tc.RootCA, krw) assert.Error(t, err) nodeConfig, err := tc.RootCA.CreateSecurityConfig(tc.Context, krw, ca.CertificateRequestConfig{ Remotes: tc.Remotes, }) assert.NoError(t, err) assert.NotNil(t, nodeConfig) assert.NotNil(t, nodeConfig.ClientTLSCreds) assert.NotNil(t, nodeConfig.ServerTLSCreds) assert.Equal(t, tc.RootCA, *nodeConfig.RootCA()) }
func TestGetRemoteSignedCertificate(t *testing.T) { tc := testutils.NewTestCA(t) defer tc.Stop() // Create a new CSR to be signed csr, _, err := ca.GenerateAndWriteNewKey(tc.Paths.Node) assert.NoError(t, err) certs, err := ca.GetRemoteSignedCertificate(context.Background(), csr, tc.ManagerToken, tc.RootCA.Pool, tc.Remotes, nil, nil) assert.NoError(t, err) assert.NotNil(t, certs) // Test the expiration for a manager certificate parsedCerts, err := helpers.ParseCertificatesPEM(certs) assert.NoError(t, err) assert.Len(t, parsedCerts, 2) assert.True(t, time.Now().Add(ca.DefaultNodeCertExpiration).AddDate(0, 0, -1).Before(parsedCerts[0].NotAfter)) assert.True(t, time.Now().Add(ca.DefaultNodeCertExpiration).AddDate(0, 0, 1).After(parsedCerts[0].NotAfter)) assert.Equal(t, parsedCerts[0].Subject.OrganizationalUnit[0], ca.ManagerRole) // Test the expiration for an agent certificate certs, err = ca.GetRemoteSignedCertificate(tc.Context, csr, tc.WorkerToken, tc.RootCA.Pool, tc.Remotes, nil, nil) assert.NoError(t, err) assert.NotNil(t, certs) parsedCerts, err = helpers.ParseCertificatesPEM(certs) assert.NoError(t, err) assert.Len(t, parsedCerts, 2) assert.True(t, time.Now().Add(ca.DefaultNodeCertExpiration).AddDate(0, 0, -1).Before(parsedCerts[0].NotAfter)) assert.True(t, time.Now().Add(ca.DefaultNodeCertExpiration).AddDate(0, 0, 1).After(parsedCerts[0].NotAfter)) assert.Equal(t, parsedCerts[0].Subject.OrganizationalUnit[0], ca.AgentRole) }
func TestLoadNewTLSConfig(t *testing.T) { tc := testutils.NewTestCA(t) defer tc.Stop() // Create two different certs and two different TLS configs cert1, err := tc.RootCA.IssueAndSaveNewCertificates(tc.Paths.Node, "CN1", ca.ManagerRole, tc.Organization) assert.NoError(t, err) cert2, err := tc.RootCA.IssueAndSaveNewCertificates(tc.Paths.Node, "CN2", ca.AgentRole, tc.Organization) assert.NoError(t, err) tlsConfig1, err := ca.NewServerTLSConfig(cert1, tc.RootCA.Pool) assert.NoError(t, err) tlsConfig2, err := ca.NewServerTLSConfig(cert2, tc.RootCA.Pool) assert.NoError(t, err) // Load the first TLS config into a MutableTLS creds, err := ca.NewMutableTLS(tlsConfig1) assert.NoError(t, err) assert.Equal(t, ca.ManagerRole, creds.Role()) assert.Equal(t, "CN1", creds.NodeID()) // Load the new Config and assert it changed err = creds.LoadNewTLSConfig(tlsConfig2) assert.NoError(t, err) assert.Equal(t, ca.AgentRole, creds.Role()) assert.Equal(t, "CN2", creds.NodeID()) }
func agentTestEnv(t *testing.T) (*Agent, func()) { var cleanup []func() tc := testutils.NewTestCA(t, testutils.AcceptancePolicy(true, true, "")) cleanup = append(cleanup, func() { tc.Stop() }) agentSecurityConfig, err := tc.NewNodeConfig(ca.AgentRole) assert.NoError(t, err) addr := "localhost:4949" remotes := picker.NewRemotes(api.Peer{Addr: addr}) conn, err := grpc.Dial(addr, grpc.WithPicker(picker.NewPicker(remotes, addr)), grpc.WithTransportCredentials(agentSecurityConfig.ClientTLSCreds)) assert.NoError(t, err) db, cleanupStorage := storageTestEnv(t) cleanup = append(cleanup, func() { cleanupStorage() }) agent, err := New(&Config{ Executor: &NoopExecutor{}, Managers: remotes, Conn: conn, DB: db, }) return agent, func() { for i := len(cleanup) - 1; i > 0; i-- { cleanup[i]() } } }
func TestIssueNodeCertificateBrokenCA(t *testing.T) { if !testutils.External { t.Skip("test only applicable for external CA configuration") } tc := testutils.NewTestCA(t) defer tc.Stop() csr, _, err := ca.GenerateNewCSR() assert.NoError(t, err) tc.ExternalSigningServer.Flake() go func() { time.Sleep(250 * time.Millisecond) tc.ExternalSigningServer.Deflake() }() issueRequest := &api.IssueNodeCertificateRequest{CSR: csr, Token: tc.WorkerToken} issueResponse, err := tc.NodeCAClients[0].IssueNodeCertificate(context.Background(), issueRequest) assert.NoError(t, err) assert.NotNil(t, issueResponse.NodeID) assert.Equal(t, api.NodeMembershipAccepted, issueResponse.NodeMembership) statusRequest := &api.NodeCertificateStatusRequest{NodeID: issueResponse.NodeID} statusResponse, err := tc.NodeCAClients[0].NodeCertificateStatus(context.Background(), statusRequest) require.NoError(t, err) assert.Equal(t, api.IssuanceStateIssued, statusResponse.Status.State) assert.NotNil(t, statusResponse.Certificate.Certificate) assert.Equal(t, api.NodeRoleWorker, statusResponse.Certificate.Role) }
func TestAgentStartStop(t *testing.T) { tc := testutils.NewTestCA(t) defer tc.Stop() agentSecurityConfig, err := tc.NewNodeConfig(ca.AgentRole) assert.NoError(t, err) addr := "localhost:4949" remotes := remotes.NewRemotes(api.Peer{Addr: addr}) db, cleanup := storageTestEnv(t) defer cleanup() agent, err := New(&Config{ Executor: &NoopExecutor{}, Managers: remotes, Credentials: agentSecurityConfig.ClientTLSCreds, DB: db, }) assert.NoError(t, err) assert.NotNil(t, agent) ctx, _ := context.WithTimeout(context.Background(), 5000*time.Millisecond) assert.Equal(t, errAgentNotStarted, agent.Stop(ctx)) assert.NoError(t, agent.Start(ctx)) if err := agent.Start(ctx); err != errAgentStarted { t.Fatalf("expected agent started error: %v", err) } assert.NoError(t, agent.Stop(ctx)) }
func TestLoadOrCreateSecurityConfigNoCerts(t *testing.T) { tc := testutils.NewTestCA(t) defer tc.Stop() // Remove only the node certificates form the directory, and attest that we get // new certificates that are locally signed os.RemoveAll(tc.Paths.Node.Cert) nodeConfig, err := ca.LoadOrCreateSecurityConfig(tc.Context, tc.TempDir, tc.WorkerToken, ca.AgentRole, tc.Picker, nil) assert.NoError(t, err) assert.NotNil(t, nodeConfig) assert.NotNil(t, nodeConfig.ClientTLSCreds) assert.NotNil(t, nodeConfig.ServerTLSCreds) assert.NotNil(t, nodeConfig.RootCA().Pool) assert.NotNil(t, nodeConfig.RootCA().Cert) assert.NotNil(t, nodeConfig.RootCA().Signer) assert.True(t, nodeConfig.RootCA().CanSign()) info := make(chan api.IssueNodeCertificateResponse, 1) // Remove only the node certificates form the directory, and attest that we get // new certificates that are issued by the remote CA os.RemoveAll(tc.Paths.RootCA.Key) os.RemoveAll(tc.Paths.Node.Cert) nodeConfig, err = ca.LoadOrCreateSecurityConfig(tc.Context, tc.TempDir, tc.WorkerToken, ca.AgentRole, tc.Picker, info) assert.NoError(t, err) assert.NotNil(t, nodeConfig) assert.NotNil(t, nodeConfig.ClientTLSCreds) assert.NotNil(t, nodeConfig.ServerTLSCreds) assert.NotNil(t, nodeConfig.RootCA().Pool) assert.NotNil(t, nodeConfig.RootCA().Cert) assert.Nil(t, nodeConfig.RootCA().Signer) assert.False(t, nodeConfig.RootCA().CanSign()) assert.NotEmpty(t, <-info) }
func agentTestEnv(t *testing.T) (*Agent, func()) { var cleanup []func() tc := testutils.NewTestCA(t) cleanup = append(cleanup, func() { tc.Stop() }) agentSecurityConfig, err := tc.NewNodeConfig(ca.AgentRole) assert.NoError(t, err) addr := "localhost:4949" remotes := remotes.NewRemotes(api.Peer{Addr: addr}) db, cleanupStorage := storageTestEnv(t) cleanup = append(cleanup, func() { cleanupStorage() }) agent, err := New(&Config{ Executor: &NoopExecutor{}, Managers: remotes, Credentials: agentSecurityConfig.ClientTLSCreds, DB: db, }) return agent, func() { for i := len(cleanup) - 1; i >= 0; i-- { cleanup[i]() } } }
func TestLoadOrCreateSecurityConfigInvalidKeyWithValidTempKey(t *testing.T) { tc := testutils.NewTestCA(t) defer tc.Stop() nodeConfig, err := ca.LoadOrCreateSecurityConfig(tc.Context, tc.TempDir, "", ca.AgentRole, tc.Picker, nil) assert.NoError(t, err) assert.NotNil(t, nodeConfig) assert.NotNil(t, nodeConfig.ClientTLSCreds) assert.NotNil(t, nodeConfig.ServerTLSCreds) assert.NotNil(t, nodeConfig.RootCA().Pool) assert.NotNil(t, nodeConfig.RootCA().Cert) assert.NotNil(t, nodeConfig.RootCA().Signer) // Write some garbage to the Key assert.NoError(t, os.Rename(tc.Paths.Node.Key, filepath.Dir(tc.Paths.Node.Key)+"."+filepath.Base(tc.Paths.Node.Key))) ioutil.WriteFile(tc.Paths.Node.Key, []byte(`-----BEGIN EC PRIVATE KEY-----\n some random garbage\n -----END EC PRIVATE KEY-----`), 0644) nodeConfig, err = ca.LoadOrCreateSecurityConfig(tc.Context, tc.TempDir, "", ca.AgentRole, nil, nil) assert.NoError(t, err) assert.NotNil(t, nodeConfig) assert.NotNil(t, nodeConfig.ClientTLSCreds) assert.NotNil(t, nodeConfig.ServerTLSCreds) assert.NotNil(t, nodeConfig.RootCA().Pool) assert.NotNil(t, nodeConfig.RootCA().Cert) assert.NotNil(t, nodeConfig.RootCA().Signer) }
func TestRenewTLSConfigManager(t *testing.T) { tc := testutils.NewTestCA(t) defer tc.Stop() ctx, cancel := context.WithCancel(context.Background()) defer cancel() // Get a new nodeConfig with a TLS cert that has the default Cert duration nodeConfig, err := tc.WriteNewNodeConfig(ca.ManagerRole) assert.NoError(t, err) // Create a new RootCA, and change the policy to issue 6 minute certificates newRootCA, err := ca.NewRootCA(tc.RootCA.Cert, tc.RootCA.Key, ca.DefaultNodeCertExpiration) assert.NoError(t, err) newRootCA.Signer.SetPolicy(&cfconfig.Signing{ Default: &cfconfig.SigningProfile{ Usage: []string{"signing", "key encipherment", "server auth", "client auth"}, Expiry: 6 * time.Minute, }, }) // Create a new CSR and overwrite the key on disk csr, _, err := ca.GenerateAndWriteNewKey(tc.Paths.Node) assert.NoError(t, err) // Issue a new certificate with the same details as the current config, but with 6 min expiration time c := nodeConfig.ClientTLSCreds signedCert, err := newRootCA.ParseValidateAndSignCSR(csr, c.NodeID(), c.Role(), c.Organization()) assert.NoError(t, err) assert.NotNil(t, signedCert) // Overwrite the certificate on disk with one that expires in 1 minute err = ioutils.AtomicWriteFile(tc.Paths.Node.Cert, signedCert, 0644) assert.NoError(t, err) // Get a new nodeConfig with a TLS cert that has 6 minutes to live var success, timeout bool renew := make(chan struct{}) updates := ca.RenewTLSConfig(ctx, nodeConfig, tc.TempDir, tc.Picker, renew) for { select { case <-time.After(2 * time.Second): timeout = true case certUpdate := <-updates: assert.NoError(t, certUpdate.Err) assert.NotNil(t, certUpdate) assert.Equal(t, ca.ManagerRole, certUpdate.Role) success = true } if timeout { assert.Fail(t, "TestRenewTLSConfig timed-out") break } if success { break } } }
func TestCanSign(t *testing.T) { tc := testutils.NewTestCA(t) defer tc.Stop() assert.True(t, tc.RootCA.CanSign()) tc.RootCA.Signer = nil assert.False(t, tc.RootCA.CanSign()) }
func TestGetRootCACertificate(t *testing.T) { tc := testutils.NewTestCA(t) defer tc.Stop() resp, err := tc.CAClients[0].GetRootCACertificate(context.Background(), &api.GetRootCACertificateRequest{}) assert.NoError(t, err) assert.NotEmpty(t, resp.Certificate) }
func TestCanSign(t *testing.T) { tc := testutils.NewTestCA(t, testutils.AcceptancePolicy(true, true, "")) defer tc.Stop() assert.True(t, tc.RootCA.CanSign()) tc.RootCA.Signer = nil assert.False(t, tc.RootCA.CanSign()) }
func TestNodeCertificateRenewalsDoNotRequireSecret(t *testing.T) { hashPwd, _ := bcrypt.GenerateFromPassword([]byte("secret-data"), 0) policy := api.AcceptancePolicy{ Policies: []*api.AcceptancePolicy_RoleAdmissionPolicy{ { Role: api.NodeRoleWorker, Autoaccept: true, Secret: &api.AcceptancePolicy_RoleAdmissionPolicy_HashedSecret{ Data: hashPwd, Alg: "bcrypt", }, }, { Role: api.NodeRoleManager, Autoaccept: true, Secret: &api.AcceptancePolicy_RoleAdmissionPolicy_HashedSecret{ Data: hashPwd, Alg: "bcrypt", }, }, }, } tc := testutils.NewTestCA(t, policy) defer tc.Stop() csr, _, err := ca.GenerateAndWriteNewKey(tc.Paths.Node) assert.NoError(t, err) role := api.NodeRoleManager issueRequest := &api.IssueNodeCertificateRequest{CSR: csr, Role: role} issueResponse, err := tc.NodeCAClients[2].IssueNodeCertificate(context.Background(), issueRequest) assert.NotNil(t, issueResponse.NodeID) assert.Equal(t, api.NodeMembershipAccepted, issueResponse.NodeMembership) statusRequest := &api.NodeCertificateStatusRequest{NodeID: issueResponse.NodeID} statusResponse, err := tc.NodeCAClients[2].NodeCertificateStatus(context.Background(), statusRequest) assert.Equal(t, api.IssuanceStateIssued, statusResponse.Status.State) assert.NotNil(t, statusResponse.Certificate.Certificate) assert.Equal(t, role, statusResponse.Certificate.Role) role = api.NodeRoleWorker issueRequest = &api.IssueNodeCertificateRequest{CSR: csr, Role: role} issueResponse, err = tc.NodeCAClients[1].IssueNodeCertificate(context.Background(), issueRequest) require.NoError(t, err) assert.NotNil(t, issueResponse.NodeID) assert.Equal(t, api.NodeMembershipAccepted, issueResponse.NodeMembership) statusRequest = &api.NodeCertificateStatusRequest{NodeID: issueResponse.NodeID} statusResponse, err = tc.NodeCAClients[2].NodeCertificateStatus(context.Background(), statusRequest) require.NoError(t, err) assert.Equal(t, api.IssuanceStateIssued, statusResponse.Status.State) assert.NotNil(t, statusResponse.Certificate.Certificate) assert.Equal(t, role, statusResponse.Certificate.Role) }
func TestLoadOrCreateSecurityConfigNoCertsAndNoRemote(t *testing.T) { tc := testutils.NewTestCA(t) defer tc.Stop() // Remove the certificate from the temp dir and try loading with a new manager os.Remove(tc.Paths.Node.Cert) os.Remove(tc.Paths.RootCA.Key) _, err := ca.LoadOrCreateSecurityConfig(tc.Context, tc.TempDir, tc.WorkerToken, ca.AgentRole, nil, nil) assert.EqualError(t, err, "valid remote address picker required") }
func TestMain(m *testing.M) { tc = cautils.NewTestCA(nil) grpclog.SetLogger(log.New(ioutil.Discard, "", log.LstdFlags)) logrus.SetOutput(ioutil.Discard) res := m.Run() tc.Stop() os.Exit(res) }
// If there are CAs and TLS certs on disk, it tries to load and fails if there // are any errors, even if a join token is provided. func TestLoadSecurityConfigLoadFromDisk(t *testing.T) { tempdir, err := ioutil.TempDir("", "test-load-node-tls") require.NoError(t, err) defer os.RemoveAll(tempdir) paths := ca.NewConfigPaths(filepath.Join(tempdir, "certificates")) tc := cautils.NewTestCA(t) defer tc.Stop() peer, err := tc.ConnBroker.Remotes().Select() require.NoError(t, err) // Load successfully with valid passphrase rootCA, err := ca.CreateRootCA(ca.DefaultRootCN, paths.RootCA) require.NoError(t, err) krw := ca.NewKeyReadWriter(paths.Node, []byte("passphrase"), nil) require.NoError(t, err) _, err = rootCA.IssueAndSaveNewCertificates(krw, identity.NewID(), ca.WorkerRole, identity.NewID()) require.NoError(t, err) node, err := New(&Config{ StateDir: tempdir, JoinAddr: peer.Addr, JoinToken: tc.ManagerToken, UnlockKey: []byte("passphrase"), }) require.NoError(t, err) securityConfig, err := node.loadSecurityConfig(context.Background()) require.NoError(t, err) require.NotNil(t, securityConfig) // Invalid passphrase node, err = New(&Config{ StateDir: tempdir, JoinAddr: peer.Addr, JoinToken: tc.ManagerToken, }) require.NoError(t, err) _, err = node.loadSecurityConfig(context.Background()) require.Equal(t, ErrInvalidUnlockKey, err) // Invalid CA rootCA, err = ca.CreateRootCA(ca.DefaultRootCN, paths.RootCA) require.NoError(t, err) node, err = New(&Config{ StateDir: tempdir, JoinAddr: peer.Addr, JoinToken: tc.ManagerToken, UnlockKey: []byte("passphrase"), }) require.NoError(t, err) _, err = node.loadSecurityConfig(context.Background()) require.IsType(t, x509.UnknownAuthorityError{}, errors.Cause(err)) }
func createManagersCluster(t *testing.T, managersCount, agentsCount int) *managersCluster { tc := catestutils.NewTestCA(t) defer tc.Stop() mc := &managersCluster{tc: tc} require.NoError(t, mc.addManagers(t, managersCount)) time.Sleep(5 * time.Second) require.NoError(t, mc.addAgents(agentsCount)) time.Sleep(10 * time.Second) return mc }
func TestLoadOrCreateSecurityConfigNoLocalCACertNoRemote(t *testing.T) { tc := testutils.NewTestCA(t) defer tc.Stop() // Delete the root CA file so that LoadOrCreateSecurityConfig falls // back to using the remote. assert.Nil(t, os.Remove(tc.Paths.RootCA.Cert)) nodeConfig, err := ca.LoadOrCreateSecurityConfig(tc.Context, tc.TempDir, "", ca.AgentRole, nil, nil) assert.EqualError(t, err, "valid remote address picker required") assert.Nil(t, nodeConfig) }