2023-03-07 23:10:42 +01:00
|
|
|
package auth
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2023-08-25 20:02:02 +02:00
|
|
|
"os"
|
|
|
|
"path/filepath"
|
2023-03-07 23:10:42 +01:00
|
|
|
|
2024-02-27 14:14:30 +01:00
|
|
|
"forge.cadoles.com/Cadoles/emissary/internal/auth/user"
|
|
|
|
"forge.cadoles.com/Cadoles/emissary/internal/command/client/flag"
|
2023-03-07 23:10:42 +01:00
|
|
|
"forge.cadoles.com/Cadoles/emissary/internal/command/common"
|
2024-02-26 18:20:40 +01:00
|
|
|
"forge.cadoles.com/Cadoles/emissary/internal/datastore"
|
2023-03-07 23:10:42 +01:00
|
|
|
"forge.cadoles.com/Cadoles/emissary/internal/jwk"
|
2024-02-27 14:14:30 +01:00
|
|
|
"github.com/google/uuid"
|
2023-03-07 23:10:42 +01:00
|
|
|
"github.com/pkg/errors"
|
|
|
|
"github.com/urfave/cli/v2"
|
|
|
|
)
|
|
|
|
|
|
|
|
func CreateTokenCommand() *cli.Command {
|
|
|
|
return &cli.Command{
|
|
|
|
Name: "create-token",
|
2023-03-13 10:44:58 +01:00
|
|
|
Usage: "Create a new authentication token",
|
2023-03-07 23:10:42 +01:00
|
|
|
Flags: []cli.Flag{
|
|
|
|
&cli.StringFlag{
|
|
|
|
Name: "role",
|
2024-02-27 14:14:30 +01:00
|
|
|
Usage: fmt.Sprintf("associate `ROLE` to the token (available: %v)", []user.Role{user.RoleReader, user.RoleWriter, user.RoleAdmin}),
|
|
|
|
Value: string(user.RoleReader),
|
2023-03-07 23:10:42 +01:00
|
|
|
},
|
|
|
|
&cli.StringFlag{
|
|
|
|
Name: "subject",
|
|
|
|
Usage: "associate `SUBJECT` to the token",
|
2024-02-27 14:14:30 +01:00
|
|
|
Value: fmt.Sprintf("user-%s", uuid.New().String()),
|
2023-03-07 23:10:42 +01:00
|
|
|
},
|
2024-02-26 18:20:40 +01:00
|
|
|
&cli.StringFlag{
|
2024-02-27 14:14:30 +01:00
|
|
|
Name: "tenant",
|
|
|
|
Usage: "associate `TENANT` to the token",
|
|
|
|
Value: "00000000-0000-0000-0000-000000000000",
|
2024-02-26 18:20:40 +01:00
|
|
|
},
|
2023-08-25 20:02:02 +02:00
|
|
|
&cli.StringFlag{
|
|
|
|
Name: "output",
|
|
|
|
Aliases: []string{"o"},
|
|
|
|
TakesFile: true,
|
|
|
|
Usage: "output token to `OUTPUT` (or '-' to print to stdout)",
|
|
|
|
Value: flag.AuthTokenDefaultHomePath,
|
|
|
|
},
|
2023-03-07 23:10:42 +01:00
|
|
|
},
|
|
|
|
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")
|
2024-02-26 18:20:40 +01:00
|
|
|
tenant := ctx.String("tenant")
|
2023-03-07 23:10:42 +01:00
|
|
|
role := ctx.String("role")
|
2023-08-25 20:02:02 +02:00
|
|
|
output := ctx.String("output")
|
2023-03-07 23:10:42 +01:00
|
|
|
|
2023-07-26 15:14:49 +02:00
|
|
|
localAuth := conf.Server.Auth.Local
|
|
|
|
if localAuth == nil {
|
|
|
|
return errors.New("local auth is disabled")
|
|
|
|
}
|
|
|
|
|
|
|
|
key, err := jwk.LoadOrGenerate(string(localAuth.PrivateKeyPath), jwk.DefaultKeySize)
|
2023-03-07 23:10:42 +01:00
|
|
|
if err != nil {
|
|
|
|
return errors.WithStack(err)
|
|
|
|
}
|
|
|
|
|
2024-02-27 14:14:30 +01:00
|
|
|
token, err := user.GenerateToken(ctx.Context, key, datastore.TenantID(tenant), subject, user.Role(role))
|
2023-03-07 23:10:42 +01:00
|
|
|
if err != nil {
|
|
|
|
return errors.WithStack(err)
|
|
|
|
}
|
|
|
|
|
2023-08-25 20:02:02 +02:00
|
|
|
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)
|
|
|
|
}
|
2023-03-07 23:10:42 +01:00
|
|
|
|
|
|
|
return nil
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|