Files
releases/test/authz/testing.go
T
Patrick East c761f8353c Add in end-to-end authz benchmark testing
These will spin up a server runtime and perform similar tests to
The other authz benchmarks, except that they do it through the full
OPA server stack.

Signed-off-by: Patrick East <east.patrick@gmail.com>
2019-06-13 19:42:46 -07:00

170 lines
3.9 KiB
Go

// Copyright 2019 The OPA Authors. All rights reserved.
// Use of this source code is governed by an Apache2
// license that can be found in the LICENSE file.
// Package authz contains unit and benchmark tests for authz use-cases
// The public (non-test) APIs are meant to be used as helpers for
// other tests to build off of.
package authz
import (
"encoding/json"
"fmt"
"github.com/open-policy-agent/opa/util"
)
// Policy is a test rego policy for a token based authz system
const Policy = `package restauthz
import data.restauthz.tokens
default allow = false
allow {
tokens[input.token_id] = token
token.authz_profiles[_] = authz
re_match(authz.path, input.path)
authz.methods[_] = input.method
}`
// AllowQuery is the test query that goes with the Policy
// defined in this package
const AllowQuery = "data.restauthz.allow"
// DataSetProfile defines how the test data should be generated
type DataSetProfile struct {
NumTokens int
NumPaths int
}
// InputMode defines what type of inputs to generate for testings
type InputMode int
// InputMode types supported by GenerateInput
const (
ForbidIdentity = iota
ForbidPath = iota
ForbidMethod = iota
Allow = iota
)
// GenerateInput will use a dataset profile and desired InputMode to generate inputs for testing
func GenerateInput(profile DataSetProfile, mode InputMode) (interface{}, interface{}) {
var input string
var allow bool
switch mode {
case ForbidIdentity:
input = fmt.Sprintf(`
{
"token_id": "deadbeef",
"path": %q,
"method": "GET"
}
`, generateRequestPath(profile.NumPaths-1))
case ForbidPath:
input = fmt.Sprintf(`
{
"token_id": %q,
"path": %q,
"method": "GET"
}`, generateTokenID(profile.NumTokens-1), "/api/v1/resourcetype-deadbeef/deadbeefresourceid")
case ForbidMethod:
input = fmt.Sprintf(`
{
"token_id": %q,
"path": %q,
"method": "DEADBEEF"
}
`, generateTokenID(profile.NumTokens-1), generateRequestPath(profile.NumPaths-1))
default:
input = fmt.Sprintf(`
{
"token_id": %q,
"path": %q,
"method": "GET"
}
`, generateTokenID(profile.NumTokens-1), generateRequestPath(profile.NumPaths-1))
allow = true
}
return util.MustUnmarshalJSON([]byte(input)), allow
}
// GenerateDataset will generate a dataset for the given DatasetProfile
func GenerateDataset(profile DataSetProfile) map[string]interface{} {
return map[string]interface{}{
"restauthz": map[string]interface{}{
"tokens": generateTokensJSON(profile),
},
}
}
func generateTokensJSON(profile DataSetProfile) interface{} {
tokens := generateTokens(profile)
bs, err := json.Marshal(tokens)
if err != nil {
panic(err)
}
return util.MustUnmarshalJSON(bs)
}
type token struct {
ID string `json:"id"`
AuthzProfiles []authzProfile `json:"authz_profiles"`
}
type authzProfile struct {
Path string `json:"path"`
Methods []string `json:"methods"`
}
func generateTokens(profile DataSetProfile) map[string]token {
tokens := map[string]token{}
for i := 0; i < profile.NumTokens; i++ {
token := generateToken(profile, i)
tokens[token.ID] = token
}
return tokens
}
func generateToken(profile DataSetProfile, i int) token {
token := token{
ID: generateTokenID(i),
AuthzProfiles: generateAuthzProfiles(profile),
}
return token
}
func generateAuthzProfiles(profile DataSetProfile) []authzProfile {
profiles := make([]authzProfile, profile.NumPaths)
for i := 0; i < profile.NumPaths; i++ {
profiles[i] = generateAuthzProfile(profile, i)
}
return profiles
}
func generateAuthzProfile(profile DataSetProfile, i int) authzProfile {
return authzProfile{
Path: generateAuthzPath(i),
Methods: []string{
"POST",
"GET",
},
}
}
func generateTokenID(suffix int) string {
return fmt.Sprintf("token-%d", suffix)
}
func generateAuthzPath(i int) string {
return fmt.Sprintf("/api/v1/resourcetype-%d/*", i)
}
func generateRequestPath(i int) string {
return fmt.Sprintf("/api/v1/resourcetype-%d/somefakeresourceid000000111111", i)
}