Merge branch 'master' into herman/acme-da-subject-check

pull/1235/head
Herman Slatman 1 year ago
commit 7c632629dd
No known key found for this signature in database
GPG Key ID: F4D8A44EA0A75A4F

@ -27,6 +27,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
## [Unreleased]
### Removed
- The deprecated CLI utils `step-awskms-init`, `step-cloudkms-init`,
`step-pkcs11-init`, `step-yubikey-init` have been removed.
[`step`](https://github.com/smallstep/cli) and
[`step-kms-plugin`](https://github.com/smallstep/step-kms-plugin) should be
used instead.
## [v0.23.1] - 2022-01-10
### Added

@ -1,13 +1,5 @@
PKG?=github.com/smallstep/certificates/cmd/step-ca
BINNAME?=step-ca
CLOUDKMS_BINNAME?=step-cloudkms-init
CLOUDKMS_PKG?=github.com/smallstep/certificates/cmd/step-cloudkms-init
AWSKMS_BINNAME?=step-awskms-init
AWSKMS_PKG?=github.com/smallstep/certificates/cmd/step-awskms-init
YUBIKEY_BINNAME?=step-yubikey-init
YUBIKEY_PKG?=github.com/smallstep/certificates/cmd/step-yubikey-init
PKCS11_BINNAME?=step-pkcs11-init
PKCS11_PKG?=github.com/smallstep/certificates/cmd/step-pkcs11-init
# Set V to 1 for verbose output from the Makefile
Q=$(if $V,,@)
@ -90,29 +82,13 @@ GOFLAGS := CGO_ENABLED=0
download:
$Q go mod download
build: $(PREFIX)bin/$(BINNAME) $(PREFIX)bin/$(CLOUDKMS_BINNAME) $(PREFIX)bin/$(AWSKMS_BINNAME) $(PREFIX)bin/$(YUBIKEY_BINNAME) $(PREFIX)bin/$(PKCS11_BINNAME)
build: $(PREFIX)bin/$(BINNAME)
@echo "Build Complete!"
$(PREFIX)bin/$(BINNAME): download $(call rwildcard,*.go)
$Q mkdir -p $(@D)
$Q $(GOOS_OVERRIDE) $(GOFLAGS) go build -v -o $(PREFIX)bin/$(BINNAME) $(LDFLAGS) $(PKG)
$(PREFIX)bin/$(CLOUDKMS_BINNAME): download $(call rwildcard,*.go)
$Q mkdir -p $(@D)
$Q $(GOOS_OVERRIDE) $(GOFLAGS) go build -v -o $(PREFIX)bin/$(CLOUDKMS_BINNAME) $(LDFLAGS) $(CLOUDKMS_PKG)
$(PREFIX)bin/$(AWSKMS_BINNAME): download $(call rwildcard,*.go)
$Q mkdir -p $(@D)
$Q $(GOOS_OVERRIDE) $(GOFLAGS) go build -v -o $(PREFIX)bin/$(AWSKMS_BINNAME) $(LDFLAGS) $(AWSKMS_PKG)
$(PREFIX)bin/$(YUBIKEY_BINNAME): download $(call rwildcard,*.go)
$Q mkdir -p $(@D)
$Q $(GOOS_OVERRIDE) $(GOFLAGS) go build -v -o $(PREFIX)bin/$(YUBIKEY_BINNAME) $(LDFLAGS) $(YUBIKEY_PKG)
$(PREFIX)bin/$(PKCS11_BINNAME): download $(call rwildcard,*.go)
$Q mkdir -p $(@D)
$Q $(GOOS_OVERRIDE) $(GOFLAGS) go build -v -o $(PREFIX)bin/$(PKCS11_BINNAME) $(LDFLAGS) $(PKCS11_PKG)
# Target to force a build of step-ca without running tests
simple: build
@ -133,7 +109,6 @@ generate:
test:
$Q $(GOFLAGS) gotestsum -- -coverprofile=coverage.out -short -covermode=atomic ./...
testcgo:
$Q gotestsum -- -coverprofile=coverage.out -short -covermode=atomic ./...
@ -166,15 +141,11 @@ lint:
INSTALL_PREFIX?=/usr/
install: $(PREFIX)bin/$(BINNAME) $(PREFIX)bin/$(CLOUDKMS_BINNAME) $(PREFIX)bin/$(AWSKMS_BINNAME)
install: $(PREFIX)bin/$(BINNAME)
$Q install -D $(PREFIX)bin/$(BINNAME) $(DESTDIR)$(INSTALL_PREFIX)bin/$(BINNAME)
$Q install -D $(PREFIX)bin/$(CLOUDKMS_BINNAME) $(DESTDIR)$(INSTALL_PREFIX)bin/$(CLOUDKMS_BINNAME)
$Q install -D $(PREFIX)bin/$(AWSKMS_BINNAME) $(DESTDIR)$(INSTALL_PREFIX)bin/$(AWSKMS_BINNAME)
uninstall:
$Q rm -f $(DESTDIR)$(INSTALL_PREFIX)/bin/$(BINNAME)
$Q rm -f $(DESTDIR)$(INSTALL_PREFIX)/bin/$(CLOUDKMS_BINNAME)
$Q rm -f $(DESTDIR)$(INSTALL_PREFIX)/bin/$(AWSKMS_BINNAME)
.PHONY: install uninstall
@ -186,18 +157,6 @@ clean:
ifneq ($(BINNAME),"")
$Q rm -f bin/$(BINNAME)
endif
ifneq ($(CLOUDKMS_BINNAME),"")
$Q rm -f bin/$(CLOUDKMS_BINNAME)
endif
ifneq ($(AWSKMS_BINNAME),"")
$Q rm -f bin/$(AWSKMS_BINNAME)
endif
ifneq ($(YUBIKEY_BINNAME),"")
$Q rm -f bin/$(YUBIKEY_BINNAME)
endif
ifneq ($(PKCS11_BINNAME),"")
$Q rm -f bin/$(PKCS11_BINNAME)
endif
.PHONY: clean

@ -1,248 +0,0 @@
package main
import (
"context"
"crypto"
"crypto/rand"
"crypto/sha1" //nolint:gosec // used to create the Subject Key Identifier by RFC 5280
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"flag"
"fmt"
"math/big"
"os"
"time"
"go.step.sm/cli-utils/fileutil"
"go.step.sm/cli-utils/ui"
"go.step.sm/crypto/kms/apiv1"
"go.step.sm/crypto/kms/awskms"
"go.step.sm/crypto/pemutil"
"golang.org/x/crypto/ssh"
)
func main() {
var credentialsFile, region string
var enableSSH bool
flag.StringVar(&credentialsFile, "credentials-file", "", "Path to the `file` containing the AWS KMS credentials.")
flag.StringVar(&region, "region", "", "AWS KMS region name.")
flag.BoolVar(&enableSSH, "ssh", false, "Create SSH keys.")
flag.Usage = usage
flag.Parse()
// Initialize windows terminal
ui.Init()
ui.Println("⚠️ This command is deprecated and will be removed in future releases.")
ui.Println("⚠️ Please use https://github.com/smallstep/step-kms-plugin instead.")
c, err := awskms.New(context.Background(), apiv1.Options{
Type: apiv1.AmazonKMS,
Region: region,
CredentialsFile: credentialsFile,
})
if err != nil {
fatal(err)
}
if err := createX509(c); err != nil {
fatal(err)
}
if enableSSH {
ui.Println()
if err := createSSH(c); err != nil {
fatal(err)
}
}
// Reset windows terminal
ui.Reset()
}
func fatal(err error) {
fmt.Fprintln(os.Stderr, err)
ui.Reset()
os.Exit(1)
}
func usage() {
fmt.Fprintln(os.Stderr, "Usage: step-awskms-init")
fmt.Fprintln(os.Stderr, `
The step-awskms-init command initializes a public key infrastructure (PKI)
to be used by step-ca.
This tool is experimental and in the future it will be integrated in step cli.
OPTIONS`)
fmt.Fprintln(os.Stderr)
flag.PrintDefaults()
fmt.Fprintf(os.Stderr, `
COPYRIGHT
(c) 2018-%d Smallstep Labs, Inc.
`, time.Now().Year())
os.Exit(1)
}
func createX509(c *awskms.KMS) error {
ui.Println("Creating X.509 PKI ...")
// Root Certificate
resp, err := c.CreateKey(&apiv1.CreateKeyRequest{
Name: "root",
SignatureAlgorithm: apiv1.ECDSAWithSHA256,
})
if err != nil {
return err
}
signer, err := c.CreateSigner(&resp.CreateSignerRequest)
if err != nil {
return err
}
now := time.Now()
root := &x509.Certificate{
IsCA: true,
NotBefore: now,
NotAfter: now.Add(time.Hour * 24 * 365 * 10),
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
BasicConstraintsValid: true,
MaxPathLen: 1,
MaxPathLenZero: false,
Issuer: pkix.Name{CommonName: "Smallstep Root"},
Subject: pkix.Name{CommonName: "Smallstep Root"},
SerialNumber: mustSerialNumber(),
SubjectKeyId: mustSubjectKeyID(resp.PublicKey),
AuthorityKeyId: mustSubjectKeyID(resp.PublicKey),
}
b, err := x509.CreateCertificate(rand.Reader, root, root, resp.PublicKey, signer)
if err != nil {
return err
}
if err := fileutil.WriteFile("root_ca.crt", pem.EncodeToMemory(&pem.Block{
Type: "CERTIFICATE",
Bytes: b,
}), 0600); err != nil {
return err
}
ui.PrintSelected("Root Key", resp.Name)
ui.PrintSelected("Root Certificate", "root_ca.crt")
root, err = pemutil.ReadCertificate("root_ca.crt")
if err != nil {
return err
}
// Intermediate Certificate
resp, err = c.CreateKey(&apiv1.CreateKeyRequest{
Name: "intermediate",
SignatureAlgorithm: apiv1.ECDSAWithSHA256,
})
if err != nil {
return err
}
intermediate := &x509.Certificate{
IsCA: true,
NotBefore: now,
NotAfter: now.Add(time.Hour * 24 * 365 * 10),
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
BasicConstraintsValid: true,
MaxPathLen: 0,
MaxPathLenZero: true,
Issuer: root.Subject,
Subject: pkix.Name{CommonName: "Smallstep Intermediate"},
SerialNumber: mustSerialNumber(),
SubjectKeyId: mustSubjectKeyID(resp.PublicKey),
}
b, err = x509.CreateCertificate(rand.Reader, intermediate, root, resp.PublicKey, signer)
if err != nil {
return err
}
if err := fileutil.WriteFile("intermediate_ca.crt", pem.EncodeToMemory(&pem.Block{
Type: "CERTIFICATE",
Bytes: b,
}), 0600); err != nil {
return err
}
ui.PrintSelected("Intermediate Key", resp.Name)
ui.PrintSelected("Intermediate Certificate", "intermediate_ca.crt")
return nil
}
func createSSH(c *awskms.KMS) error {
ui.Println("Creating SSH Keys ...")
// User Key
resp, err := c.CreateKey(&apiv1.CreateKeyRequest{
Name: "ssh-user-key",
SignatureAlgorithm: apiv1.ECDSAWithSHA256,
})
if err != nil {
return err
}
key, err := ssh.NewPublicKey(resp.PublicKey)
if err != nil {
return err
}
if err := fileutil.WriteFile("ssh_user_ca_key.pub", ssh.MarshalAuthorizedKey(key), 0600); err != nil {
return err
}
ui.PrintSelected("SSH User Public Key", "ssh_user_ca_key.pub")
ui.PrintSelected("SSH User Private Key", resp.Name)
// Host Key
resp, err = c.CreateKey(&apiv1.CreateKeyRequest{
Name: "ssh-host-key",
SignatureAlgorithm: apiv1.ECDSAWithSHA256,
})
if err != nil {
return err
}
key, err = ssh.NewPublicKey(resp.PublicKey)
if err != nil {
return err
}
if err := fileutil.WriteFile("ssh_host_ca_key.pub", ssh.MarshalAuthorizedKey(key), 0600); err != nil {
return err
}
ui.PrintSelected("SSH Host Public Key", "ssh_host_ca_key.pub")
ui.PrintSelected("SSH Host Private Key", resp.Name)
return nil
}
func mustSerialNumber() *big.Int {
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
sn, err := rand.Int(rand.Reader, serialNumberLimit)
if err != nil {
panic(err)
}
return sn
}
func mustSubjectKeyID(key crypto.PublicKey) []byte {
b, err := x509.MarshalPKIXPublicKey(key)
if err != nil {
panic(err)
}
//nolint:gosec // used to create the Subject Key Identifier by RFC 5280
hash := sha1.Sum(b)
return hash[:]
}

@ -1,286 +0,0 @@
package main
import (
"context"
"crypto"
"crypto/rand"
"crypto/sha1" //nolint:gosec // used to create the Subject Key Identifier by RFC 5280
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"flag"
"fmt"
"math/big"
"os"
"strings"
"time"
"go.step.sm/cli-utils/fileutil"
"go.step.sm/cli-utils/ui"
"go.step.sm/crypto/kms/apiv1"
"go.step.sm/crypto/kms/cloudkms"
"go.step.sm/crypto/pemutil"
"golang.org/x/crypto/ssh"
)
func main() {
var credentialsFile string
var project, location, ring string
var protectionLevelName string
var enableSSH bool
flag.StringVar(&credentialsFile, "credentials-file", "", "Path to the `file` containing the Google's Cloud KMS credentials.")
flag.StringVar(&project, "project", "", "Google Cloud Project ID.")
flag.StringVar(&location, "location", "global", "Cloud KMS location name.")
flag.StringVar(&ring, "ring", "pki", "Cloud KMS ring name.")
flag.StringVar(&protectionLevelName, "protection-level", "SOFTWARE", "Protection level to use, SOFTWARE or HSM.")
flag.BoolVar(&enableSSH, "ssh", false, "Create SSH keys.")
flag.Usage = usage
flag.Parse()
switch {
case project == "":
usage()
case location == "":
fmt.Fprintln(os.Stderr, "flag `--location` is required")
os.Exit(1)
case ring == "":
fmt.Fprintln(os.Stderr, "flag `--ring` is required")
os.Exit(1)
case protectionLevelName == "":
fmt.Fprintln(os.Stderr, "flag `--protection-level` is required")
os.Exit(1)
}
var protectionLevel apiv1.ProtectionLevel
switch strings.ToUpper(protectionLevelName) {
case "SOFTWARE":
protectionLevel = apiv1.Software
case "HSM":
protectionLevel = apiv1.HSM
default:
fmt.Fprintf(os.Stderr, "invalid value `%s` for flag `--protection-level`; options are `SOFTWARE` or `HSM`\n", protectionLevelName)
os.Exit(1)
}
// Initialize windows terminal
ui.Init()
ui.Println("⚠️ This command is deprecated and will be removed in future releases.")
ui.Println("⚠️ Please use https://github.com/smallstep/step-kms-plugin instead.")
c, err := cloudkms.New(context.Background(), apiv1.Options{
Type: apiv1.CloudKMS,
CredentialsFile: credentialsFile,
})
if err != nil {
fatal(err)
}
if err := createPKI(c, project, location, ring, protectionLevel); err != nil {
fatal(err)
}
if enableSSH {
ui.Println()
if err := createSSH(c, project, location, ring, protectionLevel); err != nil {
fatal(err)
}
}
// Reset windows terminal
ui.Reset()
}
func fatal(err error) {
fmt.Fprintln(os.Stderr, err)
ui.Reset()
os.Exit(1)
}
func usage() {
fmt.Fprintln(os.Stderr, "Usage: step-cloudkms-init --project <name>")
fmt.Fprintln(os.Stderr, `
The step-cloudkms-init command initializes a public key infrastructure (PKI)
to be used by step-ca.
This tool is experimental and in the future it will be integrated in step cli.
OPTIONS`)
fmt.Fprintln(os.Stderr)
flag.PrintDefaults()
fmt.Fprintf(os.Stderr, `
COPYRIGHT
(c) 2018-%d Smallstep Labs, Inc.
`, time.Now().Year())
os.Exit(1)
}
func createPKI(c *cloudkms.CloudKMS, project, location, keyRing string, protectionLevel apiv1.ProtectionLevel) error {
ui.Println("Creating PKI ...")
parent := "projects/" + project + "/locations/" + location + "/keyRings/" + keyRing + "/cryptoKeys"
// Root Certificate
resp, err := c.CreateKey(&apiv1.CreateKeyRequest{
Name: parent + "/root",
SignatureAlgorithm: apiv1.ECDSAWithSHA256,
ProtectionLevel: protectionLevel,
})
if err != nil {
return err
}
signer, err := c.CreateSigner(&resp.CreateSignerRequest)
if err != nil {
return err
}
now := time.Now()
root := &x509.Certificate{
IsCA: true,
NotBefore: now,
NotAfter: now.Add(time.Hour * 24 * 365 * 10),
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
BasicConstraintsValid: true,
MaxPathLen: 1,
MaxPathLenZero: false,
Issuer: pkix.Name{CommonName: "Smallstep Root"},
Subject: pkix.Name{CommonName: "Smallstep Root"},
SerialNumber: mustSerialNumber(),
SubjectKeyId: mustSubjectKeyID(resp.PublicKey),
AuthorityKeyId: mustSubjectKeyID(resp.PublicKey),
}
b, err := x509.CreateCertificate(rand.Reader, root, root, resp.PublicKey, signer)
if err != nil {
return err
}
if err := fileutil.WriteFile("root_ca.crt", pem.EncodeToMemory(&pem.Block{
Type: "CERTIFICATE",
Bytes: b,
}), 0600); err != nil {
return err
}
ui.PrintSelected("Root Key", resp.Name)
ui.PrintSelected("Root Certificate", "root_ca.crt")
root, err = pemutil.ReadCertificate("root_ca.crt")
if err != nil {
return err
}
// Intermediate Certificate
resp, err = c.CreateKey(&apiv1.CreateKeyRequest{
Name: parent + "/intermediate",
SignatureAlgorithm: apiv1.ECDSAWithSHA256,
ProtectionLevel: protectionLevel,
})
if err != nil {
return err
}
intermediate := &x509.Certificate{
IsCA: true,
NotBefore: now,
NotAfter: now.Add(time.Hour * 24 * 365 * 10),
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
BasicConstraintsValid: true,
MaxPathLen: 0,
MaxPathLenZero: true,
Issuer: root.Subject,
Subject: pkix.Name{CommonName: "Smallstep Intermediate"},
SerialNumber: mustSerialNumber(),
SubjectKeyId: mustSubjectKeyID(resp.PublicKey),
}
b, err = x509.CreateCertificate(rand.Reader, intermediate, root, resp.PublicKey, signer)
if err != nil {
return err
}
if err := fileutil.WriteFile("intermediate_ca.crt", pem.EncodeToMemory(&pem.Block{
Type: "CERTIFICATE",
Bytes: b,
}), 0600); err != nil {
return err
}
ui.PrintSelected("Intermediate Key", resp.Name)
ui.PrintSelected("Intermediate Certificate", "intermediate_ca.crt")
return nil
}
func createSSH(c *cloudkms.CloudKMS, project, location, keyRing string, protectionLevel apiv1.ProtectionLevel) error {
ui.Println("Creating SSH Keys ...")
parent := "projects/" + project + "/locations/" + location + "/keyRings/" + keyRing + "/cryptoKeys"
// User Key
resp, err := c.CreateKey(&apiv1.CreateKeyRequest{
Name: parent + "/ssh-user-key",
SignatureAlgorithm: apiv1.ECDSAWithSHA256,
ProtectionLevel: protectionLevel,
})
if err != nil {
return err
}
key, err := ssh.NewPublicKey(resp.PublicKey)
if err != nil {
return err
}
if err := fileutil.WriteFile("ssh_user_ca_key.pub", ssh.MarshalAuthorizedKey(key), 0600); err != nil {
return err
}
ui.PrintSelected("SSH User Public Key", "ssh_user_ca_key.pub")
ui.PrintSelected("SSH User Private Key", resp.Name)
// Host Key
resp, err = c.CreateKey(&apiv1.CreateKeyRequest{
Name: parent + "/ssh-host-key",
SignatureAlgorithm: apiv1.ECDSAWithSHA256,
ProtectionLevel: protectionLevel,
})
if err != nil {
return err
}
key, err = ssh.NewPublicKey(resp.PublicKey)
if err != nil {
return err
}
if err := fileutil.WriteFile("ssh_host_ca_key.pub", ssh.MarshalAuthorizedKey(key), 0600); err != nil {
return err
}
ui.PrintSelected("SSH Host Public Key", "ssh_host_ca_key.pub")
ui.PrintSelected("SSH Host Private Key", resp.Name)
return nil
}
func mustSerialNumber() *big.Int {
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
sn, err := rand.Int(rand.Reader, serialNumberLimit)
if err != nil {
panic(err)
}
return sn
}
func mustSubjectKeyID(key crypto.PublicKey) []byte {
b, err := x509.MarshalPKIXPublicKey(key)
if err != nil {
panic(err)
}
//nolint:gosec // used to create the Subject Key Identifier by RFC 5280
hash := sha1.Sum(b)
return hash[:]
}

@ -1,553 +0,0 @@
package main
import (
"context"
"crypto"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/sha1" //nolint:gosec // used to create the Subject Key Identifier by RFC 5280
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"flag"
"fmt"
"math/big"
"os"
"runtime"
"time"
"github.com/pkg/errors"
"go.step.sm/cli-utils/fileutil"
"go.step.sm/cli-utils/ui"
"go.step.sm/crypto/kms"
"go.step.sm/crypto/kms/apiv1"
"go.step.sm/crypto/kms/uri"
"go.step.sm/crypto/pemutil"
// Enable pkcs11.
_ "go.step.sm/crypto/kms/pkcs11"
)
// Config is a mapping of the cli flags.
type Config struct {
KMS string
GenerateRoot bool
RootObject string
RootKeyObject string
RootSubject string
RootPath string
CrtObject string
CrtPath string
CrtKeyObject string
CrtSubject string
CrtKeyPath string
SSHHostKeyObject string
SSHUserKeyObject string
RootFile string
KeyFile string
Pin string
PinFile string
NoCerts bool
EnableSSH bool
Force bool
Extractable bool
}
// Validate checks the flags in the config.
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 `--root-key-file`")
case c.KeyFile != "" && c.RootFile == "":
return errors.New("flag `--root-key-file` requires flag `--root-cert-file`")
case c.RootFile == "" && c.RootObject == "":
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`")
case c.Pin != "" && c.PinFile != "":
return errors.New("Only set one of pin and pin-file")
default:
if c.RootFile != "" {
c.GenerateRoot = false
c.RootObject = ""
c.RootKeyObject = ""
}
if c.CrtKeyPath != "" {
c.CrtObject = ""
c.CrtKeyObject = ""
}
if !c.EnableSSH {
c.SSHHostKeyObject = ""
c.SSHUserKeyObject = ""
}
return nil
}
}
func main() {
var kmsuri string
switch runtime.GOOS {
case "darwin":
kmsuri = "pkcs11:module-path=/usr/local/lib/pkcs11/yubihsm_pkcs11.dylib;token=YubiHSM"
case "linux":
kmsuri = "pkcs11:module-path=/usr/lib/x86_64-linux-gnu/pkcs11/yubihsm_pkcs11.so;token=YubiHSM"
case "windows":
if home, err := os.UserHomeDir(); err == nil {
kmsuri = "pkcs11:module-path=" + home + "\\yubihsm2-sdk\\bin\\yubihsm_pkcs11.dll" + ";token=YubiHSM"
}
}
var c Config
flag.StringVar(&c.KMS, "kms", kmsuri, "PKCS #11 URI with the module-path and token to connect to the module.")
flag.StringVar(&c.Pin, "pin", "", "PKCS #11 PIN")
flag.StringVar(&c.PinFile, "pin-file", "", "PKCS #11 PIN File")
// Option 1: Generate new root
flag.BoolVar(&c.GenerateRoot, "root-gen", true, "Enable the generation of a root key.")
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.")
// Option 2: Read root from disk and sign intermediate
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.CrtSubject, "crt-name", "PKCS #11 Smallstep Intermediate", "Subject of the intermediate certificate.")
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.")
// 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.")
flag.Usage = usage
flag.Parse()
if err := c.Validate(); err != nil {
fatal(err)
}
u, err := uri.ParseWithScheme("pkcs11", c.KMS)
if err != nil {
fatal(err)
}
// Initialize windows terminal
ui.Init()
ui.Println("⚠️ This command is deprecated and will be removed in future releases.")
ui.Println("⚠️ Please use https://github.com/smallstep/step-kms-plugin instead.")
switch {
case u.Get("pin-value") != "":
case u.Get("pin-source") != "":
case c.Pin != "":
case c.PinFile != "":
content, err := os.ReadFile(c.PinFile)
if err != nil {
fatal(err)
}
c.Pin = string(content)
default:
pin, err := ui.PromptPassword("What is the PKCS#11 PIN?")
if err != nil {
fatal(err)
}
c.Pin = string(pin)
}
k, err := kms.New(context.Background(), apiv1.Options{
Type: apiv1.PKCS11,
URI: c.KMS,
Pin: c.Pin,
})
if err != nil {
fatal(err)
}
defer func() {
_ = k.Close()
}()
// Check if the slots are empty, fail if they are not
certUris := []string{
c.RootObject, c.CrtObject,
}
keyUris := []string{
c.RootKeyObject, c.CrtKeyObject,
c.SSHHostKeyObject, c.SSHUserKeyObject,
}
if !c.Force {
for _, u := range certUris {
if u != "" && !c.NoCerts {
checkObject(k, u)
checkCertificate(k, u)
}
}
for _, u := range keyUris {
if u != "" {
checkObject(k, u)
}
}
} else {
deleter, ok := k.(interface {
DeleteKey(uri string) error
DeleteCertificate(uri string) error
})
if ok {
for _, u := range certUris {
if u != "" && !c.NoCerts {
// Some HSMs like Nitrokey will overwrite the key with the
// certificate label.
if err := deleter.DeleteKey(u); err != nil {
fatalClose(err, k)
}
if err := deleter.DeleteCertificate(u); err != nil {
fatalClose(err, k)
}
}
}
for _, u := range keyUris {
if u != "" {
if err := deleter.DeleteKey(u); err != nil {
fatalClose(err, k)
}
}
}
}
}
if err := createPKI(k, c); err != nil {
fatalClose(err, k)
}
// Reset windows terminal
ui.Reset()
}
func fatal(err error) {
if os.Getenv("STEPDEBUG") == "1" {
fmt.Fprintf(os.Stderr, "%+v\n", err)
} else {
fmt.Fprintln(os.Stderr, err)
}
ui.Reset()
os.Exit(1)
}
func fatalClose(err error, k kms.KeyManager) {
_ = k.Close()
fatal(err)
}
func usage() {
fmt.Fprintln(os.Stderr, "Usage: step-pkcs11-init")
fmt.Fprintln(os.Stderr, `
The step-pkcs11-init command initializes a public key infrastructure (PKI)
to be used by step-ca.
This tool is experimental and in the future it will be integrated in step cli.
OPTIONS`)
fmt.Fprintln(os.Stderr)
flag.PrintDefaults()
fmt.Fprintf(os.Stderr, `
COPYRIGHT
(c) 2018-%d Smallstep Labs, Inc.
`, time.Now().Year())
os.Exit(1)
}
func checkCertificate(k kms.KeyManager, rawuri string) {
if cm, ok := k.(kms.CertificateManager); ok {
if _, err := cm.LoadCertificate(&apiv1.LoadCertificateRequest{
Name: rawuri,
}); err == nil {
fmt.Fprintf(os.Stderr, "⚠️ Your PKCS #11 module already has a certificate on %s.\n", rawuri)
fmt.Fprintln(os.Stderr, " If you want to delete it and start fresh, use `--force`.")
_ = k.Close()
os.Exit(1)
}
}
}
func checkObject(k kms.KeyManager, rawuri string) {
if _, err := k.GetPublicKey(&apiv1.GetPublicKeyRequest{
Name: rawuri,
}); err == nil {
fmt.Fprintf(os.Stderr, "⚠️ Your PKCS #11 module already has a key on %s.\n", rawuri)
fmt.Fprintln(os.Stderr, " If you want to delete it and start fresh, use `--force`.")
_ = k.Close()
os.Exit(1)
}
}
func createPKI(k kms.KeyManager, c Config) error {
var err error
ui.Println("Creating PKI ...")
now := time.Now()
// Root Certificate
var signer crypto.Signer
var root *x509.Certificate
switch {
case c.GenerateRoot:
resp, err := k.CreateKey(&apiv1.CreateKeyRequest{
Name: c.RootKeyObject,
SignatureAlgorithm: apiv1.ECDSAWithSHA256,
Extractable: c.Extractable,
})
if err != nil {
return err
}
signer, err = k.CreateSigner(&resp.CreateSignerRequest)
if err != nil {
return err
}
template := &x509.Certificate{
IsCA: true,
NotBefore: now,
NotAfter: now.Add(time.Hour * 24 * 365 * 10),
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
BasicConstraintsValid: true,
MaxPathLen: 1,
MaxPathLenZero: false,
Issuer: pkix.Name{CommonName: c.RootSubject},
Subject: pkix.Name{CommonName: c.RootSubject},
SerialNumber: mustSerialNumber(),
SubjectKeyId: mustSubjectKeyID(resp.PublicKey),
AuthorityKeyId: mustSubjectKeyID(resp.PublicKey),
}
b, err := x509.CreateCertificate(rand.Reader, template, template, resp.PublicKey, signer)
if err != nil {
return err
}
root, err = x509.ParseCertificate(b)
if err != nil {
return errors.Wrap(err, "error parsing root certificate")
}
if cm, ok := k.(kms.CertificateManager); ok && c.RootObject != "" && !c.NoCerts {
if err := cm.StoreCertificate(&apiv1.StoreCertificateRequest{
Name: c.RootObject,
Certificate: root,
Extractable: c.Extractable,
}); err != nil {
return err
}
} else {
c.RootObject = ""
}
if err := fileutil.WriteFile(c.RootPath, pem.EncodeToMemory(&pem.Block{
Type: "CERTIFICATE",
Bytes: b,
}), 0600); err != nil {
return err
}
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 {
return err
}
key, err := pemutil.Read(c.KeyFile)
if err != nil {
return err
}
var ok bool
if signer, ok = key.(crypto.Signer); !ok {
return errors.Errorf("key type '%T' does not implement a signer", key)
}
}
// Intermediate Certificate
var keyName string
var publicKey crypto.PublicKey
var intSigner crypto.Signer
if c.CrtKeyPath != "" {
priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
return errors.Wrap(err, "error creating intermediate key")
}
pass, err := ui.PromptPasswordGenerate("What do you want your password to be? [leave empty and we'll generate one]",
ui.WithRichPrompt())
if err != nil {
return err
}
_, err = pemutil.Serialize(priv, pemutil.WithPassword(pass), pemutil.ToFile(c.CrtKeyPath, 0600))
if err != nil {
return err
}
publicKey = priv.Public()
intSigner = priv
} else {
resp, err := k.CreateKey(&apiv1.CreateKeyRequest{
Name: c.CrtKeyObject,
SignatureAlgorithm: apiv1.ECDSAWithSHA256,
Extractable: c.Extractable,
})
if err != nil {
return err
}
publicKey = resp.PublicKey
keyName = resp.Name
intSigner, err = k.CreateSigner(&resp.CreateSignerRequest)
if err != nil {
return err
}
}
if root != nil {
template := &x509.Certificate{
IsCA: true,
NotBefore: now,
NotAfter: now.Add(time.Hour * 24 * 365 * 10),
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
BasicConstraintsValid: true,
MaxPathLen: 0,
MaxPathLenZero: true,
Issuer: root.Subject,
Subject: pkix.Name{CommonName: c.CrtSubject},
SerialNumber: mustSerialNumber(),
SubjectKeyId: mustSubjectKeyID(publicKey),
}
b, err := x509.CreateCertificate(rand.Reader, template, root, publicKey, signer)
if err != nil {
return err
}
intermediate, err := x509.ParseCertificate(b)
if err != nil {
return errors.Wrap(err, "error parsing intermediate certificate")
}
if cm, ok := k.(kms.CertificateManager); ok && c.CrtObject != "" && !c.NoCerts {
if err := cm.StoreCertificate(&apiv1.StoreCertificateRequest{
Name: c.CrtObject,
Certificate: intermediate,
Extractable: c.Extractable,
}); err != nil {
return err
}
} else {
c.CrtObject = ""
}
if err := fileutil.WriteFile(c.CrtPath, pem.EncodeToMemory(&pem.Block{
Type: "CERTIFICATE",
Bytes: b,
}), 0600); err != nil {
return err
}
} else {
// No root available, generate CSR for external root.
csrTemplate := x509.CertificateRequest{
Subject: pkix.Name{CommonName: c.CrtSubject},
SignatureAlgorithm: x509.ECDSAWithSHA256,
}
// step: generate the csr request
csrCertificate, err := x509.CreateCertificateRequest(rand.Reader, &csrTemplate, intSigner)
if err != nil {
return err
}
if err := fileutil.WriteFile(c.CrtPath, pem.EncodeToMemory(&pem.Block{
Type: "CERTIFICATE REQUEST",
Bytes: csrCertificate,
}), 0600); err != nil {
return err
}
}
if c.CrtKeyPath != "" {
ui.PrintSelected("Intermediate Key", c.CrtKeyPath)
} else {
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{
Name: c.SSHHostKeyObject,
SignatureAlgorithm: apiv1.ECDSAWithSHA256,
})
if err != nil {
return err
}
ui.PrintSelected("SSH Host Key", resp.Name)
}
if c.SSHUserKeyObject != "" {
resp, err := k.CreateKey(&apiv1.CreateKeyRequest{
Name: c.SSHUserKeyObject,
SignatureAlgorithm: apiv1.ECDSAWithSHA256,
})
if err != nil {
return err
}
ui.PrintSelected("SSH User Key", resp.Name)
}
return nil
}
func mustSerialNumber() *big.Int {
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
sn, err := rand.Int(rand.Reader, serialNumberLimit)
if err != nil {
panic(err)
}
return sn
}
func mustSubjectKeyID(key crypto.PublicKey) []byte {
b, err := x509.MarshalPKIXPublicKey(key)
if err != nil {
panic(err)
}
//nolint:gosec // used to create the Subject Key Identifier by RFC 5280
hash := sha1.Sum(b)
return hash[:]
}

@ -1,355 +0,0 @@
package main
import (
"context"
"crypto"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/sha1" //nolint:gosec // used to create the Subject Key Identifier by RFC 5280
"crypto/x509"
"crypto/x509/pkix"
"encoding/hex"
"encoding/pem"
"flag"
"fmt"
"math/big"
"os"
"time"
"github.com/pkg/errors"
"go.step.sm/cli-utils/fileutil"
"go.step.sm/cli-utils/ui"
"go.step.sm/crypto/kms"
"go.step.sm/crypto/kms/apiv1"
"go.step.sm/crypto/pemutil"
// Enable yubikey.
_ "go.step.sm/crypto/kms/yubikey"
)
// Config is a mapping of the cli flags.
type Config struct {
RootOnly bool
RootSlot string
CrtSlot string
RootFile string
KeyFile string
Pin string
ManagementKey string
Force bool
}
// Validate checks the flags in the config.
func (c *Config) Validate() error {
switch {
case c.ManagementKey != "" && len(c.ManagementKey) != 48:
return errors.New("flag `--management-key` must be 48 hexadecimal characters (24 bytes)")
case c.RootFile != "" && c.KeyFile == "":
return errors.New("flag `--root` requires flag `--key`")
case c.KeyFile != "" && c.RootFile == "":
return errors.New("flag `--key` requires flag `--root`")
case c.RootOnly && c.RootFile != "":
return errors.New("flag `--root-only` is incompatible with flag `--root`")
case c.RootSlot == c.CrtSlot:
return errors.New("flag `--root-slot` and flag `--crt-slot` cannot be the same")
case c.RootFile == "" && c.RootSlot == "":
return errors.New("one of flag `--root` or `--root-slot` is required")
default:
if c.RootFile != "" {
c.RootSlot = ""
}
if c.RootOnly {
c.CrtSlot = ""
}
if c.ManagementKey != "" {
if _, err := hex.DecodeString(c.ManagementKey); err != nil {
return errors.Wrap(err, "flag `--management-key` is not valid")
}
}
return nil
}
}
func main() {
var c Config
flag.StringVar(&c.ManagementKey, "management-key", "", `Management key to use in hexadecimal format. (default "010203040506070801020304050607080102030405060708")`)
flag.BoolVar(&c.RootOnly, "root-only", false, "Slot only the root certificate and sign and intermediate.")
flag.StringVar(&c.RootSlot, "root-slot", "9a", "Slot to store the root certificate.")
flag.StringVar(&c.CrtSlot, "crt-slot", "9c", "Slot to store the intermediate certificate.")
flag.StringVar(&c.RootFile, "root", "", "Path to the root certificate to use.")
flag.StringVar(&c.KeyFile, "key", "", "Path to the root key to use.")
flag.BoolVar(&c.Force, "force", false, "Force the delete of previous keys.")
flag.Usage = usage
flag.Parse()
if err := c.Validate(); err != nil {
fatal(err)
}
// Initialize windows terminal
ui.Init()
ui.Println("⚠️ This command is deprecated and will be removed in future releases.")
ui.Println("⚠️ Please use https://github.com/smallstep/step-kms-plugin instead.")
pin, err := ui.PromptPassword("What is the YubiKey PIN?")
if err != nil {
fatal(err)
}
c.Pin = string(pin)
k, err := kms.New(context.Background(), apiv1.Options{
Type: apiv1.YubiKey,
Pin: c.Pin,
ManagementKey: c.ManagementKey,
})
if err != nil {
fatal(err)
}
// Check if the slots are empty, fail if they are not
if !c.Force {
switch {
case c.RootSlot != "":
checkSlot(k, c.RootSlot)
case c.CrtSlot != "":
checkSlot(k, c.CrtSlot)
}
}
if err := createPKI(k, c); err != nil {
fatal(err)
}
defer func() {
_ = k.Close()
}()
// Reset windows terminal
ui.Reset()
}
func fatal(err error) {
if os.Getenv("STEPDEBUG") == "1" {
fmt.Fprintf(os.Stderr, "%+v\n", err)
} else {
fmt.Fprintln(os.Stderr, err)
}
ui.Reset()
os.Exit(1)
}
func usage() {
fmt.Fprintln(os.Stderr, "Usage: step-yubikey-init")
fmt.Fprintln(os.Stderr, `
The step-yubikey-init command initializes a public key infrastructure (PKI)
to be used by step-ca.
This tool is experimental and in the future it will be integrated in step cli.
OPTIONS`)
fmt.Fprintln(os.Stderr)
flag.PrintDefaults()
fmt.Fprintf(os.Stderr, `
COPYRIGHT
(c) 2018-%d Smallstep Labs, Inc.
`, time.Now().Year())
os.Exit(1)
}
func checkSlot(k kms.KeyManager, slot string) {
if _, err := k.GetPublicKey(&apiv1.GetPublicKeyRequest{
Name: slot,
}); err == nil {
fmt.Fprintf(os.Stderr, "⚠️ Your YubiKey already has a key in the slot %s.\n", slot)
fmt.Fprintln(os.Stderr, " If you want to delete it and start fresh, use `--force`.")
os.Exit(1)
}
}
func createPKI(k kms.KeyManager, c Config) error {
var err error
ui.Println("Creating PKI ...")
now := time.Now()
// Root Certificate
var signer crypto.Signer
var root *x509.Certificate
if c.RootFile != "" && c.KeyFile != "" {
root, err = pemutil.ReadCertificate(c.RootFile)
if err != nil {
return err
}
key, err := pemutil.Read(c.KeyFile)
if err != nil {
return err
}
var ok bool
if signer, ok = key.(crypto.Signer); !ok {
return errors.Errorf("key type '%T' does not implement a signer", key)
}
} else {
resp, err := k.CreateKey(&apiv1.CreateKeyRequest{
Name: c.RootSlot,
SignatureAlgorithm: apiv1.ECDSAWithSHA256,
})
if err != nil {
return err
}
signer, err = k.CreateSigner(&resp.CreateSignerRequest)
if err != nil {
return err
}
template := &x509.Certificate{
IsCA: true,
NotBefore: now,
NotAfter: now.Add(time.Hour * 24 * 365 * 10),
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
BasicConstraintsValid: true,
MaxPathLen: 1,
MaxPathLenZero: false,
Issuer: pkix.Name{CommonName: "YubiKey Smallstep Root"},
Subject: pkix.Name{CommonName: "YubiKey Smallstep Root"},
SerialNumber: mustSerialNumber(),
SubjectKeyId: mustSubjectKeyID(resp.PublicKey),
AuthorityKeyId: mustSubjectKeyID(resp.PublicKey),
}
b, err := x509.CreateCertificate(rand.Reader, template, template, resp.PublicKey, signer)
if err != nil {
return err
}
root, err = x509.ParseCertificate(b)
if err != nil {
return errors.Wrap(err, "error parsing root certificate")
}
if cm, ok := k.(kms.CertificateManager); ok {
if err := cm.StoreCertificate(&apiv1.StoreCertificateRequest{
Name: c.RootSlot,
Certificate: root,
}); err != nil {
return err
}
}
if err := fileutil.WriteFile("root_ca.crt", pem.EncodeToMemory(&pem.Block{
Type: "CERTIFICATE",
Bytes: b,
}), 0600); err != nil {
return err
}
ui.PrintSelected("Root Key", resp.Name)
ui.PrintSelected("Root Certificate", "root_ca.crt")
}
// Intermediate Certificate
var keyName string
var publicKey crypto.PublicKey
if c.RootOnly {
priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
return errors.Wrap(err, "error creating intermediate key")
}
pass, err := ui.PromptPasswordGenerate("What do you want your password to be? [leave empty and we'll generate one]",
ui.WithRichPrompt())
if err != nil {
return err
}
_, err = pemutil.Serialize(priv, pemutil.WithPassword(pass), pemutil.ToFile("intermediate_ca_key", 0600))
if err != nil {
return err
}
publicKey = priv.Public()
} else {
resp, err := k.CreateKey(&apiv1.CreateKeyRequest{
Name: c.CrtSlot,
SignatureAlgorithm: apiv1.ECDSAWithSHA256,
})
if err != nil {
return err
}
publicKey = resp.PublicKey
keyName = resp.Name
}
template := &x509.Certificate{
IsCA: true,
NotBefore: now,
NotAfter: now.Add(time.Hour * 24 * 365 * 10),
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
BasicConstraintsValid: true,
MaxPathLen: 0,
MaxPathLenZero: true,
Issuer: root.Subject,
Subject: pkix.Name{CommonName: "YubiKey Smallstep Intermediate"},
SerialNumber: mustSerialNumber(),
SubjectKeyId: mustSubjectKeyID(publicKey),
}
b, err := x509.CreateCertificate(rand.Reader, template, root, publicKey, signer)
if err != nil {
return err
}
intermediate, err := x509.ParseCertificate(b)
if err != nil {
return errors.Wrap(err, "error parsing intermediate certificate")
}
if cm, ok := k.(kms.CertificateManager); ok {
if err := cm.StoreCertificate(&apiv1.StoreCertificateRequest{
Name: c.CrtSlot,
Certificate: intermediate,
}); err != nil {
return err
}
}
if err := fileutil.WriteFile("intermediate_ca.crt", pem.EncodeToMemory(&pem.Block{
Type: "CERTIFICATE",
Bytes: b,
}), 0600); err != nil {
return err
}
if c.RootOnly {
ui.PrintSelected("Intermediate Key", "intermediate_ca_key")
} else {
ui.PrintSelected("Intermediate Key", keyName)
}
ui.PrintSelected("Intermediate Certificate", "intermediate_ca.crt")
return nil
}
func mustSerialNumber() *big.Int {
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
sn, err := rand.Int(rand.Reader, serialNumberLimit)
if err != nil {
panic(err)
}
return sn
}
func mustSubjectKeyID(key crypto.PublicKey) []byte {
b, err := x509.MarshalPKIXPublicKey(key)
if err != nil {
panic(err)
}
//nolint:gosec // used to create the Subject Key Identifier by RFC 5280
hash := sha1.Sum(b)
return hash[:]
}

@ -5,13 +5,11 @@ COPY . .
RUN apk add --no-cache curl git make
RUN make V=1 download
RUN make V=1 bin/step-ca bin/step-awskms-init bin/step-cloudkms-init
RUN make V=1 bin/step-ca
FROM smallstep/step-cli:latest
COPY --from=builder /src/bin/step-ca /usr/local/bin/step-ca
COPY --from=builder /src/bin/step-awskms-init /usr/local/bin/step-awskms-init
COPY --from=builder /src/bin/step-cloudkms-init /usr/local/bin/step-cloudkms-init
USER root
RUN apk add --no-cache libcap && setcap CAP_NET_BIND_SERVICE=+eip /usr/local/bin/step-ca

@ -8,14 +8,9 @@ RUN apk add --no-cache gcc musl-dev pkgconf pcsc-lite-dev
RUN make V=1 download
RUN make V=1 GOFLAGS="" build
FROM smallstep/step-cli:latest
COPY --from=builder /src/bin/step-ca /usr/local/bin/step-ca
COPY --from=builder /src/bin/step-awskms-init /usr/local/bin/step-awskms-init
COPY --from=builder /src/bin/step-cloudkms-init /usr/local/bin/step-cloudkms-init
COPY --from=builder /src/bin/step-pkcs11-init /usr/local/bin/step-pkcs11-init
COPY --from=builder /src/bin/step-yubikey-init /usr/local/bin/step-yubikey-init
USER root
RUN apk add --no-cache libcap && setcap CAP_NET_BIND_SERVICE=+eip /usr/local/bin/step-ca

@ -24,7 +24,7 @@ require (
github.com/google/go-cmp v0.5.9
github.com/google/uuid v1.3.0
github.com/googleapis/gax-go/v2 v2.7.0
github.com/hashicorp/vault/api v1.8.2
github.com/hashicorp/vault/api v1.8.3
github.com/hashicorp/vault/api/auth/approle v0.3.0
github.com/hashicorp/vault/api/auth/kubernetes v0.3.0
github.com/jhump/protoreflect v1.9.0 // indirect
@ -32,7 +32,7 @@ require (
github.com/mattn/go-colorable v0.1.8 // indirect
github.com/mattn/go-isatty v0.0.13 // indirect
github.com/micromdm/scep/v2 v2.1.0
github.com/newrelic/go-agent/v3 v3.20.2
github.com/newrelic/go-agent/v3 v3.20.3
github.com/pkg/errors v0.9.1
github.com/rs/xid v1.4.0
github.com/sirupsen/logrus v1.9.0
@ -40,7 +40,7 @@ require (
github.com/smallstep/assert v0.0.0-20200723003110-82e2b9b3b262
github.com/smallstep/nosql v0.5.0
github.com/stretchr/testify v1.8.1
github.com/urfave/cli v1.22.11
github.com/urfave/cli v1.22.12
go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352
go.step.sm/cli-utils v0.7.5
go.step.sm/crypto v0.23.1
@ -49,13 +49,15 @@ require (
golang.org/x/net v0.5.0
golang.org/x/sys v0.4.0 // indirect
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect
google.golang.org/api v0.107.0
google.golang.org/api v0.108.0
google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef // indirect
google.golang.org/grpc v1.52.0
google.golang.org/protobuf v1.28.1
gopkg.in/square/go-jose.v2 v2.6.0
)
require github.com/ryboe/q v1.0.18
require (
cloud.google.com/go/compute v1.14.0 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect
@ -78,7 +80,7 @@ require (
github.com/cespare/xxhash v1.1.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgraph-io/badger v1.6.2 // indirect
github.com/dgraph-io/badger/v2 v2.2007.4 // indirect
@ -108,7 +110,7 @@ require (
github.com/hashicorp/go-version v1.2.0 // indirect
github.com/hashicorp/golang-lru v0.5.4 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/hashicorp/vault/sdk v0.6.0 // indirect
github.com/hashicorp/vault/sdk v0.7.0 // indirect
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb // indirect
github.com/huandu/xstrings v1.3.3 // indirect
github.com/imdario/mergo v0.3.12 // indirect
@ -135,9 +137,8 @@ require (
github.com/pierrec/lz4 v2.5.2+incompatible // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rogpeppe/go-internal v1.9.0 // indirect
github.com/russross/blackfriday/v2 v2.0.1 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/ryanuber/go-glob v1.0.0 // indirect
github.com/ryboe/q v1.0.18 // indirect
github.com/shopspring/decimal v1.2.0 // indirect
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
github.com/spf13/cast v1.4.1 // indirect

@ -45,6 +45,7 @@ github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZ
github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
@ -127,8 +128,9 @@ github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -342,14 +344,15 @@ github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0m
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/hashicorp/vault/api v1.8.0/go.mod h1:uJrw6D3y9Rv7hhmS17JQC50jbPDAZdjZoTtrCCxxs7E=
github.com/hashicorp/vault/api v1.8.2 h1:C7OL9YtOtwQbTKI9ogB0A1wffRbCN+rH/LLCHO3d8HM=
github.com/hashicorp/vault/api v1.8.2/go.mod h1:ML8aYzBIhY5m1MD1B2Q0JV89cC85YVH4t5kBaZiyVaE=
github.com/hashicorp/vault/api v1.8.3 h1:cHQOLcMhBR+aVI0HzhPxO62w2+gJhIrKguQNONPzu6o=
github.com/hashicorp/vault/api v1.8.3/go.mod h1:4g/9lj9lmuJQMtT6CmVMHC5FW1yENaVv+Nv4ZfG8fAg=
github.com/hashicorp/vault/api/auth/approle v0.3.0 h1:Ib0oCNXsCq/QZhPYtXPzJEbGS5WR/KoZf8c84QoFdkU=
github.com/hashicorp/vault/api/auth/approle v0.3.0/go.mod h1:hm51TbjzUkPO0Y17wkrpwOpvyyMRpXJNueTHiG04t3k=
github.com/hashicorp/vault/api/auth/kubernetes v0.3.0 h1:HkaCmTKzcgLa2tjdiAid1rbmyQNmQGHfnmvIIM2WorY=
github.com/hashicorp/vault/api/auth/kubernetes v0.3.0/go.mod h1:l1B4MGtLc+P37MabBQiIhP3qd9agj0vqhETmaQjjC/Y=
github.com/hashicorp/vault/sdk v0.6.0 h1:6Z+In5DXHiUfZvIZdMx7e2loL1PPyDjA4bVh9ZTIAhs=
github.com/hashicorp/vault/sdk v0.6.0/go.mod h1:+DRpzoXIdMvKc88R4qxr+edwy/RvH5QK8itmxLiDHLc=
github.com/hashicorp/vault/sdk v0.7.0 h1:2pQRO40R1etpKkia5fb4kjrdYMx3BHklPxl1pxpxDHg=
github.com/hashicorp/vault/sdk v0.7.0/go.mod h1:KyfArJkhooyba7gYCKSq8v66QdqJmnbAxtV/OX1+JTs=
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb h1:b5rjCoWHc7eqmAS4/qyk21ZsHyb6Mxv/jykxvNTkU4M=
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
@ -442,8 +445,6 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
@ -521,8 +522,8 @@ github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzE
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/newrelic/go-agent/v3 v3.20.2 h1:EqFMriW3Bv3on4tqKzI+fJmNYOEG55yw54v6yv8L+x8=
github.com/newrelic/go-agent/v3 v3.20.2/go.mod h1:rT6ZUxJc5rQbWLyCtjqQCOcfb01lKRFbc1yMQkcboWM=
github.com/newrelic/go-agent/v3 v3.20.3 h1:hUBAMq/Y2Y9as5/yxQbf0zNde/X7w58cWZkm2flZIaw=
github.com/newrelic/go-agent/v3 v3.20.3/go.mod h1:rT6ZUxJc5rQbWLyCtjqQCOcfb01lKRFbc1yMQkcboWM=
github.com/nishanths/predeclared v0.0.0-20200524104333-86fad755b4d3/go.mod h1:nt3d53pc1VYcphSCIaYAJtnPYnr3Zyn8fMq2wvPGPso=
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw=
@ -583,8 +584,6 @@ github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqn
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
@ -593,8 +592,9 @@ github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk=
@ -667,8 +667,8 @@ github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljT
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/urfave/cli v1.22.11 h1:3wLoofQeDAA/zDjLA4uvtzIv73+qdxJ3QkxfAqk4UVI=
github.com/urfave/cli v1.22.11/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/urfave/cli v1.22.12 h1:igJgVw1JdKH+trcLWLeLwZjU9fEfPesQ+9/e4MQ44S8=
github.com/urfave/cli v1.22.12/go.mod h1:sSBEIC79qR6OvcmsD4U3KABeOTxDqQtdDnaFuUN30b8=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
@ -878,8 +878,8 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
google.golang.org/api v0.107.0 h1:I2SlFjD8ZWabaIFOfeEDg3pf0BHJDh6iYQ1ic3Yu/UU=
google.golang.org/api v0.107.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY=
google.golang.org/api v0.108.0 h1:WVBc/faN0DkKtR43Q/7+tPny9ZoLZdIiAyG5Q9vFClg=
google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=

Loading…
Cancel
Save