mirror of
https://codeberg.org/shroff/phylum.git
synced 2026-05-12 07:08:44 -05:00
[server][cli] Generate API Keys/Tokens from CLI
This commit is contained in:
@@ -12,8 +12,10 @@ import (
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
var apiTokenEncoder = base64.StdEncoding.WithPadding(base64.NoPadding)
|
||||
|
||||
func ReadEncodedAPIKey(db db.Handler, encodedKey string) (Auth, error) {
|
||||
if b, err := base64.StdEncoding.DecodeString(encodedKey); err != nil {
|
||||
if b, err := apiTokenEncoder.DecodeString(encodedKey); err != nil {
|
||||
return nil, ErrCredentialsInvalid
|
||||
} else if len(b) < 16 {
|
||||
return nil, ErrCredentialsInvalid
|
||||
@@ -69,6 +71,6 @@ func GenerateEncodedAPIKey(db db.TxHandler, userID int32, validity time.Duration
|
||||
if id, key, err := GenerateAPIKey(db, userID, validity, description, scopes); err != nil {
|
||||
return "", err
|
||||
} else {
|
||||
return base64.StdEncoding.EncodeToString(append(id[:], key...)), nil
|
||||
return apiTokenEncoder.EncodeToString(append(id[:], key...)), nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ VALUES (@token_id, @expires, @token_hash, @oidc_provider, @oidc_client_type, @oi
|
||||
q.Add("client_id", clientID)
|
||||
q.Add("response_type", "code")
|
||||
q.Add("scope", "openid email profile")
|
||||
q.Add("state", tokenEncoder.EncodeToString(append(tokenID[:], token...)))
|
||||
q.Add("state", TokenEncoder.EncodeToString(append(tokenID[:], token...)))
|
||||
q.Add("redirect_uri", redirectURI)
|
||||
q.Add("code_challenge", codeChallenge)
|
||||
q.Add("code_challenge_method", "S256")
|
||||
@@ -70,7 +70,7 @@ func OpenIDValidateAuthCode(d db.Handler, state, authCode, redirectURI string) (
|
||||
|
||||
var tokenID uuid.UUID
|
||||
var tokenHash []byte
|
||||
if b, err := tokenEncoder.DecodeString(state); err != nil {
|
||||
if b, err := TokenEncoder.DecodeString(state); err != nil {
|
||||
return OpenIDClientNone, ErrTokenInvalid
|
||||
} else if len(b) < 16 {
|
||||
return OpenIDClientNone, ErrTokenInvalid
|
||||
|
||||
@@ -12,10 +12,10 @@ import (
|
||||
"github.com/jackc/pgx/v5"
|
||||
)
|
||||
|
||||
var tokenEncoder = base32.StdEncoding.WithPadding(base32.NoPadding)
|
||||
var TokenEncoder = base32.StdEncoding.WithPadding(base32.NoPadding)
|
||||
|
||||
func PerformTokenLogin(db db.TxHandler, encodedToken string) (Auth, string, error) {
|
||||
if b, err := tokenEncoder.DecodeString(encodedToken); err != nil {
|
||||
if b, err := TokenEncoder.DecodeString(encodedToken); err != nil {
|
||||
return nil, "", ErrCredentialsInvalid
|
||||
} else if len(b) < 16 {
|
||||
return nil, "", ErrCredentialsInvalid
|
||||
|
||||
@@ -2,6 +2,7 @@ package user
|
||||
|
||||
import (
|
||||
"codeberg.org/shroff/phylum/server/internal/command/user/bookmarks"
|
||||
"codeberg.org/shroff/phylum/server/internal/command/user/keys"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@@ -12,6 +13,7 @@ func SetupCommand() *cobra.Command {
|
||||
}
|
||||
cmd.PersistentFlags().StringP("user-email", "u", "", "User")
|
||||
cmd.AddCommand([]*cobra.Command{
|
||||
keys.SetupCommand(),
|
||||
bookmarks.SetupCommand(),
|
||||
}...)
|
||||
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
package keys
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"codeberg.org/shroff/phylum/server/internal/auth"
|
||||
"codeberg.org/shroff/phylum/server/internal/command/common"
|
||||
"codeberg.org/shroff/phylum/server/internal/db"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func SetupCommand() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "keys",
|
||||
Short: "Manager API Keys",
|
||||
}
|
||||
|
||||
cmd.AddCommand(
|
||||
setupGenerateCommand(),
|
||||
)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func setupGenerateCommand() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "generate",
|
||||
Short: "Generate New API Key/Token",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
u := common.User(cmd)
|
||||
validity, _ := cmd.Flags().GetDuration("validity")
|
||||
description, _ := cmd.Flags().GetString("description")
|
||||
if description == "" {
|
||||
description = "Generated via CLI on " + time.Now().Format(time.DateTime)
|
||||
}
|
||||
var scopes []string
|
||||
if len(scopes) == 0 {
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
name, _ := cmd.Flags().GetString("name")
|
||||
if name == "" {
|
||||
fmt.Print("Comma-separated scopes [*]: ")
|
||||
if val, err := reader.ReadString('\n'); err != nil {
|
||||
fmt.Println("failed to read scopes: " + err.Error())
|
||||
os.Exit(1)
|
||||
} else if len(strings.TrimSpace(val)) == 0 {
|
||||
scopes = []string{"*"}
|
||||
} else {
|
||||
scopes = strings.Split(val, ",")
|
||||
for i, s := range scopes {
|
||||
scopes[i] = strings.TrimSpace(s)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := db.Get(context.Background()).RunInTx(func(db db.TxHandler) error {
|
||||
if token, _ := cmd.Flags().GetBool("token"); token {
|
||||
if token, err := auth.GenerateEncodedAPIKey(db, u.ID, validity, description, scopes); err != nil {
|
||||
return err
|
||||
} else {
|
||||
fmt.Println(token)
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
if id, key, err := auth.GenerateAPIKey(db, u.ID, validity, description, scopes); err != nil {
|
||||
return err
|
||||
} else {
|
||||
fmt.Println("Key ID:", id.String())
|
||||
fmt.Println(" Key:", auth.TokenEncoder.EncodeToString(key))
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}); err != nil {
|
||||
fmt.Println("unable to generate API key: " + err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().BoolP("token", "t", false, "Generate API token instead of ID:Key pair")
|
||||
cmd.Flags().Duration("validity", time.Duration(0), "Validity of API Key (0 means never)")
|
||||
cmd.Flags().String("description", "", "Validity of API Key (0 means never)")
|
||||
cmd.Flags().StringSlice("scopes", []string{}, "Scopes")
|
||||
return cmd
|
||||
}
|
||||
Reference in New Issue
Block a user