Add IP and agent in trace for failed login

Fixes #16423

Signed-off-by: stonezdj <stonezdj@gmail.com>
This commit is contained in:
stonezdj 2022-02-24 19:24:23 +08:00
parent a5393468de
commit 9d5dc012aa
2 changed files with 81 additions and 1 deletions

View File

@ -16,6 +16,7 @@ package security
import (
"net/http"
"os"
"github.com/goharbor/harbor/src/common/models"
"github.com/goharbor/harbor/src/common/security"
@ -26,6 +27,36 @@ import (
type basicAuth struct{}
func trueClientIPHeaderName() string {
// because the true client IP header varies based on the foreground proxy/lb settings,
// make it configurable by env
name := os.Getenv("TRUE_CLIENT_IP_HEADER")
if len(name) == 0 {
name = "x-forwarded-for"
}
return name
}
// GetClientIP get client ip from request
func GetClientIP(r *http.Request) string {
if r == nil {
return ""
}
ip := r.Header.Get(trueClientIPHeaderName())
if len(ip) > 0 {
return ip
}
return r.RemoteAddr
}
// GetUserAgent get the user agent of current request
func GetUserAgent(r *http.Request) string {
if r == nil {
return ""
}
return r.Header.Get("user-agent")
}
func (b *basicAuth) Generate(req *http.Request) security.Context {
log := log.G(req.Context())
username, password, ok := req.BasicAuth()
@ -36,8 +67,9 @@ func (b *basicAuth) Generate(req *http.Request) security.Context {
Principal: username,
Password: password,
})
if err != nil {
log.Errorf("failed to authenticate %s: %v", username, err)
log.WithField("client IP", GetClientIP(req)).WithField("user agent", GetUserAgent(req)).Errorf("failed to authenticate user:%s, error:%v", username, err)
return nil
}
if user == nil {

View File

@ -33,3 +33,51 @@ func TestBasicAuth(t *testing.T) {
ctx := basicAuth.Generate(req)
assert.NotNil(t, ctx)
}
func TestGetClientIP(t *testing.T) {
h := http.Header{}
h.Set("X-Forwarded-For", "1.1.1.1")
type args struct {
r *http.Request
}
tests := []struct {
name string
args args
want string
}{
{"nil request", args{nil}, ""},
{"no header", args{&http.Request{RemoteAddr: "10.10.10.10"}}, "10.10.10.10"},
{"set x forworded for", args{&http.Request{Header: h, RemoteAddr: "10.10.10.10"}}, "1.1.1.1"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := GetClientIP(tt.args.r); got != tt.want {
t.Errorf("GetClientIP() = %v, want %v", got, tt.want)
}
})
}
}
func TestGetUserAgent(t *testing.T) {
h := http.Header{}
h.Set("user-agent", "docker")
type args struct {
r *http.Request
}
tests := []struct {
name string
args args
want string
}{
{"nil request", args{nil}, ""},
{"no header", args{&http.Request{}}, ""},
{"with user-agent", args{&http.Request{Header: h}}, "docker"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := GetUserAgent(tt.args.r); got != tt.want {
t.Errorf("GetUserAgent() = %v, want %v", got, tt.want)
}
})
}
}