github.com/lmb/consul@v1.4.1/connect/certgen/certgen.go (about)

     1  // certgen: a tool for generating test certificates on disk for use as
     2  // test-fixtures and for end-to-end testing and local development.
     3  //
     4  // Example usage:
     5  //
     6  //   $ go run connect/certgen/certgen.go -out-dir /tmp/connect-certs
     7  //
     8  // You can verify a given leaf with a given root using:
     9  //
    10  //   $ openssl verify -verbose -CAfile ca2-ca.cert.pem ca1-svc-db.cert.pem
    11  //
    12  // Note that to verify via the cross-signed intermediate, openssl requires it to
    13  // be bundled with the _root_ CA bundle and will ignore the cert if it's passed
    14  // with the subject. You can do that with:
    15  //
    16  //   $ openssl verify -verbose -CAfile \
    17  //      <(cat ca1-ca.cert.pem ca2-xc-by-ca1.cert.pem) \
    18  //      ca2-svc-db.cert.pem
    19  //   ca2-svc-db.cert.pem: OK
    20  //
    21  // Note that the same leaf and root without the intermediate should fail:
    22  //
    23  //  $ openssl verify -verbose -CAfile ca1-ca.cert.pem ca2-svc-db.cert.pem
    24  //  ca2-svc-db.cert.pem: CN = db
    25  //  error 20 at 0 depth lookup:unable to get local issuer certificate
    26  //
    27  // NOTE: THIS IS A QUIRK OF OPENSSL; in Connect we distribute the roots alone
    28  // and stable intermediates like the XC cert to the _leaf_.
    29  package main // import "github.com/hashicorp/consul/connect/certgen"
    30  
    31  import (
    32  	"flag"
    33  	"fmt"
    34  	"io/ioutil"
    35  	"log"
    36  	"os"
    37  
    38  	"github.com/hashicorp/consul/agent/connect"
    39  	"github.com/hashicorp/consul/agent/structs"
    40  	"github.com/mitchellh/go-testing-interface"
    41  )
    42  
    43  func main() {
    44  	var numCAs = 2
    45  	var services = []string{"web", "db", "cache"}
    46  	var outDir string
    47  
    48  	flag.StringVar(&outDir, "out-dir", "",
    49  		"REQUIRED: the dir to write certificates to")
    50  	flag.Parse()
    51  
    52  	if outDir == "" {
    53  		flag.PrintDefaults()
    54  		os.Exit(1)
    55  	}
    56  
    57  	// Create CA certs
    58  	var prevCA *structs.CARoot
    59  	for i := 1; i <= numCAs; i++ {
    60  		ca := connect.TestCA(&testing.RuntimeT{}, prevCA)
    61  		prefix := fmt.Sprintf("%s/ca%d-ca", outDir, i)
    62  		writeFile(prefix+".cert.pem", ca.RootCert)
    63  		writeFile(prefix+".key.pem", ca.SigningKey)
    64  		if prevCA != nil {
    65  			fname := fmt.Sprintf("%s/ca%d-xc-by-ca%d.cert.pem", outDir, i, i-1)
    66  			writeFile(fname, ca.SigningCert)
    67  		}
    68  		prevCA = ca
    69  
    70  		// Create service certs for each CA
    71  		for _, svc := range services {
    72  			certPEM, keyPEM := connect.TestLeaf(&testing.RuntimeT{}, svc, ca)
    73  			prefix := fmt.Sprintf("%s/ca%d-svc-%s", outDir, i, svc)
    74  			writeFile(prefix+".cert.pem", certPEM)
    75  			writeFile(prefix+".key.pem", keyPEM)
    76  		}
    77  	}
    78  }
    79  
    80  func writeFile(name, content string) {
    81  	fmt.Println("Writing ", name)
    82  	err := ioutil.WriteFile(name, []byte(content), 0600)
    83  	if err != nil {
    84  		log.Fatalf("failed writing file: %s", err)
    85  	}
    86  }