github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/security/x509_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  	"crypto/rand"
    15  	"crypto/rsa"
    16  	"crypto/x509"
    17  	"testing"
    18  	"time"
    19  
    20  	"github.com/cockroachdb/cockroach/pkg/security"
    21  	"github.com/cockroachdb/cockroach/pkg/testutils"
    22  	"github.com/cockroachdb/cockroach/pkg/util/leaktest"
    23  	"github.com/cockroachdb/cockroach/pkg/util/timeutil"
    24  )
    25  
    26  const wiggle = time.Minute * 5
    27  
    28  // Returns true if "|a-b| <= wiggle".
    29  func timesFuzzyEqual(a, b time.Time) bool {
    30  	diff := a.Sub(b)
    31  	if diff < 0 {
    32  		diff = -diff
    33  	}
    34  	return diff <= wiggle
    35  }
    36  
    37  func TestGenerateCertLifetime(t *testing.T) {
    38  	defer leaktest.AfterTest(t)()
    39  
    40  	testKey, err := rsa.GenerateKey(rand.Reader, 512)
    41  	if err != nil {
    42  		t.Fatal(err)
    43  	}
    44  
    45  	// Create a CA that expires in 2 days.
    46  	caDuration := time.Hour * 48
    47  	now := timeutil.Now()
    48  	caBytes, err := security.GenerateCA(testKey, caDuration)
    49  	if err != nil {
    50  		t.Fatal(err)
    51  	}
    52  
    53  	caCert, err := x509.ParseCertificate(caBytes)
    54  	if err != nil {
    55  		t.Fatal(err)
    56  	}
    57  
    58  	if a, e := caCert.NotAfter, now.Add(caDuration); !timesFuzzyEqual(a, e) {
    59  		t.Fatalf("CA expiration differs from requested: %s vs %s", a, e)
    60  	}
    61  
    62  	// Create a Node certificate expiring in 4 days. Fails on shorter CA lifetime.
    63  	nodeDuration := time.Hour * 96
    64  	_, err = security.GenerateServerCert(caCert, testKey,
    65  		testKey.Public(), nodeDuration, security.NodeUser, []string{"localhost"})
    66  	if !testutils.IsError(err, "CA lifetime is .*, shorter than the requested .*") {
    67  		t.Fatal(err)
    68  	}
    69  
    70  	// Try again, but expiring before the CA cert.
    71  	nodeDuration = time.Hour * 24
    72  	nodeBytes, err := security.GenerateServerCert(caCert, testKey,
    73  		testKey.Public(), nodeDuration, security.NodeUser, []string{"localhost"})
    74  	if err != nil {
    75  		t.Fatal(err)
    76  	}
    77  
    78  	nodeCert, err := x509.ParseCertificate(nodeBytes)
    79  	if err != nil {
    80  		t.Fatal(err)
    81  	}
    82  
    83  	if a, e := nodeCert.NotAfter, now.Add(nodeDuration); !timesFuzzyEqual(a, e) {
    84  		t.Fatalf("node expiration differs from requested: %s vs %s", a, e)
    85  	}
    86  
    87  	// Create a Client certificate expiring in 4 days. Should get reduced to the CA lifetime.
    88  	clientDuration := time.Hour * 96
    89  	_, err = security.GenerateClientCert(caCert, testKey, testKey.Public(), clientDuration, "testuser")
    90  	if !testutils.IsError(err, "CA lifetime is .*, shorter than the requested .*") {
    91  		t.Fatal(err)
    92  	}
    93  
    94  	// Try again, but expiring before the CA cert.
    95  	clientDuration = time.Hour * 24
    96  	clientBytes, err := security.GenerateClientCert(caCert, testKey, testKey.Public(), clientDuration, "testuser")
    97  	if err != nil {
    98  		t.Fatal(err)
    99  	}
   100  
   101  	clientCert, err := x509.ParseCertificate(clientBytes)
   102  	if err != nil {
   103  		t.Fatal(err)
   104  	}
   105  
   106  	if a, e := clientCert.NotAfter, now.Add(clientDuration); !timesFuzzyEqual(a, e) {
   107  		t.Fatalf("client expiration differs from requested: %s vs %s", a, e)
   108  	}
   109  
   110  }