Merge pull request #3172 from filecoin-project/feat/lotus-shed-jwt

lotus-shed: add simple jwt creation support
This commit is contained in:
Łukasz Magiera 2020-08-19 23:32:01 +02:00 committed by GitHub
commit ed098390cb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 95 additions and 4 deletions

89
cmd/lotus-shed/jwt.go Normal file
View 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)
},
}

View File

@ -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
} }

View File

@ -19,6 +19,7 @@ func main() {
base16Cmd, base16Cmd,
bitFieldCmd, bitFieldCmd,
keyinfoCmd, keyinfoCmd,
jwtCmd,
noncefix, noncefix,
bigIntParseCmd, bigIntParseCmd,
staterootCmd, staterootCmd,

View File

@ -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,
} }