func CreateClientPair(certsDir, caKeyPath string, keySize int, lifetime time.Duration, overwrite bool,
	user SQLUsername, wantPKCS8Key bool) error {
	if len(caKeyPath) == 0 {
		return errors.New("the path to the CA key is required")
	}
	if len(certsDir) == 0 {
		return errors.New("the path to the certs directory is required")
	}
	certsDirParam := fmt.Sprintf(CERTS_DIR, certsDir)
	caKeyParam := fmt.Sprintf(CA_KEY, caKeyPath)
	lifetimeParam := fmt.Sprintf(Life_Time, lifetime.String())
	execCmd(CREATE_CLIENT, user.U, certsDirParam, caKeyParam, lifetimeParam)
	return nil
}
CreateClientPair creates a node key and certificate.
The CA cert and key must load properly. If multiple certificates
exist in the CA cert, the first one is used.
If a client CA exists, this is used instead.
If wantPKCS8Key is true, the private key in PKCS#8 encoding is written as well.
package security
import (
	"crypto/x509"
	"encoding/pem"
	"errors"
	"fmt"
	"os/exec"
	"time"
)
type SQLUsername struct {
	U string
}
const (
	KeyFileMode  = 0600
	CertFileMode = 0644
	RootUser     = "root"
)
type PemUsage uint32
const (
	_ PemUsage = iota
	CAPem
	TenantClientCAPem
	ClientCAPem
	UICAPem
	NodePem
	UIPem
	ClientPem
	TenantClientPem
)
const (
	CR            string = "cockroach"
	CERT          string = "cert"
	CREATE_CA     string = "create-ca"
	CREATE_NODE   string = "create-node"
	CREATE_CLIENT string = "create-client"
	CERTS_DIR  string = "--certs-dir=%s"
	CA_KEY     string = "--ca-key=%s"
	Life_Time  string = "--lifetime=%s"
	OVER_WRITE string = "--overwrite"
)
func CreateCAPair(
	certsDir, caKeyPath string,
	keySize int,
	lifetime time.Duration,
	allowKeyReuse bool,
	overwrite bool,
) error {
	return createCACertAndKey(certsDir, caKeyPath, CAPem, keySize, lifetime, allowKeyReuse, overwrite)
}
func createCACertAndKey(certsDir, caKeyPath string, caType PemUsage, keySize int, lifetime time.Duration, allowKeyReuse bool, overwrite bool) error {
	if len(caKeyPath) == 0 {
		return errors.New("the path to the CA key is required")
	}
	if len(certsDir) == 0 {
		return errors.New("the path to the certs directory is required")
	}
	if caType != CAPem {
		return fmt.Errorf("caType argument to createCACertAndKey must be CAPem (%d), got: %d", CAPem, caType)
	}
	certsDirParam := fmt.Sprintf(CERTS_DIR, certsDir)
	caKeyParam := fmt.Sprintf(CA_KEY, caKeyPath)
	lifetimeParam := fmt.Sprintf(Life_Time, lifetime.String())
	args := []string{CREATE_CA, certsDirParam, caKeyParam, lifetimeParam}
	if overwrite {
		args = append(args, OVER_WRITE)
	}
	execCmd(args...)
	return nil
}
func CreateNodePair(certsDir, caKeyPath string, keySize int, lifetime time.Duration, overwrite bool, hosts []string) error {
	if len(caKeyPath) == 0 {
		return errors.New("the path to the CA key is required")
	}
	if len(certsDir) == 0 {
		return errors.New("the path to the certs directory is required")
	}
	certsDirParam := fmt.Sprintf(CERTS_DIR, certsDir)
	caKeyParam := fmt.Sprintf(CA_KEY, caKeyPath)
	lifetimeParam := fmt.Sprintf(Life_Time, lifetime.String())
	args := append(hosts, certsDirParam, caKeyParam, lifetimeParam)
	args = append([]string{CREATE_NODE}, args...)
	execCmd(args...)
	return nil
}