consul/command/acl/bootstrap/bootstrap.go
Ronald 4c070c38e4
Copyright headers for command folder (#16705)
* copyright headers for agent folder

* Ignore test data files

* fix proto files and remove headers in agent/uiserver folder

* ignore deep-copy files

* copyright headers for agent folder

* Copyright headers for command folder

* fix merge conflicts
2023-03-28 15:12:30 -04:00

121 lines
2.6 KiB
Go

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package bootstrap
import (
"flag"
"fmt"
"os"
"strings"
"github.com/hashicorp/consul/api"
"github.com/hashicorp/consul/command/acl/token"
"github.com/hashicorp/consul/command/flags"
"github.com/hashicorp/consul/command/helpers"
"github.com/mitchellh/cli"
)
func New(ui cli.Ui) *cmd {
c := &cmd{UI: ui}
c.init()
return c
}
type cmd struct {
UI cli.Ui
flags *flag.FlagSet
http *flags.HTTPFlags
help string
format string
}
func (c *cmd) init() {
c.flags = flag.NewFlagSet("", flag.ContinueOnError)
c.flags.StringVar(
&c.format,
"format",
token.PrettyFormat,
fmt.Sprintf("Output format {%s}", strings.Join(token.GetSupportedFormats(), "|")),
)
c.http = &flags.HTTPFlags{}
flags.Merge(c.flags, c.http.ClientFlags())
flags.Merge(c.flags, c.http.ServerFlags())
c.help = flags.Usage(help, c.flags)
}
func (c *cmd) Run(args []string) int {
if err := c.flags.Parse(args); err != nil {
return 1
}
args = c.flags.Args()
if l := len(args); l < 0 || l > 1 {
c.UI.Error("This command takes up to one argument")
return 1
}
var terminalToken string
var err error
if len(args) == 1 {
terminalToken, err = helpers.LoadDataSourceNoRaw(args[0], os.Stdin)
if err != nil {
c.UI.Error(fmt.Sprintf("Error reading provided token: %v", err))
return 1
}
}
// Remove newline from the token if it was passed by stdin
boottoken := strings.TrimSpace(terminalToken)
client, err := c.http.APIClient()
if err != nil {
c.UI.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err))
return 1
}
var t *api.ACLToken
t, _, err = client.ACL().BootstrapWithToken(boottoken)
if err != nil {
c.UI.Error(fmt.Sprintf("Failed ACL bootstrapping: %v", err))
return 1
}
formatter, err := token.NewFormatter(c.format, false)
if err != nil {
c.UI.Error(err.Error())
return 1
}
out, err := formatter.FormatToken(t)
if err != nil {
c.UI.Error(err.Error())
return 1
}
if out != "" {
c.UI.Info(out)
}
return 0
}
func (c *cmd) Synopsis() string {
return synopsis
}
func (c *cmd) Help() string {
return flags.Usage(c.help, nil)
}
const synopsis = "Bootstrap Consul's ACL system"
// TODO (ACL-V2) - maybe embed link to bootstrap reset docs
const help = `
Usage: consul acl bootstrap [options]
The bootstrap command will request Consul to generate a new token with unlimited privileges to use
for management purposes and output its details. This can only be done once and afterwards bootstrapping
will be disabled. If all tokens are lost and you need to bootstrap again you can follow the bootstrap
reset procedure
`