package auth import ( "fmt" "os" "path/filepath" "forge.cadoles.com/Cadoles/emissary/internal/auth/user" "forge.cadoles.com/Cadoles/emissary/internal/command/client/flag" "forge.cadoles.com/Cadoles/emissary/internal/command/common" "forge.cadoles.com/Cadoles/emissary/internal/datastore" "forge.cadoles.com/Cadoles/emissary/internal/jwk" "github.com/google/uuid" "github.com/pkg/errors" "github.com/urfave/cli/v2" ) func CreateTokenCommand() *cli.Command { return &cli.Command{ Name: "create-token", Usage: "Create a new authentication token", Flags: []cli.Flag{ &cli.StringFlag{ Name: "role", Usage: fmt.Sprintf("associate `ROLE` to the token (available: %v)", []user.Role{user.RoleReader, user.RoleWriter, user.RoleAdmin}), Value: string(user.RoleReader), }, &cli.StringFlag{ Name: "subject", Usage: "associate `SUBJECT` to the token", Value: fmt.Sprintf("user-%s", uuid.New().String()), }, &cli.StringFlag{ Name: "tenant", Usage: "associate `TENANT` to the token", Value: "00000000-0000-0000-0000-000000000000", }, &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) if err != nil { return errors.Wrap(err, "Could not load configuration") } subject := ctx.String("subject") tenant := ctx.String("tenant") role := ctx.String("role") output := ctx.String("output") localAuth := conf.Server.Auth.Local if localAuth == nil { return errors.New("local auth is disabled") } key, err := jwk.LoadOrGenerate(string(localAuth.PrivateKeyPath), jwk.DefaultKeySize) if err != nil { return errors.WithStack(err) } token, err := user.GenerateToken(ctx.Context, key, datastore.TenantID(tenant), subject, user.Role(role)) if err != nil { return errors.WithStack(err) } 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 }, } }