Skip to content

Commit

Permalink
RBAC using Casbin (#256)
Browse files Browse the repository at this point in the history
* Hack Casbin RBAC in for POC

* Fix issue with apigroup-core.yml

* Externalise casbin adapter

* Load in some default builtin roles (always)

* General improvements to the code
- Better error handling
- Renaming of some properties
- Renaming of API mappings file
- Use keyMatch in rbac-model.conf to allow wildcards
- Fix import order
- Rename mapping endpoint
- Remove unused bolt bucket

* Make the endpoint_enforcer.go generic and add tests

* Introduce some REST handlers and allow/deny effect

* Introduce some REST handlers and allow/deny effect

* Add pkger and mocked endpoint_enforcer tests

* Static file and dependency improvements
* Use rice instead of pkger
* Move enforcer instantiation to server.go
* Fix makefile issue

* Unit test the new handlers

* Some improvements including some from the CR
* Updated our bolt dependency (the adapter is supporting latest - so makes sense to bump us too)
* Log errors in handlers and correct wrap errors
* Improve static rbac-policy.csv

* Make the rbac-api-mappings.yml more flexible & user friendly
* We now load in a different file format at start up for the RBAC api mappings. This one is more flexible, and I believe more user friendly (see the comment in the .yml file). Once loaded, we still have an O(1) lookup available for the endpoints :)
* Moved some models out of Gaia into rbac as they we only being used internally by the rbac package.

* Add RBAC settings flag (enabled/disabled) and some improvements
* Split the settings store interface out into its own (but nested in store.GaiaStore)
* Added unit tests for settings.go and improved DI on existing ones
* Created a new SettingsHandler to encapsulate the store dependency
* Add ability to save RBAC enabled state into database
* RBAC service is switched to EnforcerService or NoOpService depeneding on enabled state
* RBAC can be enabled or disabled with cmd flag `-rbac-enabled=true/false`

* Fix the import order

* Code improvements
* Fixed issues with missing or incorrect rbac-api-mappings.yml
* Started some acceptance tests for RBAC (probably to be finished outside this PR - its a lot of work)
* Added some tests for the content of the rbac-api-mappings.yml to alert us to any future change
* Endpoint Enforce now returns a PermissionDenied error

* Resolve conflicts

* Omit rbac_endpoint_test.go (for now) and update rice.FindBox to be string literal
See https://github.com/GeertJohan/go.rice/blob/master/README.md for why

* Add some more unit tests

* Fix enforcer logic and test assertions

* Add flag for RBAC debugging logging

* Refactor RBAC settings code

* Fix all merge conflicts around settings.go

* Couple of quick fixes post merge

* Fix test and add missing pull route
  • Loading branch information
speza authored Jul 6, 2020
1 parent 532ac3f commit b419af3
Show file tree
Hide file tree
Showing 35 changed files with 2,245 additions and 100 deletions.
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ static_assets:
go get github.com/GeertJohan/go.rice/rice && \
cd ./handlers && \
rm -f rice-box.go && \
rice embed-go && \
cd ../helper/assethelper && \
rm -f rice-box.go && \
rice embed-go

