mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-08-28 10:54:59 +00:00
Now loading policies, have tests checking OPA decisions
This commit is contained in:
parent
c96adc85fc
commit
39dd2e7bed
9 changed files with 208 additions and 10 deletions
73
rbac/enforcer.go
Normal file
73
rbac/enforcer.go
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
package rbac
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/open-policy-agent/opa/sdk"
|
||||
sdktest "github.com/open-policy-agent/opa/sdk/test"
|
||||
)
|
||||
|
||||
type ABACPolicyEnforcer struct {
|
||||
S *sdk.OPA
|
||||
CTX context.Context
|
||||
Server *sdktest.Server
|
||||
}
|
||||
|
||||
func NewABACPolicyEnforcer() (*ABACPolicyEnforcer, error) {
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
policy, err := ioutil.ReadFile("example_policy.rego")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
policyS := string(policy)
|
||||
server, err := sdktest.NewServer(sdktest.MockBundle("/bundles/bundle.tar.gz", map[string]string{
|
||||
"example.rego": policyS,
|
||||
}))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config := []byte(fmt.Sprintf(`{
|
||||
"services": {
|
||||
"test": {
|
||||
"url": %q
|
||||
}
|
||||
},
|
||||
"bundles": {
|
||||
"test": {
|
||||
"resource": "/bundles/bundle.tar.gz"
|
||||
}
|
||||
},
|
||||
"decision_logs": {
|
||||
"console": true
|
||||
}
|
||||
}`, server.URL()))
|
||||
opa, err := sdk.New(ctx, sdk.Options{
|
||||
Config: bytes.NewReader(config),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &ABACPolicyEnforcer{
|
||||
S: opa,
|
||||
CTX: ctx,
|
||||
Server: server,
|
||||
}, nil
|
||||
|
||||
}
|
||||
|
||||
func readPolicyFile(p string) ([]byte, error) {
|
||||
policyData, err := ioutil.ReadFile(p)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return policyData, nil
|
||||
|
||||
}
|
||||
37
rbac/enforcer_test.go
Normal file
37
rbac/enforcer_test.go
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
package rbac_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/featurebasedb/featurebase/v3/rbac"
|
||||
"github.com/open-policy-agent/opa/sdk"
|
||||
)
|
||||
|
||||
func TestCreateABACPolicyEnforcer(t *testing.T) {
|
||||
enf, err := rbac.NewABACPolicyEnforcer()
|
||||
if err != nil {
|
||||
t.Errorf("Error creating ABACPolicyEnforcer: %s", err)
|
||||
}
|
||||
|
||||
defer enf.Server.Stop()
|
||||
defer enf.S.Stop(enf.CTX)
|
||||
|
||||
result, err := enf.S.Decision(enf.CTX, sdk.DecisionOptions{Path: "/featurebase/authz/allow", Input: map[string]interface{}{"open": "sesame"}})
|
||||
if err != nil {
|
||||
t.Errorf("Error testing OPA decision: %s", err)
|
||||
}
|
||||
if result.Result.(bool) != false {
|
||||
t.Errorf("Result was not false!")
|
||||
}
|
||||
|
||||
result, err = enf.S.Decision(enf.CTX, sdk.DecisionOptions{Path: "/featurebase/authz/allow", Input: map[string]interface{}{"method": "SELECT", "path": "index_a", "user": "fletcher"}})
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Error testing OPA decision: %s", err)
|
||||
}
|
||||
|
||||
if result.Result.(bool) != true {
|
||||
t.Errorf("Result was not true!")
|
||||
}
|
||||
|
||||
}
|
||||
11
rbac/errors.go
Normal file
11
rbac/errors.go
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
package rbac
|
||||
|
||||
import "fmt"
|
||||
|
||||
type RBACError struct {
|
||||
err string
|
||||
}
|
||||
|
||||
func (e RBACError) Error() string {
|
||||
return fmt.Sprintf("RBACError: %s", e.err)
|
||||
}
|
||||
|
|
@ -1,8 +1,3 @@
|
|||
---
|
||||
user:
|
||||
name: fletcher
|
||||
email: fletcher.haynes@featurebase.com
|
||||
|
||||
---
|
||||
group:
|
||||
name: employees
|
||||
|
|
|
|||
10
rbac/example_policy.rego
Normal file
10
rbac/example_policy.rego
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
package featurebase.authz
|
||||
|
||||
default allow = false
|
||||
|
||||
allow {
|
||||
input.method = "SELECT"
|
||||
input.path = "index_a"
|
||||
input.user = "fletcher"
|
||||
|
||||
}
|
||||
1
rbac/opa.go
Normal file
1
rbac/opa.go
Normal file
|
|
@ -0,0 +1 @@
|
|||
package rbac
|
||||
49
rbac/user.go
49
rbac/user.go
|
|
@ -1,6 +1,12 @@
|
|||
package rbac
|
||||
|
||||
import "google.golang.org/genproto/googleapis/type/datetime"
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"time"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
type FBUserStatus int32
|
||||
|
||||
|
|
@ -11,9 +17,42 @@ const (
|
|||
)
|
||||
|
||||
type FBUser struct {
|
||||
Username string
|
||||
Email string
|
||||
Created datetime.DateTime
|
||||
LastActivity datetime.DateTime
|
||||
Username string `yaml:"username"`
|
||||
Email string `yaml:"email"`
|
||||
Created time.Time
|
||||
LastActivity time.Time
|
||||
Status FBUserStatus
|
||||
}
|
||||
|
||||
func NewFBUser(username, email string) FBUser {
|
||||
newUser := FBUser{
|
||||
Username: username,
|
||||
Email: email,
|
||||
Created: time.Now(),
|
||||
LastActivity: time.Now(),
|
||||
Status: Active,
|
||||
}
|
||||
return newUser
|
||||
}
|
||||
func LoadUsersFromYAML(p string) ([]FBUser, error) {
|
||||
usersData := make(map[string][]map[string]string)
|
||||
users := make([]FBUser, 0)
|
||||
data, err := ioutil.ReadFile(p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = yaml.Unmarshal(data, usersData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fmt.Printf("Users are: %v", usersData)
|
||||
for _, user := range usersData["users"] {
|
||||
newUser := FBUser{
|
||||
Username: user["name"],
|
||||
Email: user["email"],
|
||||
}
|
||||
users = append(users, newUser)
|
||||
}
|
||||
return users, nil
|
||||
|
||||
}
|
||||
|
|
|
|||
27
rbac/user_test.go
Normal file
27
rbac/user_test.go
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
package rbac_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/featurebasedb/featurebase/v3/rbac"
|
||||
)
|
||||
|
||||
func TestCreateUserFromYAML(t *testing.T) {
|
||||
users, err := rbac.LoadUsersFromYAML("users.yaml")
|
||||
if err != nil {
|
||||
t.Errorf("Error loading test users from YAML: %s", err)
|
||||
}
|
||||
|
||||
if len(users) != 1 {
|
||||
t.Errorf("Expected 1 user to be loaded from YAML. Got %d", len(users))
|
||||
}
|
||||
|
||||
if users[0].Username != "fletcher" {
|
||||
t.Errorf("Expected test user username to be fletcher. Got %s", users[0].Username)
|
||||
}
|
||||
|
||||
if users[0].Email != "fletcher.haynes@featurebase.com" {
|
||||
t.Errorf("Expected test user email to be fletcher.haynes@featurebase.com. Got %s", users[0].Email)
|
||||
}
|
||||
|
||||
}
|
||||
5
rbac/users.yaml
Normal file
5
rbac/users.yaml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
users:
|
||||
- name: fletcher
|
||||
email: fletcher.haynes@featurebase.com
|
||||
|
||||
Loading…
Add table
Reference in a new issue