From 3d7a094cb85168895b792b4ab1a9c1590468d3bb Mon Sep 17 00:00:00 2001 From: William Petit Date: Fri, 25 Aug 2023 12:02:02 -0600 Subject: [PATCH] feat(auth): store and retrieve auth token from home directory by default (#2) --- Makefile | 2 +- doc/tutorials/fr/first-steps.md | 4 +- internal/command/api/flag/flag.go | 42 +++++++++++--------- internal/command/server/auth/create_token.go | 29 +++++++++++++- 4 files changed, 56 insertions(+), 21 deletions(-) diff --git a/Makefile b/Makefile index 9d762cc..942909f 100644 --- a/Makefile +++ b/Makefile @@ -118,7 +118,7 @@ gitea-release: .mktools tools/gitea-release/bin/gitea-release.sh goreleaser chan tools/gitea-release/bin/gitea-release.sh .emissary-token: - $(MAKE) run-emissary-server EMISSARY_CMD="--debug --config tmp/server.yml server auth create-token --role writer > .emissary-token" + $(MAKE) run-emissary-server EMISSARY_CMD="--debug --config tmp/server.yml server auth create-token --role writer --output .emissary-token" AGENT_ID ?= 1 diff --git a/doc/tutorials/fr/first-steps.md b/doc/tutorials/fr/first-steps.md index c11b32b..4eb7de2 100644 --- a/doc/tutorials/fr/first-steps.md +++ b/doc/tutorials/fr/first-steps.md @@ -80,9 +80,11 @@ 5. Créer un jeton d'administration: ```shell - sudo emissary --workdir /usr/share/emissary --config /etc/emissary/server.yml server auth create-token --role writer --subject $(whoami) > .emissary-token + sudo emissary --workdir /usr/share/emissary --config /etc/emissary/server.yml server auth create-token --role writer --subject $(whoami) ``` + > **Note** Le jeton sera stocké dans le répertoire `$HOME/.config/emissary`. + 6. Vérifier l'authentification sur l'API: ```shell diff --git a/internal/command/api/flag/flag.go b/internal/command/api/flag/flag.go index 5480d7b..270aa97 100644 --- a/internal/command/api/flag/flag.go +++ b/internal/command/api/flag/flag.go @@ -2,7 +2,6 @@ package flag import ( "fmt" - "io/ioutil" "os" "strings" @@ -12,6 +11,11 @@ import ( "github.com/urfave/cli/v2" ) +const ( + AuthTokenDefaultHomePath = "$HOME/.config/emissary/auth-token" + AuthTokenDefaultLocalPath = ".emissary-token" +) + func ComposeFlags(flags ...cli.Flag) []cli.Flag { baseFlags := []cli.Flag{ &cli.StringFlag{ @@ -37,10 +41,10 @@ func ComposeFlags(flags ...cli.Flag) []cli.Flag { Aliases: []string{"t"}, Usage: "use `TOKEN` as authentication token", }, - &cli.StringFlag{ + &cli.StringSliceFlag{ Name: "token-file", Usage: "use `TOKEN_FILE` as file containing the authentication token", - Value: ".emissary-token", + Value: cli.NewStringSlice(AuthTokenDefaultLocalPath, AuthTokenDefaultHomePath), TakesFile: true, }, } @@ -55,14 +59,14 @@ type BaseFlags struct { Format format.Format OutputMode format.OutputMode Token string - TokenFile string + TokenFiles []string } func GetBaseFlags(ctx *cli.Context) *BaseFlags { serverURL := ctx.String("server") rawFormat := ctx.String("format") rawOutputMode := ctx.String("output-mode") - tokenFile := ctx.String("token-file") + tokenFiles := ctx.StringSlice("token-file") token := ctx.String("token") return &BaseFlags{ @@ -70,7 +74,7 @@ func GetBaseFlags(ctx *cli.Context) *BaseFlags { Format: format.Format(rawFormat), OutputMode: format.OutputMode(rawOutputMode), Token: token, - TokenFile: tokenFile, + TokenFiles: tokenFiles, } } @@ -79,18 +83,20 @@ func GetToken(flags *BaseFlags) (string, error) { return flags.Token, nil } - if flags.TokenFile == "" { - return "", nil + for _, tokenFile := range flags.TokenFiles { + tokenFile = os.ExpandEnv(tokenFile) + + rawToken, err := os.ReadFile(tokenFile) + if err != nil && !errors.Is(err, os.ErrNotExist) { + return "", errors.WithStack(err) + } + + if rawToken == nil { + continue + } + + return strings.TrimSpace(string(rawToken)), nil } - rawToken, err := ioutil.ReadFile(flags.TokenFile) - if err != nil && !errors.Is(err, os.ErrNotExist) { - return "", errors.WithStack(err) - } - - if rawToken == nil { - return "", nil - } - - return strings.TrimSpace(string(rawToken)), nil + return "", nil } diff --git a/internal/command/server/auth/create_token.go b/internal/command/server/auth/create_token.go index fdf2a8d..8c8554d 100644 --- a/internal/command/server/auth/create_token.go +++ b/internal/command/server/auth/create_token.go @@ -2,8 +2,11 @@ package auth import ( "fmt" + "os" + "path/filepath" "forge.cadoles.com/Cadoles/emissary/internal/auth/thirdparty" + "forge.cadoles.com/Cadoles/emissary/internal/command/api/flag" "forge.cadoles.com/Cadoles/emissary/internal/command/common" "forge.cadoles.com/Cadoles/emissary/internal/jwk" "github.com/lithammer/shortuuid/v4" @@ -26,6 +29,13 @@ func CreateTokenCommand() *cli.Command { Usage: "associate `SUBJECT` to the token", Value: fmt.Sprintf("user-%s", shortuuid.New()), }, + &cli.StringFlag{ + Name: "output", + Aliases: []string{"o"}, + TakesFile: true, + Usage: "output token to `OUTPUT` (or '-' to print to stdout)", + Value: flag.AuthTokenDefaultHomePath, + }, }, Action: func(ctx *cli.Context) error { conf, err := common.LoadConfig(ctx) @@ -35,6 +45,7 @@ func CreateTokenCommand() *cli.Command { subject := ctx.String("subject") role := ctx.String("role") + output := ctx.String("output") localAuth := conf.Server.Auth.Local if localAuth == nil { @@ -51,7 +62,23 @@ func CreateTokenCommand() *cli.Command { return errors.WithStack(err) } - fmt.Println(token) + output = os.ExpandEnv(output) + + if output == "-" { + fmt.Println(token) + } else { + outputDirectory := filepath.Dir(output) + + if err := os.MkdirAll(outputDirectory, os.FileMode(0o700)); err != nil { + return errors.WithStack(err) + } + + if err := os.WriteFile(output, []byte(token), os.FileMode(0o600)); err != nil { + return errors.WithStack(err) + } + + fmt.Printf("Token written to '%s'.\n", output) + } return nil },