提交 10bd78f1 编写于 作者: J Jeffrey Sica 提交者: k8s-ci-robot

API request logging improvements (#3180)

* cli arg improvements

* code improvements per marcin

* store structs not bools
上级 6ed35fcf
......@@ -108,6 +108,12 @@ func (self *holderBuilder) SetSystemBannerSeverity(systemBannerSeverity string)
return self
}
// SetLogLevel 'api-log-level' argument of Dashboard binary.
func (self *holderBuilder) SetAPILogLevel(apiLogLevel string) *holderBuilder {
self.holder.apiLogLevel = apiLogLevel
return self
}
// SetAuthenticationMode 'authentication-mode' argument of Dashboard binary.
func (self *holderBuilder) SetAuthenticationMode(authMode []string) *holderBuilder {
self.holder.authenticationMode = authMode
......
......@@ -41,6 +41,7 @@ type holder struct {
kubeConfigFile string
systemBanner string
systemBannerSeverity string
apiLogLevel string
authenticationMode []string
......@@ -48,7 +49,7 @@ type holder struct {
enableInsecureLogin bool
disableSettingsAuthorizer bool
disableSkipButton bool
disableSkipButton bool
}
// GetInsecurePort 'insecure-port' argument of Dashboard binary.
......@@ -129,6 +130,11 @@ func (self *holder) GetSystemBannerSeverity() string {
return self.systemBannerSeverity
}
// LogLevel 'api-log-level' argument of Dashboard binary.
func (self *holder) GetAPILogLevel() string {
return self.apiLogLevel
}
// GetAuthenticationMode 'authentication-mode' argument of Dashboard binary.
func (self *holder) GetAuthenticationMode() []string {
return self.authenticationMode
......
......@@ -69,6 +69,7 @@ var (
argDisableSkip = pflag.Bool("disable-skip", false, "When enabled, the skip button on the login page will not be shown. Default: false.")
argSystemBanner = pflag.String("system-banner", "", "When non-empty displays message to Dashboard users. Accepts simple HTML tags. Default: ''.")
argSystemBannerSeverity = pflag.String("system-banner-severity", "INFO", "Severity of system banner. Should be one of 'INFO|WARNING|ERROR'. Default: 'INFO'.")
argAPILogLevel = pflag.String("api-log-level", "INFO", "Level of API request logging. Should be one of 'INFO|NONE|DEBUG'. Default: 'INFO'.")
argDisableSettingsAuthorizer = pflag.Bool("disable-settings-authorizer", false, "When enabled, Dashboard settings page will not require user to be logged in and authorized to access settings page.")
)
......@@ -217,6 +218,7 @@ func initArgHolder() {
builder.SetKubeConfigFile(*argKubeConfigFile)
builder.SetSystemBanner(*argSystemBanner)
builder.SetSystemBannerSeverity(*argSystemBannerSeverity)
builder.SetAPILogLevel(*argAPILogLevel)
builder.SetAuthenticationMode(*argAuthenticationMode)
builder.SetAutoGenerateCertificates(*argAutoGenerateCertificates)
builder.SetEnableInsecureLogin(*argEnableInsecureLogin)
......
......@@ -15,6 +15,7 @@
package handler
import (
"encoding/json"
"net/http"
"testing"
......@@ -23,6 +24,7 @@ import (
"strings"
restful "github.com/emicklei/go-restful"
"github.com/kubernetes/dashboard/src/app/backend/args"
"github.com/kubernetes/dashboard/src/app/backend/auth"
authApi "github.com/kubernetes/dashboard/src/app/backend/auth/api"
"github.com/kubernetes/dashboard/src/app/backend/auth/jwe"
......@@ -103,25 +105,69 @@ func TestMapUrlToResource(t *testing.T) {
}
func TestFormatRequestLog(t *testing.T) {
req, err := http.NewRequest("PUT", "/api/v1/pod", bytes.NewReader([]byte("{}")))
if err != nil {
t.Error("Cannot mockup request")
}
cases := []struct {
request *restful.Request
expected string
method string
uri string
content map[string]string
expected string
apiLogLevel string
}{
{
&restful.Request{
Request: req,
},
"PUT",
"/api/v1/pod",
map[string]string{},
"Incoming HTTP/1.1 PUT /api/v1/pod request",
"DEFAULT",
},
{
"PUT",
"/api/v1/pod",
map[string]string{},
"",
"NONE",
},
{
"POST",
"/api/v1/login",
map[string]string{"password": "abc123"},
"Incoming HTTP/1.1 POST /api/v1/login request from : { contents hidden }",
"DEFAULT",
},
{
"POST",
"/api/v1/login",
map[string]string{},
"",
"NONE",
},
{
"POST",
"/api/v1/login",
map[string]string{"password": "abc123"},
"Incoming HTTP/1.1 POST /api/v1/login request from : {\n \"password\": \"abc123\"\n}",
"DEBUG",
},
}
for _, c := range cases {
actual := formatRequestLog(c.request)
jsonValue, _ := json.Marshal(c.content)
req, err := http.NewRequest(c.method, c.uri, bytes.NewReader(jsonValue))
req.Header.Set("Content-Type", "application/json")
if err != nil {
t.Error("Cannot mockup request")
}
builder := args.GetHolderBuilder()
builder.SetAPILogLevel(c.apiLogLevel)
var restfulRequest restful.Request
restfulRequest.Request = req
actual := formatRequestLog(&restfulRequest)
if !strings.Contains(actual, c.expected) {
t.Errorf("formatRequestLog(%#v) returns %#v, expected to contain %#v", c.request, actual, c.expected)
t.Errorf("formatRequestLog(%#v) returns %#v, expected to contain %#v", req, actual, c.expected)
}
}
}
......@@ -24,6 +24,7 @@ import (
"time"
restful "github.com/emicklei/go-restful"
"github.com/kubernetes/dashboard/src/app/backend/args"
authApi "github.com/kubernetes/dashboard/src/app/backend/auth/api"
clientapi "github.com/kubernetes/dashboard/src/app/backend/client/api"
kdErrors "github.com/kubernetes/dashboard/src/app/backend/errors"
......@@ -54,9 +55,15 @@ func restrictedResourcesFilter(request *restful.Request, response *restful.Respo
// web-service filter function used for request and response logging.
func requestAndResponseLogger(request *restful.Request, response *restful.Response,
chain *restful.FilterChain) {
log.Printf(formatRequestLog(request))
if args.Holder.GetAPILogLevel() != "NONE" {
log.Printf(formatRequestLog(request))
}
chain.ProcessFilter(request, response)
log.Printf(formatResponseLog(response, request))
if args.Holder.GetAPILogLevel() != "NONE" {
log.Printf(formatResponseLog(response, request))
}
}
// formatRequestLog formats request log string.
......@@ -76,6 +83,12 @@ func formatRequestLog(request *restful.Request) string {
}
}
// Is DEBUG level logging enabled? Yes?
// Great now let's filter out any content from sensitive URLs
if args.Holder.GetAPILogLevel() != "DEBUG" && checkSensitiveURL(&uri) {
content = "{ contents hidden }"
}
return fmt.Sprintf(RequestLogString, time.Now().Format(time.RFC3339), request.Request.Proto,
request.Request.Method, uri, request.Request.RemoteAddr, content)
}
......@@ -86,6 +99,21 @@ func formatResponseLog(response *restful.Response, request *restful.Request) str
request.Request.RemoteAddr, response.StatusCode())
}
// checkSensitiveUrl checks if a string matches against a sensitive URL
// true if sensitive. false if not.
func checkSensitiveURL(url *string) bool {
var s struct{}
var sensitiveUrls = make(map[string]struct{})
sensitiveUrls["/api/v1/login"] = s
sensitiveUrls["/api/v1/csrftoken/login"] = s
if _, ok := sensitiveUrls[*url]; ok {
return true
}
return false
}
func metricsFilter(req *restful.Request, resp *restful.Response,
chain *restful.FilterChain) {
resource := mapUrlToResource(req.SelectedRoutePath())
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册