Skip to content

Commit

Permalink
Derive user automatically or prompt (#15)
Browse files Browse the repository at this point in the history
  • Loading branch information
castrapel authored Nov 4, 2020
1 parent 561b6e7 commit 45dc7f2
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 10 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ You can also specify a config file as a CLI arg:
weep --config somethingdifferent.yaml list
```

Weep supports authenticating to ConsoleMe in either a standalone challenge mode (ConsoleMe will authenticate the user
according to its settings), or mutual TLS (ConsoleMe has to be configured to accept mutual TLS).

In challenge mode, Weep will prompt the user for their username the first time they authenticate, and then attempt to
derive their username from their valid/expired jwt on subsequent attempts. You can also specify the desired username
in weep's configuration under the `challenge_settings.user` setting as seen in `example-config.yaml`.


## Routing traffic
Expand Down
61 changes: 53 additions & 8 deletions challenge/challenge.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/manifoldco/promptui"
"io/ioutil"
"net/http"
"net/http/cookiejar"
Expand All @@ -40,7 +41,12 @@ import (
)

func NewHTTPClient(consolemeUrl string) (*http.Client, error) {
if !HasValidJwt() {
existingChallengeBody, err := getChallenge()
if err != nil {
log.Debugf("unable to read existing challenge file: %v", err)

}
if !HasValidJwt(existingChallengeBody) {
return nil, errors.New("Your authentication to ConsoleMe has expired. Please restart weep.")
}
var challenge ConsolemeChallengeResponse
Expand Down Expand Up @@ -147,18 +153,39 @@ func getCredentialsPath() (string, error) {
return credentialsPath, nil
}

func HasValidJwt() bool {
func getChallenge() (*ConsolemeChallengeResponse, error) {
var challenge ConsolemeChallengeResponse
credentialPath, err := getCredentialsPath()
if err != nil {
return false
return nil, err
}
challengeBody, err := ioutil.ReadFile(credentialPath)
if err != nil {
return false
return nil, err
}
err = json.Unmarshal(challengeBody, &challenge)
if err != nil {
return nil, err
}
return &challenge, nil
}

func promptUser() (string, error) {
prompt := promptui.Prompt{
Label: "Please enter your ConsoleMe username",
}

result, err := prompt.Run()

if err != nil {
return "", err
}

return result, nil
}

func HasValidJwt(challenge *ConsolemeChallengeResponse) bool {
if challenge == nil {
return false
}
now := time.Now()
Expand All @@ -170,20 +197,38 @@ func HasValidJwt() bool {
}

func RefreshChallenge() error {
existingChallengeBody, err := getChallenge()
var user = viper.GetString("challenge_settings.user")
if err != nil {
log.Debugf("unable to read existing challenge file: %v", err)

}
// If credentials are still valid, no need to refresh them.
if HasValidJwt() {
if HasValidJwt(existingChallengeBody) {
return nil
}
// Step 1: Make unauthed request to ConsoleMe challenge endpoint and get a challenge challenge
if viper.GetString("challenge_settings.user") == "" {
// Check Config for username
if user == "" && existingChallengeBody != nil {
// Find user from old jwt
user = existingChallengeBody.User
}
if user == "" {
user, err = promptUser()
if err != nil {
return err
}
}
if user == "" {
log.Fatalf(
"Invalid configuration. You must define challenge_settings.user as the user you wish to authenticate as.",
"Invalid configuration. You must define challenge_settings.user as the user you wish to authenticate" +
" as.",
)
}
var consoleMeChallengeGeneratorEndpoint = fmt.Sprintf(
"%s/noauth/v1/challenge_generator/%s",
viper.GetString("consoleme_url"),
viper.GetString("challenge_settings.user"),
user,
)
var challenge ConsolemeChallenge
req, err := http.NewRequest("GET", consoleMeChallengeGeneratorEndpoint, nil)
Expand Down
1 change: 1 addition & 0 deletions challenge/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@ type ConsolemeChallengeResponse struct {
WantHttpOnly bool `json:"http_only"`
SameSite int `json:"same_site"`
Expires int64 `json:"expiration"`
User string `json:"user"`
}
4 changes: 2 additions & 2 deletions example-config.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
consoleme_url: https://path_to_consoleme:port
authentication_method: mtls # challenge or mtls
challenge_settings: # only needed if authentication_method is challenge
user: you@example.com
#challenge_settings: # (Optional) Username can be provided. If it is not provided, user will be prompted on first authentication attempt
# user: you@example.com
mtls_settings: # only needed if authentication_method is mtls
cert: mtls.crt
key: mtls.key
Expand Down

0 comments on commit 45dc7f2

Please sign in to comment.