You've already forked step-ca-cli
mirror of
https://github.com/smallstep/cli.git
synced 2025-08-07 16:02:54 +03:00
* Remove unnecessary utils files in favor of cli-utils package * Remove nolint:revive directive from bcrypt-pbkdf file
190 lines
4.1 KiB
Go
190 lines
4.1 KiB
Go
package ca
|
|
|
|
import (
|
|
"encoding/pem"
|
|
"fmt"
|
|
"os"
|
|
|
|
"github.com/pkg/errors"
|
|
"github.com/urfave/cli"
|
|
|
|
"github.com/smallstep/certificates/api"
|
|
"github.com/smallstep/certificates/ca"
|
|
"github.com/smallstep/certificates/pki"
|
|
"github.com/smallstep/cli-utils/command"
|
|
"github.com/smallstep/cli-utils/errs"
|
|
"github.com/smallstep/cli-utils/fileutil"
|
|
"github.com/smallstep/cli-utils/ui"
|
|
"go.step.sm/crypto/pemutil"
|
|
|
|
"github.com/smallstep/cli/flags"
|
|
)
|
|
|
|
type flowType int
|
|
|
|
const (
|
|
rootsFlow flowType = iota
|
|
federationFlow
|
|
)
|
|
|
|
func rootsCommand() cli.Command {
|
|
return cli.Command{
|
|
Name: "roots",
|
|
Action: command.ActionFunc(rootsAction),
|
|
Usage: "download all the root certificates",
|
|
UsageText: `**step ca roots** [<roots-file>]
|
|
[**--ca-url**=<uri>] [**--root**=<file>] [**--context**=<name>]`,
|
|
Description: `**step ca roots** downloads a certificate bundle with all the root
|
|
certificates.
|
|
|
|
## POSITIONAL ARGUMENTS
|
|
|
|
<roots-file>
|
|
: File to write all the root certificates (PEM format)
|
|
|
|
## EXAMPLES
|
|
|
|
Download the roots with flags set by <step ca bootstrap>:
|
|
'''
|
|
$ step ca roots roots.pem
|
|
'''
|
|
|
|
Download the roots with custom flags:
|
|
'''
|
|
$ step ca roots roots.pem \
|
|
--ca-url https://ca.example.com \
|
|
--root /path/to/root_ca.crt
|
|
'''
|
|
|
|
Print the roots using flags set by <step ca bootstrap>:
|
|
'''
|
|
$ step ca roots
|
|
'''`,
|
|
Flags: []cli.Flag{
|
|
flags.CaURL,
|
|
flags.Force,
|
|
flags.Root,
|
|
flags.Context,
|
|
},
|
|
}
|
|
}
|
|
|
|
func federationCommand() cli.Command {
|
|
return cli.Command{
|
|
Name: "federation",
|
|
Action: command.ActionFunc(federationAction),
|
|
Usage: "download all the federated certificates",
|
|
UsageText: `**step ca federation** [<federation-file>]
|
|
[**--ca-url**=<uri>] [**--root**=<file>] [**--context**=<name>]`,
|
|
Description: `**step ca federation** downloads a certificate bundle with all the root
|
|
certificates in the federation.
|
|
|
|
## POSITIONAL ARGUMENTS
|
|
|
|
<federation-file>
|
|
: File to write federation certificates (PEM format)
|
|
|
|
## EXAMPLES
|
|
|
|
Download the federated roots with flags set by <step ca bootstrap>:
|
|
'''
|
|
$ step ca federation federation.pem
|
|
'''
|
|
|
|
Download the federated roots with custom flags:
|
|
'''
|
|
$ step ca federation federation.pem \
|
|
--ca-url https://ca.example.com \
|
|
--root /path/to/root_ca.crt
|
|
'''
|
|
|
|
Print the federated roots using flags set by <step ca bootstrap>:
|
|
'''
|
|
$ step ca federation
|
|
'''`,
|
|
Flags: []cli.Flag{
|
|
flags.CaURL,
|
|
flags.Force,
|
|
flags.Root,
|
|
flags.Context,
|
|
},
|
|
}
|
|
}
|
|
|
|
func rootsAction(ctx *cli.Context) error {
|
|
return rootsAndFederationFlow(ctx, rootsFlow)
|
|
}
|
|
|
|
func federationAction(ctx *cli.Context) error {
|
|
return rootsAndFederationFlow(ctx, federationFlow)
|
|
}
|
|
|
|
func rootsAndFederationFlow(ctx *cli.Context, typ flowType) error {
|
|
if err := errs.MinMaxNumberOfArguments(ctx, 0, 1); err != nil {
|
|
return err
|
|
}
|
|
|
|
caURL, err := flags.ParseCaURL(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
root := ctx.String("root")
|
|
if root == "" {
|
|
root = pki.GetRootCAPath()
|
|
if _, err := os.Stat(root); err != nil {
|
|
return errs.RequiredFlag(ctx, "root")
|
|
}
|
|
}
|
|
|
|
client, err := ca.NewClient(caURL, ca.WithRootFile(root))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var certs []api.Certificate
|
|
switch typ {
|
|
case rootsFlow:
|
|
roots, err := client.Roots()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
certs = roots.Certificates
|
|
case federationFlow:
|
|
federation, err := client.Federation()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
certs = federation.Certificates
|
|
default:
|
|
return errors.New("unknown flow type: this should not happen")
|
|
}
|
|
|
|
var data []byte
|
|
for _, cert := range certs {
|
|
block, err := pemutil.Serialize(cert.Certificate)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
data = append(data, pem.EncodeToMemory(block)...)
|
|
}
|
|
|
|
if outFile := ctx.Args().Get(0); outFile != "" {
|
|
if err := fileutil.WriteFile(outFile, data, 0o600); err != nil {
|
|
return err
|
|
}
|
|
|
|
switch typ {
|
|
case rootsFlow:
|
|
ui.Printf("The root certificate bundle has been saved in %s.\n", outFile)
|
|
case federationFlow:
|
|
ui.Printf("The federation certificate bundle has been saved in %s.\n", outFile)
|
|
default:
|
|
return errors.New("unknown flow type: this should not happen")
|
|
}
|
|
} else {
|
|
fmt.Print(string(data))
|
|
}
|
|
return nil
|
|
}
|