mirror of
https://github.com/gravitational/teleport
synced 2024-10-21 17:53:28 +00:00
Merge pull request #19 from gravitational/alex/kingpin
Migrated tctl to kingpin cmd args parser
This commit is contained in:
commit
501e091cbb
|
@ -2,98 +2,14 @@ package command
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/gravitational/teleport/Godeps/_workspace/src/github.com/buger/goterm"
|
||||
"github.com/gravitational/teleport/Godeps/_workspace/src/github.com/codegangsta/cli"
|
||||
"github.com/gravitational/teleport/backend"
|
||||
)
|
||||
|
||||
func newHostCACommand(c *Command) cli.Command {
|
||||
return cli.Command{
|
||||
Name: "hostca",
|
||||
Usage: "Operations with host certificate authority",
|
||||
Subcommands: []cli.Command{
|
||||
{
|
||||
Name: "reset",
|
||||
Usage: "Reset host certificate authority keys",
|
||||
Flags: []cli.Flag{
|
||||
cli.BoolFlag{Name: "confirm", Usage: "Automatically apply the operation without confirmation"},
|
||||
},
|
||||
Action: c.resetHostCA,
|
||||
},
|
||||
{
|
||||
Name: "pubkey",
|
||||
Usage: "print host certificate authority public key",
|
||||
Action: c.getHostCAPub,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func newUserCACommand(c *Command) cli.Command {
|
||||
return cli.Command{
|
||||
Name: "userca",
|
||||
Usage: "Operations with user certificate authority",
|
||||
Subcommands: []cli.Command{
|
||||
{
|
||||
Name: "reset",
|
||||
Usage: "Reset user certificate authority keys",
|
||||
Flags: []cli.Flag{
|
||||
cli.BoolFlag{Name: "confirm", Usage: "Automatically apply the operation without confirmation"},
|
||||
},
|
||||
Action: c.resetUserCA,
|
||||
},
|
||||
{
|
||||
Name: "pubkey",
|
||||
Usage: "print user certificate authority public key",
|
||||
Action: c.getUserCAPub,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func newRemoteCACommand(c *Command) cli.Command {
|
||||
return cli.Command{
|
||||
Name: "remoteca",
|
||||
Usage: "Operations with remote certificate authority",
|
||||
Subcommands: []cli.Command{
|
||||
{
|
||||
Name: "upsert",
|
||||
Usage: "Upsert remote certificate to trust",
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{Name: "id", Usage: "Certificate id"},
|
||||
cli.StringFlag{Name: "fqdn", Usage: "FQDN of the remote party"},
|
||||
cli.StringFlag{Name: "type", Usage: "Cert type (host or user)"},
|
||||
cli.StringFlag{Name: "path", Usage: "Cert path (reads from stdout if omitted)"},
|
||||
cli.DurationFlag{Name: "ttl", Usage: "ttl for certificate to be trusted"},
|
||||
},
|
||||
Action: c.upsertRemoteCert,
|
||||
},
|
||||
{
|
||||
Name: "ls",
|
||||
Usage: "List trusted remote certificates",
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{Name: "fqdn", Usage: "FQDN of the remote party"},
|
||||
cli.StringFlag{Name: "type", Usage: "Cert type (host or user)"},
|
||||
},
|
||||
Action: c.getRemoteCerts,
|
||||
},
|
||||
{
|
||||
Name: "rm",
|
||||
Usage: "Remote remote CA from list of trusted certs",
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{Name: "id", Usage: "Certificate id"},
|
||||
cli.StringFlag{Name: "fqdn", Usage: "FQDN of the remote party"},
|
||||
cli.StringFlag{Name: "type", Usage: "Cert type (host or user)"},
|
||||
},
|
||||
Action: c.deleteRemoteCert,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (cmd *Command) resetHostCA(c *cli.Context) {
|
||||
if !c.Bool("confirm") && !cmd.confirm("Reseting private and public keys for Host CA. This will invalidate all signed host certs. Continue?") {
|
||||
func (cmd *Command) resetHostCA(confirm bool) {
|
||||
if !confirm && !cmd.confirm("Reseting private and public keys for Host CA. This will invalidate all signed host certs. Continue?") {
|
||||
cmd.printError(fmt.Errorf("aborted by user"))
|
||||
return
|
||||
}
|
||||
|
@ -104,7 +20,7 @@ func (cmd *Command) resetHostCA(c *cli.Context) {
|
|||
cmd.printOK("CA keys have been regenerated")
|
||||
}
|
||||
|
||||
func (cmd *Command) getHostCAPub(c *cli.Context) {
|
||||
func (cmd *Command) getHostCAPub() {
|
||||
key, err := cmd.client.GetHostCAPub()
|
||||
if err != nil {
|
||||
cmd.printError(err)
|
||||
|
@ -114,8 +30,8 @@ func (cmd *Command) getHostCAPub(c *cli.Context) {
|
|||
fmt.Fprintf(cmd.out, string(key))
|
||||
}
|
||||
|
||||
func (cmd *Command) resetUserCA(c *cli.Context) {
|
||||
if !c.Bool("confirm") && !cmd.confirm("Reseting private and public keys for User CA. This will invalidate all signed user certs. Continue?") {
|
||||
func (cmd *Command) resetUserCA(confirm bool) {
|
||||
if !confirm && !cmd.confirm("Reseting private and public keys for User CA. This will invalidate all signed user certs. Continue?") {
|
||||
cmd.printError(fmt.Errorf("aborted by user"))
|
||||
return
|
||||
}
|
||||
|
@ -126,7 +42,7 @@ func (cmd *Command) resetUserCA(c *cli.Context) {
|
|||
cmd.printOK("CA keys have been regenerated")
|
||||
}
|
||||
|
||||
func (cmd *Command) getUserCAPub(c *cli.Context) {
|
||||
func (cmd *Command) getUserCAPub() {
|
||||
key, err := cmd.client.GetUserCAPub()
|
||||
if err != nil {
|
||||
cmd.printError(err)
|
||||
|
@ -136,28 +52,27 @@ func (cmd *Command) getUserCAPub(c *cli.Context) {
|
|||
fmt.Fprintf(cmd.out, string(key))
|
||||
}
|
||||
|
||||
func (cmd *Command) upsertRemoteCert(c *cli.Context) {
|
||||
ctype, fqdn, id := c.String("type"), c.String("fqdn"), c.String("id")
|
||||
val, err := cmd.readInput(c.String("path"))
|
||||
func (cmd *Command) upsertRemoteCert(id, fqdn, certType, path string, ttl time.Duration) {
|
||||
val, err := cmd.readInput(path)
|
||||
if err != nil {
|
||||
cmd.printError(err)
|
||||
return
|
||||
}
|
||||
cert := backend.RemoteCert{
|
||||
FQDN: fqdn,
|
||||
Type: ctype,
|
||||
Type: certType,
|
||||
ID: id,
|
||||
Value: val,
|
||||
}
|
||||
if err := cmd.client.UpsertRemoteCert(cert, c.Duration("ttl")); err != nil {
|
||||
if err := cmd.client.UpsertRemoteCert(cert, ttl); err != nil {
|
||||
cmd.printError(err)
|
||||
return
|
||||
}
|
||||
cmd.printOK("Remote cert have been upserted")
|
||||
}
|
||||
|
||||
func (cmd *Command) getRemoteCerts(c *cli.Context) {
|
||||
certs, err := cmd.client.GetRemoteCerts(c.String("type"), c.String("fqdn"))
|
||||
func (cmd *Command) getRemoteCerts(fqdn, certType string) {
|
||||
certs, err := cmd.client.GetRemoteCerts(certType, fqdn)
|
||||
if err != nil {
|
||||
cmd.printError(err)
|
||||
return
|
||||
|
@ -165,8 +80,8 @@ func (cmd *Command) getRemoteCerts(c *cli.Context) {
|
|||
fmt.Fprintf(cmd.out, remoteCertsView(certs))
|
||||
}
|
||||
|
||||
func (cmd *Command) deleteRemoteCert(c *cli.Context) {
|
||||
err := cmd.client.DeleteRemoteCert(c.String("type"), c.String("fqdn"), c.String("id"))
|
||||
func (cmd *Command) deleteRemoteCert(id, fqdn, certType string) {
|
||||
err := cmd.client.DeleteRemoteCert(certType, fqdn, id)
|
||||
if err != nil {
|
||||
cmd.printError(err)
|
||||
return
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"github.com/gravitational/teleport/Godeps/_workspace/src/github.com/codegangsta/cli"
|
||||
"github.com/gravitational/teleport/auth"
|
||||
"github.com/gravitational/teleport/utils"
|
||||
"gopkg.in/alecthomas/kingpin.v2"
|
||||
)
|
||||
|
||||
type Command struct {
|
||||
|
@ -27,11 +28,81 @@ func NewCommand() *Command {
|
|||
}
|
||||
|
||||
func (cmd *Command) Run(args []string) error {
|
||||
addr, args, err := findAddr(args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a, err := utils.ParseAddr(addr)
|
||||
app := kingpin.New("tctl", "CLI for key management of teleport SSH cluster")
|
||||
authUrl := app.Flag("auth", "Teleport URL").Default(DefaultTeleportURL).String()
|
||||
|
||||
// Host CA
|
||||
hostCa := app.Command("host-ca", "Operations with host certificate authority")
|
||||
|
||||
hostCaReset := hostCa.Command("reset", "Reset host certificate authority keys")
|
||||
hostCaResetConfirm := hostCaReset.Flag("confirm", "Automatically apply the operation without confirmation").Bool()
|
||||
|
||||
hostCaPubKey := hostCa.Command("pub-key", "print host certificate authority public key")
|
||||
|
||||
// User CA
|
||||
userCa := app.Command("user-ca", "Operations with user certificate authority")
|
||||
|
||||
userCaReset := userCa.Command("reset", "Reset user certificate authority keys")
|
||||
userCaResetConfirm := userCaReset.Flag("confirm", "Automatically apply the operation without confirmation").Bool()
|
||||
|
||||
userCaPubKey := userCa.Command("pub-key", "Print user certificate authority public key")
|
||||
|
||||
// Remote CA
|
||||
remoteCa := app.Command("remote-ca", "Operations with remote certificate authority")
|
||||
|
||||
remoteCaUpsert := remoteCa.Command("upsert", "Upsert remote certificate to trust")
|
||||
remoteCaUpsertID := remoteCaUpsert.Flag("id", "Certificate id").Required().String()
|
||||
remoteCaUpsertFQDN := remoteCaUpsert.Flag("fqdn", "FQDN of the remote party").Required().String()
|
||||
remoteCaUpsertType := remoteCaUpsert.Flag("type", "Cert type (host or user)").Required().String()
|
||||
remoteCaUpsertPath := remoteCaUpsert.Flag("path", "Cert path (reads from stdout if omitted)").Required().ExistingFile()
|
||||
remoteCaUpsertTTL := remoteCaUpsert.Flag("ttl", "ttl for certificate to be trusted").Duration()
|
||||
|
||||
remoteCaLs := remoteCa.Command("ls", "List trusted remote certificates")
|
||||
remoteCaLsFQDN := remoteCaLs.Flag("fqdn", "FQDN of the remote party").String()
|
||||
remoteCaLsType := remoteCaLs.Flag("type", "Cert type (host or user)").Required().String()
|
||||
|
||||
remoteCaRm := remoteCa.Command("rm", "Remote remote CA from list of trusted certs")
|
||||
remoteCaRmID := remoteCaRm.Flag("id", "Certificate id").Required().String()
|
||||
remoteCaRmFQDN := remoteCaRm.Flag("fqdn", "FQDN of the remote party").Required().String()
|
||||
remoteCaRmType := remoteCaRm.Flag("type", "Cert type (host or user)").Required().String()
|
||||
|
||||
// Secret
|
||||
secret := app.Command("secret", "Operations with secret tokens")
|
||||
|
||||
secretNew := secret.Command("new", "Generate new secret key")
|
||||
|
||||
// Token
|
||||
token := app.Command("token", "Generates provisioning tokens")
|
||||
|
||||
tokenGenerate := token.Command("generate", "Generate provisioning token for server with fqdn")
|
||||
tokenGenerateFQDN := tokenGenerate.Flag("fqdn", "FQDN of the server").Required().String()
|
||||
tokenGenerateTTL := tokenGenerate.Flag("ttl", "Time to live").Default("120").Duration()
|
||||
tokenGenerateOutput := tokenGenerate.Flag("output", "Optional output file").String()
|
||||
|
||||
// User
|
||||
user := app.Command("user", "Operations with registered users")
|
||||
|
||||
userLs := user.Command("ls", "List users registered in teleport")
|
||||
|
||||
userDelete := user.Command("delete", "Delete user")
|
||||
userDeleteUser := userDelete.Flag("user", "User to delete").Required().String()
|
||||
|
||||
userUpsertKey := user.Command("upsert-key", "Grant access to the user key, returns signed certificate")
|
||||
userUpsertKeyUser := userUpsertKey.Flag("user", "User holding the key").Required().String()
|
||||
userUpsertKeyKeyID := userUpsertKey.Flag("key-id", "SSH key ID").Required().String()
|
||||
userUpsertKeyKey := userUpsertKey.Flag("key", "Path to public key").Required().ExistingFile()
|
||||
userUpsertKeyTTL := userUpsertKey.Flag("ttl", "Access time to live, certificate and access entry will expire when set").Duration()
|
||||
|
||||
userLsKeys := user.Command("ls-keys", "List user's keys registered in teleport")
|
||||
userLsKeysUser := userLsKeys.Flag("user", "User to list keys form").Required().String()
|
||||
|
||||
userSetPass := user.Command("set-pass", "Set user password")
|
||||
userSetPassUser := userSetPass.Flag("user", "User name").Required().String()
|
||||
userSetPassPass := userSetPass.Flag("pass", "Password").Required().String()
|
||||
|
||||
selectedCommand := kingpin.MustParse(app.Parse(args[1:]))
|
||||
|
||||
a, err := utils.ParseAddr(*authUrl)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -42,20 +113,52 @@ func (cmd *Command) Run(args []string) error {
|
|||
|
||||
cmd.client = clt
|
||||
|
||||
app := cli.NewApp()
|
||||
app.Name = "tctl"
|
||||
app.Usage = "CLI for key management of teleport SSH cluster"
|
||||
app.Flags = flags()
|
||||
switch selectedCommand {
|
||||
// Host CA
|
||||
case hostCaReset.FullCommand():
|
||||
cmd.resetHostCA(*hostCaResetConfirm)
|
||||
case hostCaPubKey.FullCommand():
|
||||
cmd.getHostCAPub()
|
||||
|
||||
app.Commands = []cli.Command{
|
||||
newHostCACommand(cmd),
|
||||
newUserCACommand(cmd),
|
||||
newRemoteCACommand(cmd),
|
||||
newUserCommand(cmd),
|
||||
newTokenCommand(cmd),
|
||||
newSecretCommand(cmd),
|
||||
// User CA
|
||||
case userCaReset.FullCommand():
|
||||
cmd.resetUserCA(*userCaResetConfirm)
|
||||
case userCaPubKey.FullCommand():
|
||||
cmd.getUserCAPub()
|
||||
|
||||
// Remote CA
|
||||
case remoteCaUpsert.FullCommand():
|
||||
cmd.upsertRemoteCert(*remoteCaUpsertID, *remoteCaUpsertFQDN,
|
||||
*remoteCaUpsertType, *remoteCaUpsertPath, *remoteCaUpsertTTL)
|
||||
case remoteCaLs.FullCommand():
|
||||
cmd.getRemoteCerts(*remoteCaLsFQDN, *remoteCaLsType)
|
||||
case remoteCaRm.FullCommand():
|
||||
cmd.deleteRemoteCert(*remoteCaRmID, *remoteCaRmFQDN, *remoteCaRmType)
|
||||
|
||||
// Secret
|
||||
case secretNew.FullCommand():
|
||||
cmd.newKey()
|
||||
|
||||
// Token
|
||||
case tokenGenerate.FullCommand():
|
||||
cmd.generateToken(*tokenGenerateFQDN, *tokenGenerateTTL,
|
||||
*tokenGenerateOutput)
|
||||
|
||||
// User
|
||||
case userLs.FullCommand():
|
||||
cmd.getUsers()
|
||||
case userDelete.FullCommand():
|
||||
cmd.deleteUser(*userDeleteUser)
|
||||
case userUpsertKey.FullCommand():
|
||||
cmd.upsertKey(*userUpsertKeyUser, *userUpsertKeyKeyID,
|
||||
*userUpsertKeyKey, *userUpsertKeyTTL)
|
||||
case userLsKeys.FullCommand():
|
||||
cmd.getUserKeys(*userLsKeysUser)
|
||||
case userSetPass.FullCommand():
|
||||
cmd.setPass(*userSetPassUser, *userSetPassPass)
|
||||
}
|
||||
return app.Run(args)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cmd *Command) readInput(path string) ([]byte, error) {
|
||||
|
@ -104,24 +207,6 @@ func (cmd *Command) printInfo(message string, params ...interface{}) {
|
|||
fmt.Fprintf(cmd.out, "INFO: %s\n", fmt.Sprintf(message, params...))
|
||||
}
|
||||
|
||||
// This function extracts url from the command line regardless of it's position
|
||||
// this is a workaround, as cli libary does not support "superglobal" urls yet.
|
||||
func findAddr(args []string) (string, []string, error) {
|
||||
for i, arg := range args {
|
||||
if strings.HasPrefix(arg, "--teleport=") || strings.HasPrefix(arg, "-teleport=") {
|
||||
out := strings.Split(arg, "=")
|
||||
return out[1], cut(i, i+1, args), nil
|
||||
} else if strings.HasPrefix(arg, "-teleport") || strings.HasPrefix(arg, "--teleport") {
|
||||
// This argument should not be the last one
|
||||
if i > len(args)-2 {
|
||||
return "", nil, fmt.Errorf("provide a valid address")
|
||||
}
|
||||
return args[i+1], cut(i, i+2, args), nil
|
||||
}
|
||||
}
|
||||
return DefaultTeleportURL, args, nil
|
||||
}
|
||||
|
||||
func cut(i, j int, args []string) []string {
|
||||
s := []string{}
|
||||
s = append(s, args[:i]...)
|
||||
|
|
|
@ -6,15 +6,21 @@ import (
|
|||
"io/ioutil"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/gravitational/teleport/auth"
|
||||
authority "github.com/gravitational/teleport/auth/native"
|
||||
"github.com/gravitational/teleport/backend/membk"
|
||||
"github.com/gravitational/teleport/backend"
|
||||
"github.com/gravitational/teleport/backend/boltbk"
|
||||
"github.com/gravitational/teleport/events/boltlog"
|
||||
"github.com/gravitational/teleport/recorder"
|
||||
"github.com/gravitational/teleport/recorder/boltrec"
|
||||
"github.com/gravitational/teleport/session"
|
||||
"github.com/gravitational/teleport/utils"
|
||||
|
||||
"github.com/gravitational/teleport/Godeps/_workspace/src/github.com/gravitational/memlog"
|
||||
"github.com/gravitational/teleport/Godeps/_workspace/src/github.com/gravitational/log"
|
||||
"github.com/gravitational/teleport/Godeps/_workspace/src/github.com/mailgun/lemma/secret"
|
||||
|
||||
. "github.com/gravitational/teleport/Godeps/_workspace/src/gopkg.in/check.v1"
|
||||
|
@ -30,9 +36,12 @@ type CmdSuite struct {
|
|||
clt *auth.Client
|
||||
cmd *Command
|
||||
out *bytes.Buffer
|
||||
bk *membk.MemBackend
|
||||
bk *boltbk.BoltBackend
|
||||
bl *boltlog.BoltLog
|
||||
scrt *secret.Service
|
||||
rec recorder.Recorder
|
||||
addr utils.NetAddr
|
||||
dir string
|
||||
}
|
||||
|
||||
var _ = Suite(&CmdSuite{})
|
||||
|
@ -43,12 +52,25 @@ func (s *CmdSuite) SetUpSuite(c *C) {
|
|||
srv, err := secret.New(&secret.Config{KeyBytes: key})
|
||||
c.Assert(err, IsNil)
|
||||
s.scrt = srv
|
||||
|
||||
log.Init([]*log.LogConfig{&log.LogConfig{Name: "console"}})
|
||||
}
|
||||
|
||||
func (s *CmdSuite) SetUpTest(c *C) {
|
||||
s.bk = membk.New()
|
||||
s.dir = c.MkDir()
|
||||
var err error
|
||||
s.bk, err = boltbk.New(filepath.Join(s.dir, "db"))
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
s.bl, err = boltlog.New(filepath.Join(s.dir, "eventsdb"))
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
s.rec, err = boltrec.New(s.dir)
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
s.asrv = auth.NewAuthServer(s.bk, authority.New(), s.scrt)
|
||||
s.srv = httptest.NewServer(auth.NewAPIServer(s.asrv, memlog.New()))
|
||||
s.srv = httptest.NewServer(auth.NewAPIServer(s.asrv, s.bl,
|
||||
session.New(s.bk), s.rec))
|
||||
|
||||
u, err := url.Parse(s.srv.URL)
|
||||
c.Assert(err, IsNil)
|
||||
|
@ -74,7 +96,7 @@ func (s *CmdSuite) runString(in string) string {
|
|||
func (s *CmdSuite) run(params ...string) string {
|
||||
args := []string{"tctl"}
|
||||
args = append(args, params...)
|
||||
args = append(args, fmt.Sprintf("--teleport=%v", &s.addr))
|
||||
args = append(args, fmt.Sprintf("--auth=%v", &s.addr))
|
||||
s.out = &bytes.Buffer{}
|
||||
s.cmd = &Command{out: s.out}
|
||||
s.cmd.Run(args)
|
||||
|
@ -83,24 +105,31 @@ func (s *CmdSuite) run(params ...string) string {
|
|||
|
||||
func (s *CmdSuite) TestHostCACRUD(c *C) {
|
||||
c.Assert(
|
||||
s.run("hostca", "reset", "-confirm"),
|
||||
s.run("host-ca", "reset", "--confirm"),
|
||||
Matches, fmt.Sprintf(".*%v.*", "regenerated"))
|
||||
c.Assert(s.bk.HostCA, NotNil)
|
||||
|
||||
hostCA, err := s.bk.GetHostCA()
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(hostCA, NotNil)
|
||||
|
||||
c.Assert(
|
||||
s.run("hostca", "pubkey"),
|
||||
Matches, fmt.Sprintf(".*%v.*", s.bk.HostCA.Pub))
|
||||
s.run("host-ca", "pub-key"),
|
||||
Matches, fmt.Sprintf(".*%v.*", hostCA.Pub))
|
||||
}
|
||||
|
||||
func (s *CmdSuite) TestUserCACRUD(c *C) {
|
||||
c.Assert(
|
||||
s.run("userca", "reset", "-confirm"),
|
||||
s.run("user-ca", "reset", "--confirm"),
|
||||
Matches, fmt.Sprintf(".*%v.*", "regenerated"))
|
||||
c.Assert(s.bk.UserCA, NotNil)
|
||||
|
||||
userCA, err := s.bk.GetUserCA()
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(userCA, NotNil)
|
||||
c.Assert(userCA, NotNil)
|
||||
|
||||
c.Assert(
|
||||
s.run("userca", "pubkey"),
|
||||
Matches, fmt.Sprintf(".*%v.*", s.bk.UserCA.Pub))
|
||||
s.run("user-ca", "pub-key"),
|
||||
Matches, fmt.Sprintf(".*%v.*", userCA.Pub))
|
||||
}
|
||||
|
||||
func (s *CmdSuite) TestUserCRUD(c *C) {
|
||||
|
@ -114,25 +143,29 @@ func (s *CmdSuite) TestUserCRUD(c *C) {
|
|||
defer fkey.Close()
|
||||
fkey.Write(pub)
|
||||
|
||||
out := s.run("user", "upsert_key", "-user", "alex", "-keyid", "key1", "-key", fkey.Name())
|
||||
out := s.run("user", "upsert-key", "--user", "alex", "--key-id", "key1", "--key", fkey.Name())
|
||||
c.Assert(out, Matches, fmt.Sprintf(".*%v.*", pub))
|
||||
|
||||
c.Assert(trim(string(s.bk.Users["alex"].Keys["key1"].Value)), Equals, trim(out))
|
||||
var keys []backend.AuthorizedKey
|
||||
keys, err = s.bk.GetUserKeys("alex")
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(trim(keys[0].ID), Equals, "key1")
|
||||
c.Assert(trim(string(keys[0].Value)), Equals, trim(out))
|
||||
|
||||
c.Assert(
|
||||
s.run("user", "ls"),
|
||||
Matches, fmt.Sprintf(".*%v.*", "alex"))
|
||||
|
||||
c.Assert(s.run("user", "ls_keys", "-user", "alex"), Matches, fmt.Sprintf(".*%v.*", "key1"))
|
||||
c.Assert(s.run("user", "ls-keys", "--user", "alex"), Matches, fmt.Sprintf(".*%v.*", "key1"))
|
||||
|
||||
c.Assert(
|
||||
s.run("user", "delete", "-user", "alex"),
|
||||
s.run("user", "delete", "--user", "alex"),
|
||||
Matches, fmt.Sprintf(".*%v.*", "alex"))
|
||||
}
|
||||
|
||||
func (s *CmdSuite) TestGenerateToken(c *C) {
|
||||
token := s.run(
|
||||
"token", "generate", "-fqdn", "a.example.com", "-ttl", "100s")
|
||||
"token", "generate", "--fqdn", "a.example.com", "--ttl", "100s")
|
||||
c.Assert(s.asrv.ValidateToken(token, "a.example.com"), IsNil)
|
||||
}
|
||||
|
||||
|
@ -147,17 +180,22 @@ func (s *CmdSuite) TestRemoteCertCRUD(c *C) {
|
|||
defer fkey.Close()
|
||||
fkey.Write(pub)
|
||||
|
||||
out := s.run("remoteca", "upsert", "-id", "id1", "-type", "user", "-fqdn", "example.com", "-path", fkey.Name())
|
||||
out := s.run("remote-ca", "upsert", "--id", "id1", "--type", "user", "--fqdn", "example.com", "--path", fkey.Name())
|
||||
c.Assert(out, Matches, fmt.Sprintf(".*%v.*", "upserted"))
|
||||
c.Assert(trim(string(s.bk.RemoteCerts[0].Value)), Equals, trim(string(pub)))
|
||||
|
||||
out = s.run("remoteca", "ls", "-type", "user")
|
||||
var remoteCerts []backend.RemoteCert
|
||||
remoteCerts, err = s.bk.GetRemoteCerts("user", "example.com")
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(trim(string(remoteCerts[0].Value)), Equals, trim(string(pub)))
|
||||
|
||||
out = s.run("remote-ca", "ls", "--type", "user")
|
||||
c.Assert(out, Matches, fmt.Sprintf(".*%v.*", "example.com"))
|
||||
|
||||
out = s.run("remoteca", "rm", "-type", "user", "-fqdn", "example.com", "-id", "id1")
|
||||
out = s.run("remote-ca", "rm", "--type", "user", "--fqdn", "example.com", "--id", "id1")
|
||||
c.Assert(out, Matches, fmt.Sprintf(".*%v.*", "deleted"))
|
||||
|
||||
c.Assert(len(s.bk.RemoteCerts), Equals, 0)
|
||||
remoteCerts, err = s.bk.GetRemoteCerts("user", "")
|
||||
c.Assert(len(remoteCerts), Equals, 0)
|
||||
}
|
||||
|
||||
func trim(val string) string {
|
||||
|
|
|
@ -3,25 +3,10 @@ package command
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gravitational/teleport/Godeps/_workspace/src/github.com/codegangsta/cli"
|
||||
"github.com/gravitational/teleport/Godeps/_workspace/src/github.com/mailgun/lemma/secret"
|
||||
)
|
||||
|
||||
func newSecretCommand(c *Command) cli.Command {
|
||||
return cli.Command{
|
||||
Name: "secret",
|
||||
Usage: "Operations with secret tokens",
|
||||
Subcommands: []cli.Command{
|
||||
{
|
||||
Name: "new",
|
||||
Usage: "Generate new secret key",
|
||||
Action: c.newKey,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (cmd *Command) newKey(c *cli.Context) {
|
||||
func (cmd *Command) newKey() {
|
||||
key, err := secret.NewKey()
|
||||
if err != nil {
|
||||
cmd.printError(fmt.Errorf("failed to generate key: %v", err))
|
||||
|
|
|
@ -4,40 +4,21 @@ import (
|
|||
"fmt"
|
||||
"io/ioutil"
|
||||
"time"
|
||||
|
||||
"github.com/gravitational/teleport/Godeps/_workspace/src/github.com/codegangsta/cli"
|
||||
)
|
||||
|
||||
func newTokenCommand(c *Command) cli.Command {
|
||||
return cli.Command{
|
||||
Name: "token",
|
||||
Usage: "Generates provisioning tokens",
|
||||
Subcommands: []cli.Command{
|
||||
{
|
||||
Name: "generate",
|
||||
Usage: "Generate provisioning token for server with fqdn",
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{Name: "fqdn", Usage: "FQDN of the server"},
|
||||
cli.DurationFlag{Name: "ttl", Value: 120 * time.Second, Usage: "TTL"},
|
||||
cli.StringFlag{Name: "output", Usage: "Optional output file"},
|
||||
},
|
||||
Action: c.generateToken,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
func (cmd *Command) generateToken(fqdn string, ttl time.Duration,
|
||||
output string) {
|
||||
|
||||
func (cmd *Command) generateToken(c *cli.Context) {
|
||||
token, err := cmd.client.GenerateToken(c.String("fqdn"), c.Duration("ttl"))
|
||||
token, err := cmd.client.GenerateToken(fqdn, ttl)
|
||||
if err != nil {
|
||||
cmd.printError(err)
|
||||
return
|
||||
}
|
||||
if c.String("output") == "" {
|
||||
if output == "" {
|
||||
fmt.Fprintf(cmd.out, token)
|
||||
return
|
||||
}
|
||||
err = ioutil.WriteFile(c.String("output"), []byte(token), 0644)
|
||||
err = ioutil.WriteFile(output, []byte(token), 0644)
|
||||
if err != nil {
|
||||
cmd.printError(err)
|
||||
}
|
||||
|
|
|
@ -2,79 +2,29 @@ package command
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/gravitational/teleport/Godeps/_workspace/src/github.com/buger/goterm"
|
||||
"github.com/gravitational/teleport/Godeps/_workspace/src/github.com/codegangsta/cli"
|
||||
"github.com/gravitational/teleport/backend"
|
||||
)
|
||||
|
||||
func newUserCommand(c *Command) cli.Command {
|
||||
return cli.Command{
|
||||
Name: "user",
|
||||
Usage: "Operations with registered users",
|
||||
Subcommands: []cli.Command{
|
||||
{
|
||||
Name: "ls",
|
||||
Usage: "List users registered in teleport",
|
||||
Action: c.getUsers,
|
||||
},
|
||||
{
|
||||
Name: "delete",
|
||||
Usage: "Delete user",
|
||||
Action: c.deleteUser,
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{Name: "user", Usage: "User to delete"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "upsert_key",
|
||||
Usage: "Grant access to the user key, returns signed certificate",
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{Name: "user", Usage: "User holding the key"},
|
||||
cli.StringFlag{Name: "keyid", Usage: "SSH key ID"},
|
||||
cli.StringFlag{Name: "key", Usage: "Path to public key"},
|
||||
cli.DurationFlag{Name: "ttl", Usage: "Access time to live, certificate and access entry will expire when set"},
|
||||
},
|
||||
Action: c.upsertKey,
|
||||
},
|
||||
{
|
||||
Name: "ls_keys",
|
||||
Usage: "List user's keys registered in teleport",
|
||||
Action: c.getUserKeys,
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{Name: "user", Usage: "User to list keys form"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "set_pass",
|
||||
Usage: "Set user password",
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{Name: "user", Usage: "User name"},
|
||||
cli.StringFlag{Name: "pass", Usage: "Password"},
|
||||
},
|
||||
Action: c.setPass,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (cmd *Command) setPass(c *cli.Context) {
|
||||
err := cmd.client.UpsertPassword(c.String("user"), []byte(c.String("pass")))
|
||||
func (cmd *Command) setPass(user, pass string) {
|
||||
err := cmd.client.UpsertPassword(user, []byte(pass))
|
||||
if err != nil {
|
||||
cmd.printError(err)
|
||||
return
|
||||
}
|
||||
cmd.printOK("password has been set for user '%v'", c.String("user"))
|
||||
cmd.printOK("password has been set for user '%v'", user)
|
||||
}
|
||||
|
||||
func (cmd *Command) upsertKey(c *cli.Context) {
|
||||
bytes, err := cmd.readInput(c.String("key"))
|
||||
func (cmd *Command) upsertKey(user, keyID, key string, ttl time.Duration) {
|
||||
bytes, err := cmd.readInput(key)
|
||||
if err != nil {
|
||||
cmd.printError(err)
|
||||
return
|
||||
}
|
||||
signed, err := cmd.client.UpsertUserKey(
|
||||
c.String("user"), backend.AuthorizedKey{ID: c.String("keyid"), Value: bytes}, c.Duration("ttl"))
|
||||
user, backend.AuthorizedKey{ID: keyID, Value: bytes}, ttl)
|
||||
if err != nil {
|
||||
cmd.printError(err)
|
||||
return
|
||||
|
@ -82,15 +32,15 @@ func (cmd *Command) upsertKey(c *cli.Context) {
|
|||
fmt.Fprintf(cmd.out, "%v", string(signed))
|
||||
}
|
||||
|
||||
func (cmd *Command) deleteUser(c *cli.Context) {
|
||||
if err := cmd.client.DeleteUser(c.String("user")); err != nil {
|
||||
func (cmd *Command) deleteUser(user string) {
|
||||
if err := cmd.client.DeleteUser(user); err != nil {
|
||||
cmd.printError(err)
|
||||
return
|
||||
}
|
||||
cmd.printOK("User %v deleted", c.String("user"))
|
||||
cmd.printOK("User %v deleted", user)
|
||||
}
|
||||
|
||||
func (cmd *Command) getUsers(c *cli.Context) {
|
||||
func (cmd *Command) getUsers() {
|
||||
users, err := cmd.client.GetUsers()
|
||||
if err != nil {
|
||||
cmd.printError(err)
|
||||
|
@ -100,8 +50,8 @@ func (cmd *Command) getUsers(c *cli.Context) {
|
|||
fmt.Fprintf(cmd.out, usersView(users))
|
||||
}
|
||||
|
||||
func (cmd *Command) getUserKeys(c *cli.Context) {
|
||||
keys, err := cmd.client.GetUserKeys(c.String("user"))
|
||||
func (cmd *Command) getUserKeys(user string) {
|
||||
keys, err := cmd.client.GetUserKeys(user)
|
||||
if err != nil {
|
||||
cmd.printError(err)
|
||||
return
|
||||
|
|
Loading…
Reference in a new issue