Merge pull request #1240 from smallstep/remove-deprecated-binaries

Remove deprecated binaries
This commit is contained in:
Mariano Cano 2023-01-24 11:16:50 -08:00 committed by GitHub
commit 4bb25d4a52
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 11 additions and 1493 deletions

View file

@ -27,6 +27,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
## [Unreleased] ## [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 ## [v0.23.1] - 2022-01-10
### Added ### Added

View file

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

View file

@ -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[:]
}

View file

@ -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[:]
}

View file

@ -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[:]
}

View file

@ -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[:]
}

View file

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

View file

@ -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 download
RUN make V=1 GOFLAGS="" build RUN make V=1 GOFLAGS="" build
FROM smallstep/step-cli:latest FROM smallstep/step-cli:latest
COPY --from=builder /src/bin/step-ca /usr/local/bin/step-ca 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 USER root
RUN apk add --no-cache libcap && setcap CAP_NET_BIND_SERVICE=+eip /usr/local/bin/step-ca RUN apk add --no-cache libcap && setcap CAP_NET_BIND_SERVICE=+eip /usr/local/bin/step-ca