diff --git a/.travis.yml b/.travis.yml index 9b1c482..facfc3d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,4 +9,7 @@ install: script: - make all services: - - docker \ No newline at end of file + - docker +branches: + only: + - master \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 8a3562c..66939a9 100755 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,12 @@ FROM alpine:3.3 MAINTAINER Liron Levin +# Indicates basic authorization is enforced +ENV AUTHORIZER basic + +# Indicates basic auditor type is used (log to console) +ENV AUDITOR basic + VOLUME /var/lib/twistlock/policy.json VOLUME /run/docker/plugins/ diff --git a/authz/basic.go b/authz/basic.go index 6dafd6f..a82c8e3 100755 --- a/authz/basic.go +++ b/authz/basic.go @@ -185,17 +185,33 @@ func NewBasicAuditor() core.Auditor { return &basicAuditor{} } -// TODO: Check nil func (f *basicAuditor) AuditRequest(req *authorization.Request, pluginRes *authorization.Response) { - logrus.Debugf("Request: method:%s' uri:'%s' user:'%s' allow:'%t' plugin msg:'%s'", req.RequestMethod, req.RequestURI, req.User, pluginRes.Allow, pluginRes.Msg) + + if req == nil { + logrus.Errorf("Authorization request is nil") + return + } + + if pluginRes == nil { + logrus.Errorf("Authorization response is nil") + return + } + + fields := logrus.Fields{ + "method": req.RequestMethod, + "uri": req.RequestURI, + "user": req.User, + "allow": pluginRes.Allow, + "msg": pluginRes.Msg, + } + + if pluginRes != nil ||pluginRes.Err != "" { + fields["err"] = pluginRes.Err + } + + logrus.WithFields(fields).Info("Request") } func (f *basicAuditor) AuditResponse(req *authorization.Request, pluginRes *authorization.Response) { - logrus.Debugf("Response: method:%s' uri:'%s' user:'%s' daeomn status code '%d' allow:'%t' plugin msg:'%s'", - req.RequestMethod, - req.RequestURI, - req.User, - req.ResponseStatusCode, - pluginRes.Allow, - pluginRes.Msg) + // Only log requests } diff --git a/authz/basic_test.go b/authz/basic_test.go index c1d64ad..522e24c 100755 --- a/authz/basic_test.go +++ b/authz/basic_test.go @@ -33,13 +33,22 @@ func TestPolicyApply(t *testing.T) { {"POST", "/v1.21/containers/id/rename", "user_6", false, "policy_4"}, // Readonly policy - GET denied } - handler := NewBasicAuthZAuthorizer(&BasicAuthorizerSettings{PolicyPath: policyFileName}) + authorizer := NewBasicAuthZAuthorizer(&BasicAuthorizerSettings{PolicyPath: policyFileName}) - assert.NoError(t, handler.Init(), "Initialization must be succesfull") + assert.NoError(t, authorizer.Init(), "Initialization must be succesfull") for _, test := range tests { - res := handler.AuthZReq(&authorization.Request{RequestMethod: test.method, RequestURI: test.uri, User: test.user}) + res := authorizer.AuthZReq(&authorization.Request{RequestMethod: test.method, RequestURI: test.uri, User: test.user}) assert.Equal(t, res.Allow, test.allow, "Request must be allowed/denied based on policy") assert.Contains(t, res.Msg, test.expectedPolicy, "Policy name must appear in the response") } } + +func TestAuditRequest(t *testing.T) { + auditor := NewBasicAuditor() + auditor.AuditRequest(&authorization.Request{User:"user"}, &authorization.Response{Allow:true}) + auditor.AuditRequest(&authorization.Request{User:"user"}, nil) + auditor.AuditRequest(nil, &authorization.Response{ + Err:"err", + }) +} diff --git a/authz/doc.go b/authz/doc.go new file mode 100644 index 0000000..6df4658 --- /dev/null +++ b/authz/doc.go @@ -0,0 +1,5 @@ +// authz package consist of specific authorization and auditing implementations +// supported mechanism: +// basic authorization - basic policy evaluation based on JSON policy files +// basic auditing - basic auditing to log file (JSON format) - only incoming request is audited +package authz diff --git a/broker/main.go b/broker/main.go index 3072931..567fccf 100755 --- a/broker/main.go +++ b/broker/main.go @@ -1,4 +1,4 @@ -// Entry point for Twistlock authorization plugin +// broker consists of the entry point for the twistlock authz broker package main import ( @@ -12,13 +12,13 @@ import ( const ( debugFlag = "debug" - handlerFlag = "authz-handler" + authorizerFlag = "authz-handler" auditorFlag = "auditor" policyFileFlag = "policy-file" ) const ( - handlerBasic = "basic" + authorizerBasic = "basic" ) const ( @@ -39,18 +39,18 @@ func main() { var auditor core.Auditor var authZHandler core.Authorizer - switch c.GlobalString(handlerFlag) { - case handlerBasic: + switch c.GlobalString(authorizerFlag) { + case authorizerBasic: authZHandler = authz.NewBasicAuthZAuthorizer(&authz.BasicAuthorizerSettings{PolicyPath: c.GlobalString(policyFileFlag)}) default: - panic(fmt.Sprintf("Unkwon authz hander %q", c.GlobalString(handlerFlag))) + panic(fmt.Sprintf("Unkwon authz hander %q", c.GlobalString(authorizerFlag))) } switch c.GlobalString(auditorFlag) { case auditorBasic: auditor = authz.NewBasicAuditor() default: - panic(fmt.Sprintf("Unkwon authz hander %q", c.GlobalString(handlerFlag))) + panic(fmt.Sprintf("Unkwon authz hander %q", c.GlobalString(authorizerFlag))) } srv := core.NewAuthZSrv(authZHandler, auditor) @@ -69,9 +69,9 @@ func main() { }, cli.StringFlag{ - Name: handlerFlag, - Value: handlerBasic, - EnvVar: "AUTHZ-HANDLER", + Name: authorizerFlag, + Value: authorizerBasic, + EnvVar: "AUTHORIZER", Usage: "Defines the authz handler type", }, @@ -85,7 +85,7 @@ func main() { cli.StringFlag{ Name: auditorFlag, Value: auditorBasic, - EnvVar: "AUTHZ-AUDITOR", + EnvVar: "AUDITOR", Usage: "Defines the authz auditor type", }, } diff --git a/core/doc.go b/core/doc.go new file mode 100644 index 0000000..cadf83e --- /dev/null +++ b/core/doc.go @@ -0,0 +1,3 @@ +// core packge consist of common authorization building block required for implementing +// concrete authorization logic. For example, route parsing and plugin service interface. +package core