зеркало из https://github.com/mozilla/doorman.git
Rename warden to doorman
This commit is contained in:
Родитель
3c2cf1bd77
Коммит
fbaee2e235
4
Makefile
4
Makefile
|
@ -2,8 +2,8 @@ GO_LINT := $(GOPATH)/bin/golint
|
||||||
GO_GLIDE := $(GOPATH)/bin/glide
|
GO_GLIDE := $(GOPATH)/bin/glide
|
||||||
GO_BINDATA := $(GOPATH)/bin/go-bindata
|
GO_BINDATA := $(GOPATH)/bin/go-bindata
|
||||||
DATA_FILES := ./utilities/openapi.yaml ./utilities/contribute.yaml
|
DATA_FILES := ./utilities/openapi.yaml ./utilities/contribute.yaml
|
||||||
SRC := *.go ./utilities/*.go ./warden/*.go
|
SRC := *.go ./utilities/*.go ./doorman/*.go
|
||||||
PACKAGES := ./ ./utilities/ ./warden/
|
PACKAGES := ./ ./utilities/ ./doorman/
|
||||||
|
|
||||||
main: vendor utilities/bindata.go $(SRC)
|
main: vendor utilities/bindata.go $(SRC)
|
||||||
CGO_ENABLED=0 go build -o main *.go
|
CGO_ENABLED=0 go build -o main *.go
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package warden
|
package doorman
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
@ -20,30 +20,30 @@ import (
|
||||||
// DefaultPoliciesFilename is the default policies filename.
|
// DefaultPoliciesFilename is the default policies filename.
|
||||||
const DefaultPoliciesFilename string = "policies.yaml"
|
const DefaultPoliciesFilename string = "policies.yaml"
|
||||||
|
|
||||||
// ContextKey is the Gin context key to obtain the *Warden instance.
|
// ContextKey is the Gin context key to obtain the *Doorman instance.
|
||||||
const ContextKey string = "warden"
|
const ContextKey string = "doorman"
|
||||||
|
|
||||||
const maxInt int64 = 1<<63 - 1
|
const maxInt int64 = 1<<63 - 1
|
||||||
|
|
||||||
// Config contains the settings of the warden.
|
// Config contains the settings of the doorman.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
PoliciesFilename string
|
PoliciesFilename string
|
||||||
JWTIssuer string
|
JWTIssuer string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Warden is the backend in charge of checking requests against policies.
|
// Doorman is the backend in charge of checking requests against policies.
|
||||||
type Warden struct {
|
type Doorman struct {
|
||||||
l ladon.Ladon
|
l ladon.Ladon
|
||||||
Manager ladon.Manager
|
Manager ladon.Manager
|
||||||
Config *Config
|
Config *Config
|
||||||
}
|
}
|
||||||
|
|
||||||
// New instantiates a new warden.
|
// New instantiates a new doorman.
|
||||||
func New(config *Config) *Warden {
|
func New(config *Config) *Doorman {
|
||||||
l := ladon.Ladon{
|
l := ladon.Ladon{
|
||||||
Manager: manager.NewMemoryManager(),
|
Manager: manager.NewMemoryManager(),
|
||||||
}
|
}
|
||||||
w := &Warden{l, l.Manager, config}
|
w := &Doorman{l, l.Manager, config}
|
||||||
if err := w.LoadPolicies(config.PoliciesFilename); err != nil {
|
if err := w.LoadPolicies(config.PoliciesFilename); err != nil {
|
||||||
log.Fatal(err.Error())
|
log.Fatal(err.Error())
|
||||||
}
|
}
|
||||||
|
@ -51,12 +51,12 @@ func New(config *Config) *Warden {
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsAllowed is responsible for deciding if subject can perform action on a resource with a context.
|
// IsAllowed is responsible for deciding if subject can perform action on a resource with a context.
|
||||||
func (warden *Warden) IsAllowed(request *ladon.Request) error {
|
func (doorman *Doorman) IsAllowed(request *ladon.Request) error {
|
||||||
return warden.l.IsAllowed(request)
|
return doorman.l.IsAllowed(request)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadPolicies reads policies from the YAML file.
|
// LoadPolicies reads policies from the YAML file.
|
||||||
func (warden *Warden) LoadPolicies(filename string) error {
|
func (doorman *Doorman) LoadPolicies(filename string) error {
|
||||||
// If not specified, read it from ENV or read local `.policies.yaml`
|
// If not specified, read it from ENV or read local `.policies.yaml`
|
||||||
if filename == "" {
|
if filename == "" {
|
||||||
filename = os.Getenv("POLICIES_FILE")
|
filename = os.Getenv("POLICIES_FILE")
|
||||||
|
@ -95,19 +95,19 @@ func (warden *Warden) LoadPolicies(filename string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear every existing policy, and load new ones.
|
// Clear every existing policy, and load new ones.
|
||||||
existing, err := warden.Manager.GetAll(0, maxInt)
|
existing, err := doorman.Manager.GetAll(0, maxInt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for _, pol := range existing {
|
for _, pol := range existing {
|
||||||
err := warden.Manager.Delete(pol.GetID())
|
err := doorman.Manager.Delete(pol.GetID())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, pol := range policies {
|
for _, pol := range policies {
|
||||||
log.Info("Load policy ", pol.GetID()+": ", pol.GetDescription())
|
log.Info("Load policy ", pol.GetID()+": ", pol.GetDescription())
|
||||||
err := warden.Manager.Create(pol)
|
err := doorman.Manager.Create(pol)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -116,19 +116,19 @@ func (warden *Warden) LoadPolicies(filename string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContextMiddleware adds the Warden instance to the Gin context.
|
// ContextMiddleware adds the Doorman instance to the Gin context.
|
||||||
func ContextMiddleware(warden *Warden) gin.HandlerFunc {
|
func ContextMiddleware(doorman *Doorman) gin.HandlerFunc {
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
c.Set(ContextKey, warden)
|
c.Set(ContextKey, doorman)
|
||||||
c.Next()
|
c.Next()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetupRoutes adds warden views to query the policies.
|
// SetupRoutes adds doorman views to query the policies.
|
||||||
func SetupRoutes(r *gin.Engine, warden *Warden) {
|
func SetupRoutes(r *gin.Engine, doorman *Doorman) {
|
||||||
r.Use(ContextMiddleware(warden))
|
r.Use(ContextMiddleware(doorman))
|
||||||
if warden.Config.JWTIssuer != "" {
|
if doorman.Config.JWTIssuer != "" {
|
||||||
r.Use(VerifyJWTMiddleware(warden.Config.JWTIssuer))
|
r.Use(VerifyJWTMiddleware(doorman.Config.JWTIssuer))
|
||||||
}
|
}
|
||||||
r.POST("/allowed", allowedHandler)
|
r.POST("/allowed", allowedHandler)
|
||||||
}
|
}
|
||||||
|
@ -156,13 +156,13 @@ func allowedHandler(c *gin.Context) {
|
||||||
accessRequest.Subject = payloadJWT.(*jwt.Claims).Subject
|
accessRequest.Subject = payloadJWT.(*jwt.Claims).Subject
|
||||||
}
|
}
|
||||||
|
|
||||||
warden := c.MustGet(ContextKey).(*Warden)
|
doorman := c.MustGet(ContextKey).(*Doorman)
|
||||||
err := warden.IsAllowed(&accessRequest)
|
err := doorman.IsAllowed(&accessRequest)
|
||||||
allowed := (err == nil)
|
allowed := (err == nil)
|
||||||
|
|
||||||
// Show some debug information about matched policy.
|
// Show some debug information about matched policy.
|
||||||
if allowed && gin.Mode() != gin.ReleaseMode {
|
if allowed && gin.Mode() != gin.ReleaseMode {
|
||||||
policies, _ := warden.Manager.FindRequestCandidates(&accessRequest)
|
policies, _ := doorman.Manager.FindRequestCandidates(&accessRequest)
|
||||||
matched := policies[0]
|
matched := policies[0]
|
||||||
log.Debug("Policy matched ", matched.GetID()+": ", matched.GetDescription())
|
log.Debug("Policy matched ", matched.GetID()+": ", matched.GetDescription())
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package warden
|
package doorman
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
@ -38,28 +38,28 @@ func TestMain(m *testing.M) {
|
||||||
os.Exit(m.Run())
|
os.Exit(m.Run())
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadTempFile(warden *Warden, content []byte) error {
|
func loadTempFile(doorman *Doorman, content []byte) error {
|
||||||
tmpfile, _ := ioutil.TempFile("", "")
|
tmpfile, _ := ioutil.TempFile("", "")
|
||||||
defer os.Remove(tmpfile.Name()) // clean up
|
defer os.Remove(tmpfile.Name()) // clean up
|
||||||
tmpfile.Write(content)
|
tmpfile.Write(content)
|
||||||
tmpfile.Close()
|
tmpfile.Close()
|
||||||
return warden.LoadPolicies(tmpfile.Name())
|
return doorman.LoadPolicies(tmpfile.Name())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLoadPolicies(t *testing.T) {
|
func TestLoadPolicies(t *testing.T) {
|
||||||
warden := New(&Config{"../policies.yaml", ""})
|
doorman := New(&Config{"../policies.yaml", ""})
|
||||||
|
|
||||||
// Missing file
|
// Missing file
|
||||||
var err error
|
var err error
|
||||||
err = warden.LoadPolicies("/tmp/unknown.yaml")
|
err = doorman.LoadPolicies("/tmp/unknown.yaml")
|
||||||
assert.NotNil(t, err)
|
assert.NotNil(t, err)
|
||||||
|
|
||||||
// Bad YAML
|
// Bad YAML
|
||||||
err = loadTempFile(warden, []byte("$\\--xx"))
|
err = loadTempFile(doorman, []byte("$\\--xx"))
|
||||||
assert.NotNil(t, err)
|
assert.NotNil(t, err)
|
||||||
|
|
||||||
// Bad policies
|
// Bad policies
|
||||||
err = loadTempFile(warden, []byte(`
|
err = loadTempFile(doorman, []byte(`
|
||||||
-
|
-
|
||||||
id: "1"
|
id: "1"
|
||||||
conditions:
|
conditions:
|
||||||
|
@ -69,7 +69,7 @@ func TestLoadPolicies(t *testing.T) {
|
||||||
assert.NotNil(t, err)
|
assert.NotNil(t, err)
|
||||||
|
|
||||||
// Duplicated ID
|
// Duplicated ID
|
||||||
err = loadTempFile(warden, []byte(`
|
err = loadTempFile(doorman, []byte(`
|
||||||
-
|
-
|
||||||
id: "1"
|
id: "1"
|
||||||
effect: allow
|
effect: allow
|
||||||
|
@ -95,7 +95,7 @@ func performAllowed(t *testing.T, r *gin.Engine, body io.Reader, expected int, r
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWardenGet(t *testing.T) {
|
func TestDoormanGet(t *testing.T) {
|
||||||
r := gin.New()
|
r := gin.New()
|
||||||
SetupRoutes(r, New(&defaultConfig))
|
SetupRoutes(r, New(&defaultConfig))
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ func TestWardenGet(t *testing.T) {
|
||||||
assert.Equal(t, w.Code, http.StatusNotFound)
|
assert.Equal(t, w.Code, http.StatusNotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWardenEmpty(t *testing.T) {
|
func TestDoormanEmpty(t *testing.T) {
|
||||||
r := gin.New()
|
r := gin.New()
|
||||||
SetupRoutes(r, New(&defaultConfig))
|
SetupRoutes(r, New(&defaultConfig))
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ func TestWardenEmpty(t *testing.T) {
|
||||||
assert.Equal(t, response.Message, "Missing body")
|
assert.Equal(t, response.Message, "Missing body")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWardenInvalidJSON(t *testing.T) {
|
func TestDoormanInvalidJSON(t *testing.T) {
|
||||||
r := gin.New()
|
r := gin.New()
|
||||||
SetupRoutes(r, New(&defaultConfig))
|
SetupRoutes(r, New(&defaultConfig))
|
||||||
|
|
||||||
|
@ -122,11 +122,11 @@ func TestWardenInvalidJSON(t *testing.T) {
|
||||||
assert.Contains(t, response.Message, "invalid character ';'")
|
assert.Contains(t, response.Message, "invalid character ';'")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWardenAllowed(t *testing.T) {
|
func TestDoormanAllowed(t *testing.T) {
|
||||||
r := gin.New()
|
r := gin.New()
|
||||||
warden := New(&defaultConfig)
|
doorman := New(&defaultConfig)
|
||||||
warden.LoadPolicies(samplePoliciesFile)
|
doorman.LoadPolicies(samplePoliciesFile)
|
||||||
SetupRoutes(r, warden)
|
SetupRoutes(r, doorman)
|
||||||
|
|
||||||
for _, request := range []*ladon.Request{
|
for _, request := range []*ladon.Request{
|
||||||
// Policy #1
|
// Policy #1
|
||||||
|
@ -180,11 +180,11 @@ func TestWardenAllowed(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWardenNotAllowed(t *testing.T) {
|
func TestDoormanNotAllowed(t *testing.T) {
|
||||||
r := gin.New()
|
r := gin.New()
|
||||||
warden := New(&defaultConfig)
|
doorman := New(&defaultConfig)
|
||||||
warden.LoadPolicies(samplePoliciesFile)
|
doorman.LoadPolicies(samplePoliciesFile)
|
||||||
SetupRoutes(r, warden)
|
SetupRoutes(r, doorman)
|
||||||
|
|
||||||
for _, request := range []*ladon.Request{
|
for _, request := range []*ladon.Request{
|
||||||
// Policy #1
|
// Policy #1
|
|
@ -1,4 +1,4 @@
|
||||||
package warden
|
package doorman
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
|
@ -1,4 +1,4 @@
|
||||||
package warden
|
package doorman
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -8,7 +8,7 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestMain defined in warden_test.go
|
// TestMain defined in doorman_test.go
|
||||||
// func TestMain(m *testing.M) {}
|
// func TestMain(m *testing.M) {}
|
||||||
|
|
||||||
func TestVerifyJWT(t *testing.T) {
|
func TestVerifyJWT(t *testing.T) {
|
10
main.go
10
main.go
|
@ -9,7 +9,7 @@ import (
|
||||||
"go.mozilla.org/mozlogrus"
|
"go.mozilla.org/mozlogrus"
|
||||||
|
|
||||||
"github.com/leplatrem/iam/utilities"
|
"github.com/leplatrem/iam/utilities"
|
||||||
"github.com/leplatrem/iam/warden"
|
"github.com/leplatrem/iam/doorman"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -49,13 +49,13 @@ func setupRouter() *gin.Engine {
|
||||||
r.Use(gin.Logger())
|
r.Use(gin.Logger())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup warden with default config (read policies from disk)
|
// Setup doorman with default config (read policies from disk)
|
||||||
config := &warden.Config{
|
config := &doorman.Config{
|
||||||
PoliciesFilename: "",
|
PoliciesFilename: "",
|
||||||
JWTIssuer: os.Getenv("JWT_ISSUER"),
|
JWTIssuer: os.Getenv("JWT_ISSUER"),
|
||||||
}
|
}
|
||||||
w := warden.New(config)
|
w := doorman.New(config)
|
||||||
warden.SetupRoutes(r, w)
|
doorman.SetupRoutes(r, w)
|
||||||
|
|
||||||
utilities.SetupRoutes(r)
|
utilities.SetupRoutes(r)
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ info:
|
||||||
|
|
||||||
tags:
|
tags:
|
||||||
- name: Utilities
|
- name: Utilities
|
||||||
- name: Warden
|
- name: Doorman
|
||||||
|
|
||||||
paths:
|
paths:
|
||||||
/__heartbeat__:
|
/__heartbeat__:
|
||||||
|
@ -123,4 +123,4 @@ paths:
|
||||||
allowed:
|
allowed:
|
||||||
type: boolean
|
type: boolean
|
||||||
tags:
|
tags:
|
||||||
- Warden
|
- Doorman
|
||||||
|
|
Загрузка…
Ссылка в новой задаче