1
0
mirror of https://github.com/smallstep/cli.git synced 2026-10-24 11:19:19 +03:00
Files
step-ca-cli/command/ca/admin/admin.go
2025-01-07 00:37:05 +01:00

163 lines
3.8 KiB
Go

package admin
import (
"errors"
"fmt"
"github.com/urfave/cli"
"github.com/smallstep/certificates/ca"
"github.com/smallstep/cli-utils/errs"
"github.com/smallstep/cli-utils/ui"
"github.com/smallstep/linkedca"
)
// Command returns the jwk subcommand.
func Command() cli.Command {
return cli.Command{
Name: "admin",
Usage: "create and manage the certificate authority admins",
UsageText: "**step ca admin** <subcommand> [arguments] [global-flags] [subcommand-flags]",
Subcommands: cli.Commands{
listCommand(),
addCommand(),
removeCommand(),
updateCommand(),
},
Description: `**step ca admin** command group provides facilities for managing the
certificate authority admins.
An admin is an entity that manages administrative resources (like authority
configuration, provisioner configuration, and other admins) within a certificate
authority.
## EXAMPLES
List the active admins:
'''
$ step ca admin list
'''
Add an admin:
'''
$ step ca admin add max@smallstep.com my-jwk-provisioner --super
'''
Update an admin:
'''
$ step ca admin update max@smallstep.com --super=false
'''
Remove an admin:
'''
$ step ca admin remove max@smallstep.com
'''`,
}
}
var provisionerFilterFlag = cli.StringFlag{
Name: "provisioner",
Usage: `The provisioner <name> by which to filter admins.`,
}
type adminSelect struct {
Name string
CLIAdmin *cliAdmin
}
type cliAdmin struct {
*linkedca.Admin
ProvisionerName string
ProvisionerType string
}
func toCLI(_ *cli.Context, client *ca.AdminClient, adm *linkedca.Admin) (*cliAdmin, error) {
p, err := client.GetProvisioner(ca.WithProvisionerID(adm.ProvisionerId))
if err != nil {
return nil, err
}
return &cliAdmin{Admin: adm, ProvisionerName: p.GetName(), ProvisionerType: p.GetType().String()}, nil
}
func listToCLI(ctx *cli.Context, client *ca.AdminClient, admins []*linkedca.Admin) ([]*cliAdmin, error) {
var (
err error
cliAdmins = make([]*cliAdmin, len(admins))
)
for i, adm := range admins {
cliAdmins[i], err = toCLI(ctx, client, adm)
if err != nil {
return nil, err
}
}
return cliAdmins, nil
}
func adminPrompt(ctx *cli.Context, client *ca.AdminClient, admins []*linkedca.Admin) (*cliAdmin, error) {
if len(admins) == 0 {
return nil, errors.New("no admins to update")
}
args := ctx.Args()
subject := args[0]
cliAdmins, err := listToCLI(ctx, client, admins)
if err != nil {
return nil, err
}
// Filter by subject
cliAdmins = adminFilter(cliAdmins, func(adm *cliAdmin) bool {
return adm.Subject == subject
})
if len(cliAdmins) == 0 {
return nil, fmt.Errorf("no admins with subject %s", subject)
}
// Filter by provisionerName
if provName := ctx.String("provisioner"); provName != "" {
cliAdmins = adminFilter(cliAdmins, func(a *cliAdmin) bool {
return a.ProvisionerName == provName
})
if len(cliAdmins) == 0 {
return nil, errs.InvalidFlagValue(ctx, "provisioner", provName, "")
}
}
// Select admin
var items []*adminSelect
for _, adm := range cliAdmins {
items = append(items, &adminSelect{
//Name: fmt.Sprintf("%s\t%s (%s)\t%s", adm.Subject,
Name: fmt.Sprintf("subject: %s, provisioner: %s(%s), type: %s", adm.Subject,
adm.ProvisionerName, adm.ProvisionerType, adm.Type),
CLIAdmin: adm,
})
}
if len(items) == 1 {
if err := ui.PrintSelected("Admin", items[0].Name); err != nil {
return nil, err
}
return items[0].CLIAdmin, nil
}
i, _, err := ui.Select("Select an admin:", items,
ui.WithSelectTemplates(ui.NamedSelectTemplates("Admin")))
if err != nil {
return nil, err
}
return items[i].CLIAdmin, nil
}
// adminFilter returns a slice of admins that pass the given filter.
func adminFilter(cliAdmins []*cliAdmin, f func(*cliAdmin) bool) []*cliAdmin {
var result []*cliAdmin
for _, a := range cliAdmins {
if f(a) {
result = append(result, a)
}
}
return result
}