Skip to content

Commit

Permalink
Added logs to client logging methods (#8014)
Browse files Browse the repository at this point in the history
* Adding logging in Traffic Ops, to show which login mechanism was used by the client

* Add logging for SSO/ token login (#208)

add logging for SSO/ token login

Co-authored-by: Srijeet Chatterjee <srijeet0406@gmail.com>

---------

Co-authored-by: Chatterjee, Srijeet <srijeet_chatterjee@comcast.com>
Co-authored-by: Srijeet Chatterjee <srijeet0406@gmail.com>
  • Loading branch information
3 people authored May 22, 2024
1 parent a892235 commit 8890fd3
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).

## [unreleased]
### Added
- [#8014](https://github.com/apache/trafficcontrol/pull/8014) *Traffic Ops* Added logs to indicate which mechanism a client used to login to TO.
- [#7812](https://github.com/apache/trafficcontrol/pull/7812) *Traffic Portal*: Expose the `configUpdateFailed` and `revalUpdateFailed` fields on the server table.
- [#7870](https://github.com/apache/trafficcontrol/pull/7870) *Traffic Portal*: Adds a hyperlink to the DSR page to the DS itself for ease of navigation.
- [#7896](https://github.com/apache/trafficcontrol/pull/7896) *ATC Build system*: Count commits since the last release, not commits
Expand Down
31 changes: 29 additions & 2 deletions traffic_ops/traffic_ops_golang/login/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ func LoginHandler(db *sqlx.DB, cfg config.Config) http.HandlerFunc {

// Failed certificate-based auth, perform standard form auth
if !authenticated {
log.Infof("user %s could not be successfully authenticated using client certificates", form.Username)
// Perform form authentication
if err := json.NewDecoder(r.Body).Decode(&form); err != nil {
api.HandleErr(w, r, nil, http.StatusBadRequest, err, nil)
Expand Down Expand Up @@ -212,17 +213,25 @@ func LoginHandler(db *sqlx.DB, cfg config.Config) http.HandlerFunc {
if err != nil {
log.Errorf("checking local user password: %s\n", err)
}
var ldapErr error
if !authenticated && cfg.LDAPEnabled {
if authenticated {
log.Infof("user %s successfully authenticated using username/ password", form.Username)
} else if cfg.LDAPEnabled {
var ldapErr error
authenticated, ldapErr = auth.CheckLDAPUser(form, cfg.ConfigLDAP)
if ldapErr != nil {
log.Infof("user %s could not be successfully authenticated using LDAP", form.Username)
log.Errorf("checking ldap user: %s\n", ldapErr.Error())
} else {
log.Infof("user %s successfully authenticated using LDAP", form.Username)
}
}
} else {
log.Infof("user %s successfully authenticated using client certificates", form.Username)
}

// Failed to authenticate in either local DB or LDAP, return unauthorized
if !authenticated {
log.Infof("user %s could not be successfully authenticated using username/ password", form.Username)
resp = tc.CreateAlerts(tc.ErrorLevel, "Invalid username or password.")
w.WriteHeader(http.StatusUnauthorized)
api.WriteRespRaw(w, r, resp)
Expand Down Expand Up @@ -298,6 +307,7 @@ func TokenLoginHandler(db *sqlx.DB, cfg config.Config) http.HandlerFunc {
defer r.Body.Close()
var t tc.UserToken
if err := json.NewDecoder(r.Body).Decode(&t); err != nil {
log.Infof("user could not be successfully authenticated using token")
api.HandleErr(w, r, nil, http.StatusBadRequest, fmt.Errorf("Invalid request: %v", err), nil)
return
}
Expand All @@ -306,11 +316,13 @@ func TokenLoginHandler(db *sqlx.DB, cfg config.Config) http.HandlerFunc {
if err != nil {
sysErr := fmt.Errorf("Checking token: %v", err)
errCode := http.StatusInternalServerError
log.Infof("user could not be successfully authenticated using token")
api.HandleErr(w, r, nil, errCode, nil, sysErr)
return
} else if !tokenMatches {
userErr := errors.New("Invalid token. Please contact your administrator.")
errCode := http.StatusUnauthorized
log.Infof("user could not be successfully authenticated using token")
api.HandleErr(w, r, nil, errCode, userErr, nil)
return
}
Expand All @@ -321,13 +333,15 @@ func TokenLoginHandler(db *sqlx.DB, cfg config.Config) http.HandlerFunc {
if err != nil {
sysErr := fmt.Errorf("Marshaling response: %v", err)
errCode := http.StatusInternalServerError
log.Infof("user could not be successfully authenticated using token")
api.HandleErr(w, r, nil, errCode, nil, sysErr)
return
}

_, dbErr := db.Exec(UpdateLoginTimeQuery, username)
if dbErr != nil {
dbErr = fmt.Errorf("unable to update authentication time for user '%s': %w", username, dbErr)
log.Infof("user %s could not be successfully authenticated using token", username)
api.HandleErr(w, r, nil, http.StatusInternalServerError, nil, dbErr)
return
}
Expand Down Expand Up @@ -413,16 +427,19 @@ func OauthLoginHandler(db *sqlx.DB, cfg config.Config) http.HandlerFunc {
}{}

if err := json.NewDecoder(r.Body).Decode(&parameters); err != nil {
log.Infof("user %s could not be successfully authenticated using SSO", form.Username)
api.HandleErr(w, r, nil, http.StatusBadRequest, err, nil)
return
}

matched, err := VerifyUrlOnWhiteList(parameters.AuthCodeTokenUrl, cfg.ConfigTrafficOpsGolang.WhitelistedOAuthUrls)
if err != nil {
log.Infof("user %s could not be successfully authenticated using SSO", form.Username)
api.HandleErr(w, r, nil, http.StatusInternalServerError, nil, err)
return
}
if !matched {
log.Infof("user %s could not be successfully authenticated using SSO", form.Username)
api.HandleErr(w, r, nil, http.StatusForbidden, nil, errors.New("Key URL from token is not included in the whitelisted urls. Received: "+parameters.AuthCodeTokenUrl))
return
}
Expand All @@ -439,6 +456,7 @@ func OauthLoginHandler(db *sqlx.DB, cfg config.Config) http.HandlerFunc {
req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(parameters.ClientId+":"+cfg.OAuthClientSecret))) // per RFC6749 section 2.3.1
}
if err != nil {
log.Infof("user %s could not be successfully authenticated using SSO", form.Username)
api.HandleErr(w, r, nil, http.StatusInternalServerError, nil, fmt.Errorf("obtaining token using code from oauth provider: %w", err))
return
}
Expand All @@ -448,6 +466,7 @@ func OauthLoginHandler(db *sqlx.DB, cfg config.Config) http.HandlerFunc {
}
response, err := client.Do(req)
if err != nil {
log.Infof("user %s could not be successfully authenticated using SSO", form.Username)
api.HandleErr(w, r, nil, http.StatusInternalServerError, nil, fmt.Errorf("getting an http client: %w", err))
return
}
Expand All @@ -473,12 +492,14 @@ func OauthLoginHandler(db *sqlx.DB, cfg config.Config) http.HandlerFunc {
default:
sysErr := fmt.Errorf("Incorrect type of access_token! Expected 'string', got '%v'\n", t)
usrErr := errors.New("Bad response from OAuth2.0 provider")
log.Infof("user %s could not be successfully authenticated using SSO", form.Username)
api.HandleErr(w, r, nil, http.StatusBadGateway, usrErr, sysErr)
return
}
}

if encodedToken == "" {
log.Infof("user %s could not be successfully authenticated using SSO", form.Username)
api.HandleErr(w, r, nil, http.StatusBadRequest, errors.New("Token not found in request but is required"), nil)
return
}
Expand All @@ -494,6 +515,7 @@ func OauthLoginHandler(db *sqlx.DB, cfg config.Config) http.HandlerFunc {
jwt.WithVerifyAuto(false),
jwt.WithJWKSetFetcher(jwksFetcher),
); err != nil {
log.Infof("user %s could not be successfully authenticated using SSO", form.Username)
api.HandleErr(w, r, nil, http.StatusInternalServerError, nil, fmt.Errorf("error decoding token with message: %w", err))
return
}
Expand All @@ -505,6 +527,7 @@ func OauthLoginHandler(db *sqlx.DB, cfg config.Config) http.HandlerFunc {
if cfg.OAuthUserAttribute != "" {
attributes := decodedToken.PrivateClaims()
if userIDInterface, ok = attributes[cfg.OAuthUserAttribute]; !ok {
log.Infof("user %s could not be successfully authenticated using SSO", form.Username)
api.HandleErr(w, r, nil, http.StatusInternalServerError, nil, fmt.Errorf("Non-existent OAuth attribute : %s", cfg.OAuthUserAttribute))
return
}
Expand All @@ -518,6 +541,7 @@ func OauthLoginHandler(db *sqlx.DB, cfg config.Config) http.HandlerFunc {
defer cancelTx()
userAllowed, err, blockingErr := auth.CheckLocalUserIsAllowed(form.Username, db, dbCtx)
if blockingErr != nil {
log.Infof("user %s could not be successfully authenticated using SSO", form.Username)
api.HandleErr(w, r, nil, http.StatusServiceUnavailable, nil, fmt.Errorf("error checking local user password: %s\n", blockingErr.Error()))
return
}
Expand All @@ -528,6 +552,7 @@ func OauthLoginHandler(db *sqlx.DB, cfg config.Config) http.HandlerFunc {
if userAllowed {
_, dbErr := db.Exec(UpdateLoginTimeQuery, form.Username)
if dbErr != nil {
log.Infof("user %s could not be successfully authenticated using SSO", form.Username)
dbErr = fmt.Errorf("unable to update authentication time for user '%s': %w", form.Username, dbErr)
api.HandleErr(w, r, nil, http.StatusInternalServerError, nil, dbErr)
return
Expand All @@ -537,10 +562,12 @@ func OauthLoginHandler(db *sqlx.DB, cfg config.Config) http.HandlerFunc {
resp = struct {
tc.Alerts
}{tc.CreateAlerts(tc.SuccessLevel, "Successfully logged in.")}
log.Infof("user %s successfully authenticated using SSO", form.Username)
} else {
resp = struct {
tc.Alerts
}{tc.CreateAlerts(tc.ErrorLevel, "Invalid username or password.")}
log.Infof("user %s could not be successfully authenticated using SSO", form.Username)
}

respBts, err := json.Marshal(resp)
Expand Down

0 comments on commit 8890fd3

Please sign in to comment.