pomerium/authorize/evaluator/opa/opa_test.go

110 lines
8.3 KiB
Go

package opa
import (
"context"
"testing"
"time"
"github.com/pomerium/pomerium/config"
"gopkg.in/square/go-jose.v2"
"gopkg.in/square/go-jose.v2/jwt"
)
func Test_Eval(t *testing.T) {
t.Parallel()
type Identity struct {
User string `json:"user,omitempty"`
Email string `json:"email,omitempty"`
Groups []string `json:"groups,omitempty"`
ImpersonateEmail string `json:"impersonate_email,omitempty"`
ImpersonateGroups []string `json:"impersonate_groups,omitempty"`
}
tests := []struct {
name string
policies []config.Policy
route string
Identity *Identity
admins []string
secret string
want bool
}{
{"valid domain", []config.Policy{{From: "https://from.example", To: "https://to.example", AllowedDomains: []string{"example.com"}}}, "from.example", &Identity{Email: "user@example.com"}, nil, "secret", true},
{"valid domain with admins", []config.Policy{{From: "https://from.example", To: "https://to.example", AllowedDomains: []string{"example.com"}}}, "from.example", &Identity{Email: "user@example.com"}, []string{"admin@example.com"}, "secret", true},
{"invalid domain prepend", []config.Policy{{From: "https://from.example", To: "https://to.example", AllowedDomains: []string{"example.com"}}}, "from.example", &Identity{Email: "a@1example.com"}, nil, "secret", false},
{"invalid domain postpend", []config.Policy{{From: "https://from.example", To: "https://to.example", AllowedDomains: []string{"example.com"}}}, "from.example", &Identity{Email: "user@example.com2"}, nil, "secret", false},
{"valid group", []config.Policy{{From: "https://from.example", To: "https://to.example", AllowedGroups: []string{"admin"}}}, "from.example", &Identity{Email: "user@example.com", Groups: []string{"admin"}}, nil, "secret", true},
{"invalid group", []config.Policy{{From: "https://from.example", To: "https://to.example", AllowedGroups: []string{"admin"}}}, "from.example", &Identity{Email: "user@example.com", Groups: []string{"everyone"}}, nil, "secret", false},
{"invalid empty", []config.Policy{{From: "https://from.example", To: "https://to.example", AllowedGroups: []string{"admin"}}}, "from.example", &Identity{Email: "user@example.com", Groups: []string{""}}, nil, "secret", false},
{"valid group multiple", []config.Policy{{From: "https://from.example", To: "https://to.example", AllowedGroups: []string{"admin"}}}, "from.example", &Identity{Email: "user@example.com", Groups: []string{"everyone", "admin"}}, nil, "secret", true},
{"invalid group multiple", []config.Policy{{From: "https://from.example", To: "https://to.example", AllowedGroups: []string{"admin"}}}, "from.example", &Identity{Email: "user@example.com", Groups: []string{"everyones", "sadmin"}}, nil, "secret", false},
{"valid user email", []config.Policy{{From: "https://from.example", To: "https://to.example", AllowedUsers: []string{"user@example.com"}}}, "from.example", &Identity{Email: "user@example.com"}, nil, "secret", true},
{"invalid user email", []config.Policy{{From: "https://from.example", To: "https://to.example", AllowedUsers: []string{"user@example.com"}}}, "from.example", &Identity{Email: "user2@example.com"}, nil, "secret", false},
{"empty everything", []config.Policy{{From: "https://from.example", To: "https://to.example"}}, "from.example", &Identity{Email: "user2@example.com"}, nil, "secret", false},
{"empty policy", []config.Policy{}, "from.example", &Identity{Email: "user2@example.com"}, nil, "secret", false},
// impersonation related
{"admin not impersonating allowed", []config.Policy{{From: "https://from.example", To: "https://to.example", AllowedDomains: []string{"example.com"}}}, "from.example", &Identity{Email: "admin@example.com"}, []string{"admin@example.com"}, "secret", true},
{"admin not impersonating denied", []config.Policy{{From: "https://from.example", To: "https://to.example", AllowedDomains: []string{"example.com"}}}, "from.example", &Identity{Email: "admin@admin-domain.com"}, []string{"admin@admin-domain.com"}, "secret", false},
{"impersonating match domain", []config.Policy{{From: "https://from.example", To: "https://to.example", AllowedDomains: []string{"example.com"}}}, "from.example", &Identity{Email: "admin@admin-domain.com", ImpersonateEmail: "user@example.com"}, []string{"admin@admin-domain.com"}, "secret", true},
{"impersonating does not match domain", []config.Policy{{From: "https://from.example", To: "https://to.example", AllowedDomains: []string{"example.com"}}}, "from.example", &Identity{Email: "admin@admin-domain.com", ImpersonateEmail: "user@not-example.com"}, []string{"admin@admin-domain.com"}, "secret", false},
{"impersonating match email", []config.Policy{{From: "https://from.example", To: "https://to.example", AllowedUsers: []string{"user@example.com"}}}, "from.example", &Identity{Email: "admin@admin-domain.com", ImpersonateEmail: "user@example.com"}, []string{"admin@admin-domain.com"}, "secret", true},
{"impersonating does not match email", []config.Policy{{From: "https://from.example", To: "https://to.example", AllowedUsers: []string{"user@example.com"}}}, "from.example", &Identity{Email: "admin@admin-domain.com", ImpersonateEmail: "user@not-example.com"}, []string{"admin@admin-domain.com"}, "secret", false},
{"impersonating match groups", []config.Policy{{From: "https://from.example", To: "https://to.example", AllowedGroups: []string{"support"}}}, "from.example", &Identity{Email: "admin@admin-domain.com", ImpersonateGroups: []string{"support"}}, []string{"admin@admin-domain.com"}, "secret", true},
{"impersonating match many groups", []config.Policy{{From: "https://from.example", To: "https://to.example", AllowedGroups: []string{"support"}}}, "from.example", &Identity{Email: "admin@admin-domain.com", ImpersonateGroups: []string{"a", "b", "c", "support"}}, []string{"admin@admin-domain.com"}, "secret", true},
{"impersonating does not match groups", []config.Policy{{From: "https://from.example", To: "https://to.example", AllowedGroups: []string{"support"}}}, "from.example", &Identity{Email: "admin@admin-domain.com", ImpersonateGroups: []string{"not support"}}, []string{"admin@admin-domain.com"}, "secret", false},
{"impersonating does not match many groups", []config.Policy{{From: "https://from.example", To: "https://to.example", AllowedGroups: []string{"support"}}}, "from.example", &Identity{Email: "admin@admin-domain.com", ImpersonateGroups: []string{"not support", "b", "c"}}, []string{"admin@admin-domain.com"}, "secret", false},
{"impersonating does not match empty groups", []config.Policy{{From: "https://from.example", To: "https://to.example", AllowedGroups: []string{"support"}}}, "from.example", &Identity{Email: "admin@admin-domain.com", ImpersonateGroups: []string{""}}, []string{"admin@admin-domain.com"}, "secret", false},
// jwt validation
{"bad jwt shared secret", []config.Policy{{From: "https://from.example", To: "https://to.example", AllowedDomains: []string{"example.com"}}}, "from.example", &Identity{Email: "user@example.com"}, nil, "bad-secret", false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
for i := range tt.policies {
if err := (&tt.policies[i]).Validate(); err != nil {
t.Fatal(err)
}
}
key := []byte("secret")
sig, err := jose.NewSigner(jose.SigningKey{Algorithm: jose.HS256, Key: key},
(&jose.SignerOptions{}).WithType("JWT"))
if err != nil {
t.Fatal(err)
}
cl := jwt.Claims{
NotBefore: jwt.NewNumericDate(time.Now()),
Expiry: jwt.NewNumericDate(time.Now().Add(time.Hour)),
Audience: jwt.Audience{tt.route},
}
rawJWT, err := jwt.Signed(sig).Claims(cl).Claims(tt.Identity).CompactSerialize()
if err != nil {
t.Fatal(err)
}
data := map[string]interface{}{
"route_policies": tt.policies,
"admins": tt.admins,
"shared_key": tt.secret,
}
pe, err := New(context.Background(), &Options{Data: data})
if err != nil {
t.Fatal(err)
}
req := struct {
Host string `json:"host,omitempty"`
URL string `json:"url,omitempty"`
User string `json:"user,omitempty"`
}{
Host: tt.route,
URL: "https://" + tt.route,
User: rawJWT,
}
got, err := pe.IsAuthorized(context.TODO(), req)
if err != nil {
t.Fatal(err)
}
if got.GetAllow() != tt.want {
t.Errorf("pe.Eval() = %v, want %v", got.GetAllow(), tt.want)
}
})
}
}