package main import ( "crypto/rand" "encoding/hex" "encoding/json" "fmt" "io" "io/ioutil" "os" "github.com/gbrlsnchs/jwt/v3" "github.com/urfave/cli/v2" "github.com/filecoin-project/lotus/api/apistruct" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/node/modules" ) var jwtCmd = &cli.Command{ Name: "jwt", Usage: "work with lotus jwt secrets and tokens", Description: `The subcommands of jwt provide helpful tools for working with jwt files without having to run the lotus daemon.`, Subcommands: []*cli.Command{ jwtNewCmd, }, } var jwtNewCmd = &cli.Command{ Name: "new", Usage: "create a new jwt secret and token for lotus", ArgsUsage: "", Description: `Jwt tokens are used to authenticate api requests to the lotus daemon. The created jwt token have full privileges and should not be shared.`, Flags: []cli.Flag{}, Action: func(cctx *cli.Context) error { if !cctx.Args().Present() { return fmt.Errorf("please specify a name") } keyName := cctx.Args().First() sk, err := ioutil.ReadAll(io.LimitReader(rand.Reader, 32)) if err != nil { return err } keyInfo := types.KeyInfo{ Type: modules.KTJwtHmacSecret, PrivateKey: sk, } p := modules.JwtPayload{ Allow: apistruct.AllPermissions, } token, err := jwt.Sign(&p, jwt.NewHS256(keyInfo.PrivateKey)) if err != nil { return err } filename := fmt.Sprintf("jwt-%s.jwts", keyName) file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600) if err != nil { return err } defer func() { if err := file.Close(); err != nil { log.Warnf("failed to close output file: %w", err) } }() bytes, err := json.Marshal(keyInfo) if err != nil { return err } encoded := hex.EncodeToString(bytes) if _, err := file.Write([]byte(encoded)); err != nil { return err } filenameToken := fmt.Sprintf("jwt-%s.token", keyName) return ioutil.WriteFile(filenameToken, token, 0600) }, }