github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/security/certificate_manager_test.go (about)

     1  // Copyright 2017 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package security_test
    12  
    13  import (
    14  	"fmt"
    15  	"io/ioutil"
    16  	"os"
    17  	"path/filepath"
    18  	"strings"
    19  	"testing"
    20  	"time"
    21  
    22  	"github.com/cockroachdb/cockroach/pkg/security"
    23  	"github.com/cockroachdb/cockroach/pkg/util/envutil"
    24  	"github.com/cockroachdb/cockroach/pkg/util/leaktest"
    25  	"github.com/stretchr/testify/require"
    26  )
    27  
    28  func TestManagerWithEmbedded(t *testing.T) {
    29  	defer leaktest.AfterTest(t)()
    30  	cm, err := security.NewCertificateManager("test_certs")
    31  	if err != nil {
    32  		t.Error(err)
    33  	}
    34  
    35  	// Verify loaded certs.
    36  	if cm.CACert() == nil {
    37  		t.Error("expected non-nil CACert")
    38  	}
    39  	if cm.NodeCert() == nil {
    40  		t.Error("expected non-nil NodeCert")
    41  	}
    42  	clientCerts := cm.ClientCerts()
    43  	if a, e := len(clientCerts), 2; a != e {
    44  		t.Errorf("expected %d client certs, found %d", e, a)
    45  	}
    46  
    47  	if _, ok := clientCerts[security.RootUser]; !ok {
    48  		t.Error("no client cert for root user found")
    49  	}
    50  
    51  	// Verify that we can build tls.Config objects.
    52  	if _, err := cm.GetServerTLSConfig(); err != nil {
    53  		t.Error(err)
    54  	}
    55  	if _, err := cm.GetClientTLSConfig(security.NodeUser); err != nil {
    56  		t.Error(err)
    57  	}
    58  	if _, err := cm.GetClientTLSConfig(security.RootUser); err != nil {
    59  		t.Error(err)
    60  	}
    61  	if _, err := cm.GetClientTLSConfig("testuser"); err != nil {
    62  		t.Error(err)
    63  	}
    64  	if _, err := cm.GetClientTLSConfig("my-random-user"); err == nil {
    65  		t.Error("unexpected success")
    66  	}
    67  }
    68  
    69  func TestManagerWithPrincipalMap(t *testing.T) {
    70  	defer leaktest.AfterTest(t)()
    71  
    72  	// Do not mock cert access for this test.
    73  	security.ResetAssetLoader()
    74  	defer ResetTest()
    75  
    76  	defer func() { _ = security.SetCertPrincipalMap(nil) }()
    77  	defer func() {
    78  		_ = os.Setenv("COCKROACH_CERT_NODE_USER", security.NodeUser)
    79  		envutil.ClearEnvCache()
    80  	}()
    81  	require.NoError(t, os.Setenv("COCKROACH_CERT_NODE_USER", "node.crdb.io"))
    82  
    83  	certsDir, err := ioutil.TempDir("", "certs_test")
    84  	require.NoError(t, err)
    85  	defer func() {
    86  		require.NoError(t, os.RemoveAll(certsDir))
    87  	}()
    88  
    89  	caKey := filepath.Join(certsDir, "ca.key")
    90  	require.NoError(t, security.CreateCAPair(
    91  		certsDir, caKey, testKeySize, time.Hour*96, true, true,
    92  	))
    93  	require.NoError(t, security.CreateClientPair(
    94  		certsDir, caKey, testKeySize, time.Hour*48, true, "testuser", false,
    95  	))
    96  	require.NoError(t, security.CreateNodePair(
    97  		certsDir, caKey, testKeySize, time.Hour*48, true, []string{"127.0.0.1", "foo"},
    98  	))
    99  
   100  	setCertPrincipalMap := func(s string) {
   101  		require.NoError(t, security.SetCertPrincipalMap(strings.Split(s, ",")))
   102  	}
   103  	newCertificateManager := func() error {
   104  		_, err := security.NewCertificateManager(certsDir)
   105  		return err
   106  	}
   107  	loadUserCert := func(user string) error {
   108  		cm, err := security.NewCertificateManager(certsDir)
   109  		if err != nil {
   110  			return err
   111  		}
   112  		ci := cm.ClientCerts()[user]
   113  		if ci == nil {
   114  			return fmt.Errorf("user %q not found", user)
   115  		}
   116  		return ci.Error
   117  	}
   118  
   119  	setCertPrincipalMap("")
   120  	require.Regexp(t, `node certificate has principals \["node.crdb.io" "foo"\]`, newCertificateManager())
   121  
   122  	// We can map the "node.crdb.io" principal to "node".
   123  	setCertPrincipalMap("node.crdb.io:node")
   124  	require.NoError(t, newCertificateManager())
   125  
   126  	// We can map the "foo" principal to "node".
   127  	setCertPrincipalMap("foo:node")
   128  	require.NoError(t, newCertificateManager())
   129  
   130  	// Mapping the "testuser" principal to a different name should result in an
   131  	// error as it no longer matches the file name.
   132  	setCertPrincipalMap("testuser:foo,node.crdb.io:node")
   133  	require.Regexp(t, `client certificate has principals \["foo"\], expected "testuser"`, loadUserCert("testuser"))
   134  
   135  	// Renaming "client.testuser.crt" to "client.foo.crt" allows us to load it
   136  	// under that name.
   137  	require.NoError(t, os.Rename(filepath.Join(certsDir, "client.testuser.crt"),
   138  		filepath.Join(certsDir, "client.foo.crt")))
   139  	require.NoError(t, os.Rename(filepath.Join(certsDir, "client.testuser.key"),
   140  		filepath.Join(certsDir, "client.foo.key")))
   141  	setCertPrincipalMap("testuser:foo,node.crdb.io:node")
   142  	require.NoError(t, loadUserCert("foo"))
   143  }