Merge pull request #3172 from filecoin-project/feat/lotus-shed-jwt
lotus-shed: add simple jwt creation support
This commit is contained in:
commit
ed098390cb
89
cmd/lotus-shed/jwt.go
Normal file
89
cmd/lotus-shed/jwt.go
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
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: "<name>",
|
||||||
|
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)
|
||||||
|
},
|
||||||
|
}
|
@ -330,7 +330,7 @@ var keyinfoNewCmd = &cli.Command{
|
|||||||
filename = strings.ReplaceAll(filename, "<addr>", keyAddr)
|
filename = strings.ReplaceAll(filename, "<addr>", keyAddr)
|
||||||
filename = strings.ReplaceAll(filename, "<type>", keyType)
|
filename = strings.ReplaceAll(filename, "<type>", keyType)
|
||||||
|
|
||||||
file, err := os.Create(filename)
|
file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ func main() {
|
|||||||
base16Cmd,
|
base16Cmd,
|
||||||
bitFieldCmd,
|
bitFieldCmd,
|
||||||
keyinfoCmd,
|
keyinfoCmd,
|
||||||
|
jwtCmd,
|
||||||
noncefix,
|
noncefix,
|
||||||
bigIntParseCmd,
|
bigIntParseCmd,
|
||||||
staterootCmd,
|
staterootCmd,
|
||||||
|
@ -37,8 +37,9 @@ func RecordValidator(ps peerstore.Peerstore) record.Validator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const JWTSecretName = "auth-jwt-private" //nolint:gosec
|
const JWTSecretName = "auth-jwt-private" //nolint:gosec
|
||||||
|
const KTJwtHmacSecret = "jwt-hmac-secret"
|
||||||
|
|
||||||
type jwtPayload struct {
|
type JwtPayload struct {
|
||||||
Allow []auth.Permission
|
Allow []auth.Permission
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,7 +55,7 @@ func APISecret(keystore types.KeyStore, lr repo.LockedRepo) (*dtypes.APIAlg, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
key = types.KeyInfo{
|
key = types.KeyInfo{
|
||||||
Type: "jwt-hmac-secret",
|
Type: KTJwtHmacSecret,
|
||||||
PrivateKey: sk,
|
PrivateKey: sk,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,7 +64,7 @@ func APISecret(keystore types.KeyStore, lr repo.LockedRepo) (*dtypes.APIAlg, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: make this configurable
|
// TODO: make this configurable
|
||||||
p := jwtPayload{
|
p := JwtPayload{
|
||||||
Allow: apistruct.AllPermissions,
|
Allow: apistruct.AllPermissions,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user