Add some extra validation and print certificate objects

This commit also changes the following flags for consistency:
  - --crt-cert to --crt-cert-obj
  - --crt-key to --crt-key-obj
This commit is contained in:
Mariano Cano 2021-11-17 15:48:52 -08:00
parent bbb327c8c5
commit febb619882

View file

@ -58,16 +58,25 @@ func (c *Config) Validate() error {
switch {
case c.KMS == "":
return errors.New("flag `--kms` is required")
case c.CrtPath == "":
return errors.New("flag `--crt-cert-path` is required")
case c.RootFile != "" && c.KeyFile == "":
return errors.New("flag `--root-cert-file` requires flag `--key`")
return errors.New("flag `--root-cert-file` requires flag `--root-key-file`")
case c.KeyFile != "" && c.RootFile == "":
return errors.New("flag `--key` requires flag `--root-cert-file`")
return errors.New("flag `--root-key-file` requires flag `--root-cert-file`")
case c.RootFile == "" && c.RootObject == "":
return errors.New("one of flag `--root` or `--root-cert` is required")
case c.RootFile == "" && c.RootKeyObject == "":
return errors.New("one of flag `--root` or `--root-key` is required")
return errors.New("one of flag `--root-cert-file` or `--root-cert-obj` is required")
case c.KeyFile == "" && c.RootKeyObject == "":
return errors.New("one of flag `--root-key-file` or `--root-key-obj` is required")
case c.CrtKeyPath == "" && c.CrtKeyObject == "":
return errors.New("one of flag `--crt-key-path` or `--crt-key-obj` is required")
case c.RootFile == "" && c.GenerateRoot && c.RootKeyObject == "":
return errors.New("flag `--root-gen` requires flag `--root-key-obj`")
case c.RootFile == "" && c.GenerateRoot && c.RootPath == "":
return errors.New("flag `--root-gen` requires `--root-cert-path`")
default:
if c.RootFile != "" {
c.GenerateRoot = false
c.RootObject = ""
c.RootKeyObject = ""
}
@ -101,23 +110,25 @@ func main() {
flag.StringVar(&c.Pin, "pin", "", "PKCS #11 PIN")
// Option 1: Generate new root
flag.BoolVar(&c.GenerateRoot, "root-gen", true, "Enable the generation of a root key.")
flag.StringVar(&c.RootFile, "root-cert-file", "", "Path to the root certificate to use.")
flag.StringVar(&c.RootSubject, "root-name", "PKCS #11 Smallstep Root", "Subject and Issuer of the root certificate.")
flag.StringVar(&c.RootObject, "root-cert-obj", "pkcs11:id=7330;object=root-cert", "PKCS #11 URI with object id and label to store the root certificate.")
flag.StringVar(&c.RootKeyObject, "root-key-obj", "pkcs11:id=7330;object=root-key", "PKCS #11 URI with object id and label to store the root key.")
flag.StringVar(&c.RootSubject, "root-name", "PKCS #11 Smallstep Root", "Subject and Issuer of the root certificate.")
// Option 2: Read root from disk and sign intermediate
flag.StringVar(&c.RootPath, "root-cert-path", "root_ca.crt", "Location to write the root certificate.")
flag.StringVar(&c.RootFile, "root-cert-file", "", "Path to the root certificate to use.")
flag.StringVar(&c.KeyFile, "root-key-file", "", "Path to the root key to use.")
// Option 3: Generate certificate signing request
flag.StringVar(&c.CrtObject, "crt-cert", "pkcs11:id=7331;object=intermediate-cert", "PKCS #11 URI with object id and label to store the intermediate certificate.")
flag.StringVar(&c.CrtPath, "crt-cert-path", "intermediate_ca.crt", "Location to write the intermediate certificate.")
flag.StringVar(&c.CrtKeyObject, "crt-key", "pkcs11:id=7331;object=intermediate-key", "PKCS #11 URI with object id and label to store the intermediate certificate.")
flag.StringVar(&c.CrtSubject, "crt-name", "PKCS #11 Smallstep Intermediate", "Subject of the intermediate certificate.")
flag.StringVar(&c.CrtKeyPath, "crt-key-path", "", "Location to write the intermediate private key.")
flag.StringVar(&c.CrtObject, "crt-cert-obj", "pkcs11:id=7331;object=intermediate-cert", "PKCS #11 URI with object id and label to store the intermediate certificate.")
flag.StringVar(&c.CrtKeyObject, "crt-key-obj", "pkcs11:id=7331;object=intermediate-key", "PKCS #11 URI with object id and label to store the intermediate certificate.")
// SSH certificates
flag.BoolVar(&c.EnableSSH, "ssh", false, "Enable the creation of ssh keys.")
flag.StringVar(&c.SSHHostKeyObject, "ssh-host-key", "pkcs11:id=7332;object=ssh-host-key", "PKCS #11 URI with object id and label to store the key used to sign SSH host certificates.")
flag.StringVar(&c.SSHUserKeyObject, "ssh-user-key", "pkcs11:id=7333;object=ssh-user-key", "PKCS #11 URI with object id and label to store the key used to sign SSH user certificates.")
flag.BoolVar(&c.EnableSSH, "ssh", false, "Enable the creation of ssh keys.")
// Output files
flag.StringVar(&c.RootPath, "root-cert-path", "root_ca.crt", "Location to write the root certificate.")
flag.StringVar(&c.CrtPath, "crt-cert-path", "intermediate_ca.crt", "Location to write the intermediate certificate.")
flag.StringVar(&c.CrtKeyPath, "crt-key-path", "", "Location to write the intermediate private key.")
// Others
flag.BoolVar(&c.NoCerts, "no-certs", false, "Do not store certificates in the module.")
flag.BoolVar(&c.Force, "force", false, "Force the delete of previous keys.")
flag.BoolVar(&c.Extractable, "extractable", false, "Allow export of private keys under wrap.")
@ -319,7 +330,7 @@ func createPKI(k kms.KeyManager, c Config) error {
return errors.Wrap(err, "error parsing root certificate")
}
if cm, ok := k.(kms.CertificateManager); ok && !c.NoCerts {
if cm, ok := k.(kms.CertificateManager); ok && c.RootObject != "" && !c.NoCerts {
if err := cm.StoreCertificate(&apiv1.StoreCertificateRequest{
Name: c.RootObject,
Certificate: root,
@ -327,6 +338,8 @@ func createPKI(k kms.KeyManager, c Config) error {
}); err != nil {
return err
}
} else {
c.RootObject = ""
}
if err := fileutil.WriteFile(c.RootPath, pem.EncodeToMemory(&pem.Block{
@ -338,6 +351,9 @@ func createPKI(k kms.KeyManager, c Config) error {
ui.PrintSelected("Root Key", resp.Name)
ui.PrintSelected("Root Certificate", c.RootPath)
if c.RootObject != "" {
ui.PrintSelected("Root Certificate Object", c.RootObject)
}
case c.RootFile != "" && c.KeyFile != "": // Read Root From File
root, err = pemutil.ReadCertificate(c.RootFile)
if err != nil {
@ -421,7 +437,7 @@ func createPKI(k kms.KeyManager, c Config) error {
return errors.Wrap(err, "error parsing intermediate certificate")
}
if cm, ok := k.(kms.CertificateManager); ok && !c.NoCerts {
if cm, ok := k.(kms.CertificateManager); ok && c.CrtObject != "" && !c.NoCerts {
if err := cm.StoreCertificate(&apiv1.StoreCertificateRequest{
Name: c.CrtObject,
Certificate: intermediate,
@ -429,6 +445,8 @@ func createPKI(k kms.KeyManager, c Config) error {
}); err != nil {
return err
}
} else {
c.CrtObject = ""
}
if err := fileutil.WriteFile(c.CrtPath, pem.EncodeToMemory(&pem.Block{
@ -437,7 +455,8 @@ func createPKI(k kms.KeyManager, c Config) error {
}), 0600); err != nil {
return err
}
} else { // No root available, generate CSR for external root.
} else {
// No root available, generate CSR for external root.
csrTemplate := x509.CertificateRequest{
Subject: pkix.Name{CommonName: c.CrtSubject},
SignatureAlgorithm: x509.ECDSAWithSHA256,
@ -461,7 +480,14 @@ func createPKI(k kms.KeyManager, c Config) error {
ui.PrintSelected("Intermediate Key", keyName)
}
if root != nil {
ui.PrintSelected("Intermediate Certificate", c.CrtPath)
if c.CrtObject != "" {
ui.PrintSelected("Intermediate Certificate Object", c.CrtObject)
}
} else {
ui.PrintSelected("Intermediate Certificate Request", c.CrtPath)
}
if c.SSHHostKeyObject != "" {
resp, err := k.CreateKey(&apiv1.CreateKeyRequest{