compile_backend:
Expand Down
7 changes: 5 additions & 2 deletions gaia.go
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,8 @@ type Config struct {
DockerRunImage string
DockerWorkerHostURL string
DockerWorkerGRPCHostURL string
RBACEnabled bool
RBACDebug bool

// Worker
WorkerName string
Expand All @@ -345,8 +347,9 @@ type Config struct {

// StoreConfig defines config settings to be stored in DB.
type StoreConfig struct {
ID int
Poll bool
ID int
Poll bool
RBACEnabled bool
}

// String returns a pipeline type string back
Expand Down
11 changes: 5 additions & 6 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ require (
github.com/Pallinder/go-randomdata v1.1.0
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 // indirect
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 // indirect
github.com/boltdb/bolt v1.3.1 // indirect
github.com/casbin/casbin/v2 v2.6.12
github.com/containerd/containerd v1.2.8 // indirect
github.com/coreos/bbolt v1.3.0
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/docker/distribution v2.7.1+incompatible // indirect
github.com/docker/docker v0.7.3-0.20190731001754-589f1dad8dad
Expand All @@ -18,7 +17,6 @@ require (
github.com/emirpasic/gods v1.9.0 // indirect
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 // indirect
github.com/gaia-pipeline/flag v1.7.4-pre
github.com/gaia-pipeline/gosdk v0.0.0-20180909192508-cc9f89055777 // indirect
github.com/gaia-pipeline/protobuf v0.0.0-20180812091451-7be8a901b55a
github.com/gliderlabs/ssh v0.1.1 // indirect
github.com/gofrs/uuid v3.2.0+incompatible
Expand Down Expand Up @@ -49,10 +47,11 @@ require (
github.com/robfig/cron v0.0.0-20180505203441-b41be1df6967
github.com/sergi/go-diff v1.0.0 // indirect
github.com/sirupsen/logrus v1.4.2 // indirect
github.com/speza/casbin-bolt-adapter v0.0.0-20200612141053-0da5f0ce6fc7
github.com/src-d/gcfg v1.3.0 // indirect
github.com/stretchr/testify v1.3.0 // indirect
github.com/stretchr/testify v1.6.1
github.com/xanzy/ssh-agent v0.2.0 // indirect
go.etcd.io/bbolt v1.3.4 // indirect
go.etcd.io/bbolt v1.3.4
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be
golang.org/x/sys v0.0.0-20200610111108-226ff32320da // indirect
Expand All @@ -62,7 +61,7 @@ require (
gopkg.in/src-d/go-git-fixtures.v3 v3.3.0 // indirect
gopkg.in/src-d/go-git.v4 v4.5.0
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v2 v2.2.2
gopkg.in/yaml.v2 v2.2.7
gotest.tools v2.2.0+incompatible // indirect
)

Expand Down
24 changes: 14 additions & 10 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ github.com/GeertJohan/go.incremental v1.0.0 h1:7AH+pY1XUgQE4Y1HcXYaMqAI0m9yrFqo/
github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0=
github.com/GeertJohan/go.rice v1.0.0 h1:KkI6O9uMaQU3VEKaj01ulavtF7o1fWT7+pk/4voiMLQ=
github.com/GeertJohan/go.rice v1.0.0/go.mod h1:eH6gbSOAUv07dQuZVnBmoDP8mgsM1rtixis4Tib9if0=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1:1G1pk05UrOh0NlF1oeaaix1x8XzrfjIDK47TY0Zehcw=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU=
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
github.com/Pallinder/go-randomdata v1.1.0 h1:gUubB1IEUliFmzjqjhf+bgkg1o6uoFIkRsP3VrhEcx8=
Expand All @@ -15,13 +17,11 @@ github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBb
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4=
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
github.com/casbin/casbin/v2 v2.6.12 h1:WTSs0Zbk74aScewyTsxkfoPwhwcwVfy8XqQ8j5Z+18M=
github.com/casbin/casbin/v2 v2.6.12/go.mod h1:XXtYGrs/0zlOsJMeRteEdVi/FsB0ph7KgNfjoCoJUD8=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/containerd/containerd v1.2.8 h1:oM84oDW6+A0FQ4aWW5wnnexazvrQA5Hw6iXAi4rczWw=
github.com/containerd/containerd v1.2.8/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
github.com/coreos/bbolt v1.3.0 h1:HIgH5xUWXT914HCI671AxuTTqjj64UOFr7pHn48LUTI=
github.com/coreos/bbolt v1.3.0/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/daaku/go.zipexe v1.0.0 h1:VSOgZtH418pH9L16hC/JrgSNJbbAL26pj7lmD1+CGdY=
github.com/daaku/go.zipexe v1.0.0/go.mod h1:z8IiR6TsVLEYKwXAoE/I+8ys/sDkgTzSL0CLnGVd57E=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
Expand All @@ -44,8 +44,6 @@ github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjr
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/gaia-pipeline/flag v1.7.4-pre h1:/TAmHVYVQGE4Mw9xl0Qs0D5UruVDMF95thexyEFbTAY=
github.com/gaia-pipeline/flag v1.7.4-pre/go.mod h1:rLpsWzqOEPa2K0Yl4aC34nmblLpIYjGqjP/srZbYvEk=
github.com/gaia-pipeline/gosdk v0.0.0-20180909192508-cc9f89055777 h1:Gn3nmETr4IE44pIFLeTDNNBBRhNXXh53PqFV23CsVok=
github.com/gaia-pipeline/gosdk v0.0.0-20180909192508-cc9f89055777/go.mod h1:e3TkvPdcdSdHZTgwiS89fs8lJrveYHsGLlz/Q0oXlN8=
github.com/gaia-pipeline/protobuf v0.0.0-20180812091451-7be8a901b55a h1:/5XAmdAyGl4yL9BugdPdBLaXquif1zw6Hih6go8E7Xs=
github.com/gaia-pipeline/protobuf v0.0.0-20180812091451-7be8a901b55a/go.mod h1:H0w7MofSuW53Nz7kesnBdVkvr437flf5B7D9Lcsb+lQ=
github.com/gliderlabs/ssh v0.1.1 h1:j3L6gSLQalDETeEg/Jg0mGY0/y/N6zI2xX1978P0Uqw=
Expand Down Expand Up @@ -133,13 +131,15 @@ github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAm
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/speza/casbin-bolt-adapter v0.0.0-20200612141053-0da5f0ce6fc7 h1:pY7C4f8F0mWtB8ODsTFkAB7Zx6Q+Mbc+p15iEYM4ZI0=
github.com/speza/casbin-bolt-adapter v0.0.0-20200612141053-0da5f0ce6fc7/go.mod h1:u1IU3msaVUqnhWSfvKzO0VdYAPqZoB2OXRddWJemteY=
github.com/src-d/gcfg v1.3.0 h1:2BEDr8r0I0b8h/fOqwtxCEiq2HJu8n2JGZJQFGXWLjg=
github.com/src-d/gcfg v1.3.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.0.1 h1:tY9CJiPnMXf1ERmG2EyK7gNUd+c6RKGD0IfU8WdUSz8=
Expand All @@ -166,6 +166,7 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b h1:ag/x1USPSsqHud38I9BAC88qd
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5 h1:LfCXLvNmTYH9kEmVgqbnsWfruoXZIrh4YBgqVHtDvw0=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200610111108-226ff32320da h1:bGb80FudwxpeucJUjPYJXuJ8Hk91vNtfvrymzwiei38=
golang.org/x/sys v0.0.0-20200610111108-226ff32320da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
Expand All @@ -192,8 +193,11 @@ gopkg.in/src-d/go-git.v4 v4.5.0 h1:6VjUh+5ATbfmlCAhV/Fb+1uQ7GnwLIuBPkwcRtxHZkk=
gopkg.in/src-d/go-git.v4 v4.5.0/go.mod h1:CzbUWqMn4pvmvndg3gnh5iZFmSsbhyhUWdI0IQ60AQo=
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo=
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c h1:grhR+C34yXImVGp7EzNk+DTIk+323eIUWOmEevy6bDo=
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
42 changes: 32 additions & 10 deletions handlers/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,19 @@ import (
"strings"

"github.com/dgrijalva/jwt-go"
"github.com/labstack/echo"

"github.com/gaia-pipeline/gaia"
"github.com/gaia-pipeline/gaia/helper/rolehelper"
"github.com/labstack/echo"
"github.com/gaia-pipeline/gaia/security/rbac"
)

var (
// errNotAuthorized is thrown when user wants to access resource which is protected
errNotAuthorized = errors.New("no or invalid jwt token provided. You are not authorized")
)

// AuthMiddleware is middleware used for each request. Includes functionality that validates the JWT tokens and user
// permissions.
func AuthMiddleware(roleAuth *AuthConfig) echo.MiddlewareFunc {
func authMiddleware(authCfg *AuthConfig) echo.MiddlewareFunc {
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
token, err := getToken(c)
Expand All @@ -29,15 +29,36 @@ func AuthMiddleware(roleAuth *AuthConfig) echo.MiddlewareFunc {
}

// Validate token
if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
if claims, okClaims := token.Claims.(jwt.MapClaims); okClaims && token.Valid {
// All ok, continue
username, okUsername := claims["username"]
roles, okPerms := claims["roles"]
if okUsername && okPerms && roles != nil {
username, hasUsername := claims["username"]
roles, hasRoles := claims["roles"]
if hasUsername && hasRoles && roles != nil {
// Look through the perms until we find that the user has this permission
err := roleAuth.checkRole(roles, c.Request().Method, c.Path())
if err := authCfg.checkRole(roles, c.Request().Method, c.Path()); err != nil {
return c.String(http.StatusForbidden, fmt.Sprintf("Permission denied for user."))
}

username, okUsername := username.(string)
if !okUsername {
gaia.Cfg.Logger.Error("username is not type string")
return c.String(http.StatusInternalServerError, fmt.Sprintf("Unknown error has occured."))
}

// Currently this lives inside the existing auth middleware. Ideally we would have independent
// middleware for enforcing RBAC. For now I will leave this here so we avoid parsing the token
// and claims multiple times.
params := map[string]string{}
for i, n := range c.ParamNames() {
params[n] = c.ParamValues()[i]
}
err := authCfg.rbacEnforcer.Enforce(username, c.Request().Method, c.Path(), params)
if err != nil {
return c.String(http.StatusForbidden, fmt.Sprintf("Permission denied for user %s. %s", username, err.Error()))
if _, permDenied := err.(*rbac.ErrPermissionDenied); permDenied {
return c.String(http.StatusForbidden, err.Error())
}
gaia.Cfg.Logger.Error("rbacEnforcer error", "error", err.Error())
return c.String(http.StatusInternalServerError, fmt.Sprintf("Unknown error has occurred while validating permissions."))
}
}
return next(c)
Expand All @@ -51,6 +72,7 @@ func AuthMiddleware(roleAuth *AuthConfig) echo.MiddlewareFunc {
// the permission roles required for each echo endpoint.
type AuthConfig struct {
RoleCategories []*gaia.UserRoleCategory
rbacEnforcer rbac.EndpointEnforcer
}

// Finds the required role for the metho & path specified. If it exists we validate that the provided user roles have
Expand Down
90 changes: 88 additions & 2 deletions handlers/auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package handlers
import (
"crypto/rand"
"crypto/rsa"
"errors"
"fmt"
"io/ioutil"
"net/http"
Expand All @@ -11,11 +12,27 @@ import (
"time"

"github.com/dgrijalva/jwt-go"
"github.com/hashicorp/go-hclog"
"github.com/labstack/echo"
"github.com/stretchr/testify/assert"

"github.com/gaia-pipeline/gaia"
"github.com/gaia-pipeline/gaia/helper/rolehelper"
"github.com/labstack/echo"
"github.com/gaia-pipeline/gaia/security/rbac"
)

type mockEchoEnforcer struct{}

func (m *mockEchoEnforcer) Enforce(username, method, path string, params map[string]string) error {
if username == "enforcer-perms-err" {
return rbac.NewErrPermissionDenied("namespace", "action", "thing")
}
if username == "enforcer-err" {
return errors.New("error")
}
return nil
}

var mockRoleAuth = &AuthConfig{
RoleCategories: []*gaia.UserRoleCategory{
{
Expand Down Expand Up @@ -54,11 +71,12 @@ var mockRoleAuth = &AuthConfig{
},
},
},
rbacEnforcer: &mockEchoEnforcer{},
}

func makeAuthBarrierRouter() *echo.Echo {
e := echo.New()
e.Use(AuthMiddleware(mockRoleAuth))
e.Use(authMiddleware(mockRoleAuth))

success := func(c echo.Context) error {
return c.NoContent(200)
Expand All @@ -68,6 +86,7 @@ func makeAuthBarrierRouter() *echo.Echo {
e.GET("/catone/:test", success)
e.GET("/catone/latest", success)
e.POST("/catone", success)
e.POST("/enforcer/test", success)

return e
}
Expand Down Expand Up @@ -355,3 +374,70 @@ func testPermSuccess(t *testing.T, statusCode int, body string) {
t.Fatalf("expected response code %v got %v", http.StatusOK, statusCode)
}
}

func Test_AuthMiddleware_Enforcer_PermissionDenied(t *testing.T) {
e := makeAuthBarrierRouter()

defer func() {
gaia.Cfg = nil
}()

gaia.Cfg = &gaia.Config{
JWTKey: []byte("hmac-jwt-key"),
}

claims := jwtCustomClaims{
Username: "enforcer-perms-err",
Roles: []string{},
StandardClaims: jwt.StandardClaims{
ExpiresAt: time.Now().Unix() + jwtExpiry,
IssuedAt: time.Now().Unix(),
Subject: "Gaia Session Token",
},
}

token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
tokenstring, _ := token.SignedString(gaia.Cfg.JWTKey)

rec := httptest.NewRecorder()
req := httptest.NewRequest(echo.POST, "/enforcer/test", nil)
req.Header.Set("Authorization", "Bearer "+tokenstring)
e.ServeHTTP(rec, req)

assert.Equal(t, rec.Code, http.StatusForbidden)
assert.Equal(t, rec.Body.String(), "Permission denied. Must have namespace/action thing")
}

func Test_AuthMiddleware_Enforcer_UnknownError(t *testing.T) {
e := makeAuthBarrierRouter()

defer func() {
gaia.Cfg = nil
}()

gaia.Cfg = &gaia.Config{
JWTKey: []byte("hmac-jwt-key"),
}
gaia.Cfg.Logger = hclog.NewNullLogger()

claims := jwtCustomClaims{
Username: "enforcer-err",
Roles: []string{},
StandardClaims: jwt.StandardClaims{
ExpiresAt: time.Now().Unix() + jwtExpiry,
IssuedAt: time.Now().Unix(),
Subject: "Gaia Session Token",
},
}

token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
tokenstring, _ := token.SignedString(gaia.Cfg.JWTKey)

rec := httptest.NewRecorder()
req := httptest.NewRequest(echo.POST, "/enforcer/test", nil)
req.Header.Set("Authorization", "Bearer "+tokenstring)
e.ServeHTTP(rec, req)

assert.Equal(t, rec.Code, http.StatusInternalServerError)
assert.Equal(t, rec.Body.String(), "Unknown error has occurred while validating permissions.")
}
Loading

0 comments on commit b419af3

Please sign in to comment.