consul/connect/certgen/certgen.go

96 lines
2.8 KiB
Go
Raw Normal View History

// Copyright (c) HashiCorp, Inc.
[COMPLIANCE] License changes (#18443) * Adding explicit MPL license for sub-package This directory and its subdirectories (packages) contain files licensed with the MPLv2 `LICENSE` file in this directory and are intentionally licensed separately from the BSL `LICENSE` file at the root of this repository. * Adding explicit MPL license for sub-package This directory and its subdirectories (packages) contain files licensed with the MPLv2 `LICENSE` file in this directory and are intentionally licensed separately from the BSL `LICENSE` file at the root of this repository. * Updating the license from MPL to Business Source License Going forward, this project will be licensed under the Business Source License v1.1. Please see our blog post for more details at <Blog URL>, FAQ at www.hashicorp.com/licensing-faq, and details of the license at www.hashicorp.com/bsl. * add missing license headers * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 --------- Co-authored-by: hashicorp-copywrite[bot] <110428419+hashicorp-copywrite[bot]@users.noreply.github.com>
2023-08-11 13:12:13 +00:00
// SPDX-License-Identifier: BUSL-1.1
// certgen: a tool for generating test certificates on disk for use as
// test-fixtures and for end-to-end testing and local development.
//
// Example usage:
//
// $ go run connect/certgen/certgen.go -out-dir /tmp/connect-certs
//
// You can verify a given leaf with a given root using:
//
// $ openssl verify -verbose -CAfile ca1-ca.cert.pem ca1-svc-db.cert.pem
//
// Note that to verify via the cross-signed intermediate, openssl requires it to
// be bundled with the _root_ CA bundle and will ignore the cert if it's passed
// with the subject. You can do that with:
//
// $ openssl verify -verbose -CAfile \
// <(cat ca1-ca.cert.pem ca2-xc-by-ca1.cert.pem) \
// ca2-svc-db.cert.pem
// ca2-svc-db.cert.pem: OK
//
// Note that the same leaf and root without the intermediate should fail:
//
// $ openssl verify -verbose -CAfile ca1-ca.cert.pem ca2-svc-db.cert.pem
// ca2-svc-db.cert.pem: CN = db
// error 20 at 0 depth lookup:unable to get local issuer certificate
//
// NOTE: THIS IS A QUIRK OF OPENSSL; in Connect we distribute the roots alone
// and stable intermediates like the XC cert to the _leaf_.
package main // import "github.com/hashicorp/consul/connect/certgen"
import (
"flag"
"fmt"
"log"
"os"
"github.com/mitchellh/go-testing-interface"
"github.com/hashicorp/consul/agent/connect"
"github.com/hashicorp/consul/agent/structs"
)
func main() {
var numCAs = 2
var services = []string{"web", "db", "cache"}
var outDir string
var keyType string = "ec"
var keyBits int = 256
flag.StringVar(&outDir, "out-dir", "",
"REQUIRED: the dir to write certificates to")
flag.StringVar(&keyType, "key-type", "ec",
"Type of private key to create (ec, rsa)")
flag.IntVar(&keyBits, "key-bits", 256,
"Size of private key to create, in bits")
flag.Parse()
if outDir == "" {
flag.PrintDefaults()
os.Exit(1)
}
// Create CA certs
var prevCA *structs.CARoot
for i := 1; i <= numCAs; i++ {
ca := connect.TestCAWithKeyType(&testing.RuntimeT{}, prevCA, keyType, keyBits)
prefix := fmt.Sprintf("%s/ca%d-ca", outDir, i)
writeFile(prefix+".cert.pem", ca.RootCert)
writeFile(prefix+".key.pem", ca.SigningKey)
if prevCA != nil {
fname := fmt.Sprintf("%s/ca%d-xc-by-ca%d.cert.pem", outDir, i, i-1)
writeFile(fname, ca.SigningCert)
}
prevCA = ca
// Create service certs for each CA
for _, svc := range services {
certPEM, keyPEM := connect.TestLeaf(&testing.RuntimeT{}, svc, ca)
prefix := fmt.Sprintf("%s/ca%d-svc-%s", outDir, i, svc)
writeFile(prefix+".cert.pem", certPEM)
writeFile(prefix+".key.pem", keyPEM)
}
}
}
func writeFile(name, content string) {
fmt.Println("Writing ", name)
err := os.WriteFile(name, []byte(content), 0600)
if err != nil {
log.Fatalf("failed writing file: %s", err)
}
}