mirror of
https://github.com/davidallendj/magellan.git
synced 2025-12-20 11:37:01 -07:00
Added login flow to get access token
This commit is contained in:
parent
6b6b694f42
commit
7760857ae5
3 changed files with 127 additions and 1 deletions
84
cmd/login.go
Normal file
84
cmd/login.go
Normal file
|
|
@ -0,0 +1,84 @@
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
magellan "github.com/OpenCHAMI/magellan/internal"
|
||||||
|
"github.com/lestrrat-go/jwx/jwt"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
loginUrl string
|
||||||
|
targetHost string
|
||||||
|
targetPort int
|
||||||
|
tokenPath string
|
||||||
|
forceLogin bool
|
||||||
|
noBrowser bool
|
||||||
|
)
|
||||||
|
|
||||||
|
var loginCmd = &cobra.Command{
|
||||||
|
Use: "login",
|
||||||
|
Short: "Log in with identity provider for access token",
|
||||||
|
Long: "",
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
// check if we have a valid JWT before starting login
|
||||||
|
if !forceLogin {
|
||||||
|
// try getting the access token from env var
|
||||||
|
testToken := []byte(os.Getenv("OCHAMI_ACCESS_TOKEN"))
|
||||||
|
if testToken == nil {
|
||||||
|
// try reading access token from a file
|
||||||
|
b, err := os.ReadFile(tokenPath)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("failed to read access token from file: %v\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
testToken = b
|
||||||
|
}
|
||||||
|
// parse into jwt.Token to validate
|
||||||
|
token, err := jwt.Parse(testToken)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("failed to parse access token contents: %v\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// check if the token is invalid and we need a new one
|
||||||
|
err = jwt.Validate(token)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("failed to validate access token...fetching a new one")
|
||||||
|
} else {
|
||||||
|
fmt.Printf("found a valid token...skipping login (use the '-f/--force' flag to login anyway)")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// start the login flow
|
||||||
|
var err error
|
||||||
|
accessToken, err = magellan.Login(loginUrl, targetHost, targetPort)
|
||||||
|
if errors.Is(err, http.ErrServerClosed) {
|
||||||
|
fmt.Printf("\n=========================================\nServer closed.\n=========================================\n\n")
|
||||||
|
} else if err != nil {
|
||||||
|
fmt.Printf("failed to start server: %v\n", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we got a new token successfully, save it to the token path
|
||||||
|
if accessToken != "" && tokenPath != "" {
|
||||||
|
err := os.WriteFile(tokenPath, []byte(accessToken), os.ModePerm)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("failed to write access token to file: %v\n", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
loginCmd.Flags().StringVar(&loginUrl, "url", "http://127.0.0.1:3333/login", "set the login URL")
|
||||||
|
loginCmd.Flags().StringVar(&targetHost, "target-host", "127.0.0.1", "set the target host to return the access code")
|
||||||
|
loginCmd.Flags().IntVar(&targetPort, "target-port", 5000, "set the target host to return the access code")
|
||||||
|
loginCmd.Flags().BoolVarP(&forceLogin, "force", "f", false, "start the login process even with a valid token")
|
||||||
|
loginCmd.Flags().StringVar(&tokenPath, "token-path", ".ochami-token", "set the path the load/save the access token")
|
||||||
|
loginCmd.Flags().BoolVar(&noBrowser, "no-browser", false, "prevent the default browser from being opened automatically")
|
||||||
|
rootCmd.AddCommand(loginCmd)
|
||||||
|
}
|
||||||
|
|
@ -8,6 +8,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
accessToken string
|
||||||
timeout int
|
timeout int
|
||||||
threads int
|
threads int
|
||||||
ports []int
|
ports []int
|
||||||
|
|
@ -21,7 +22,7 @@ var (
|
||||||
drivers []string
|
drivers []string
|
||||||
preferredDriver string
|
preferredDriver string
|
||||||
ipmitoolPath string
|
ipmitoolPath string
|
||||||
outputPath string
|
outputPath string
|
||||||
verbose bool
|
verbose bool
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
41
internal/login.go
Normal file
41
internal/login.go
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
package magellan
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/go-chi/chi/v5"
|
||||||
|
"github.com/pkg/browser"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Login(loginUrl string, targetHost string, targetPort int) (string, error) {
|
||||||
|
var accessToken string
|
||||||
|
|
||||||
|
// check and make sure the login URL isn't empty
|
||||||
|
if loginUrl == "" {
|
||||||
|
return "", fmt.Errorf("no login URL provided")
|
||||||
|
}
|
||||||
|
|
||||||
|
// if a target host and port are provided, then add to URL
|
||||||
|
if targetHost != "" && targetPort > 0 && targetPort < 65536 {
|
||||||
|
loginUrl += fmt.Sprintf("?target=http://%s:%d", targetHost, targetPort)
|
||||||
|
}
|
||||||
|
|
||||||
|
// open browser with the specified URL
|
||||||
|
err := browser.OpenURL(loginUrl)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("failed to open browser: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// start a temporary server to listen for token
|
||||||
|
s := http.Server{
|
||||||
|
Addr: fmt.Sprintf("%s:%d", targetHost, targetPort),
|
||||||
|
}
|
||||||
|
r := chi.NewRouter()
|
||||||
|
r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// try and extract access token from headers
|
||||||
|
accessToken = r.Header.Get("access_token")
|
||||||
|
s.Close()
|
||||||
|
})
|
||||||
|
return accessToken, s.ListenAndServe()
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue