mirror of
https://github.com/pomerium/pomerium.git
synced 2025-04-29 10:26:29 +02:00
107 lines
2.6 KiB
Go
107 lines
2.6 KiB
Go
package criteria
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/open-policy-agent/opa/ast"
|
|
|
|
"github.com/pomerium/pomerium/pkg/policy/generator"
|
|
"github.com/pomerium/pomerium/pkg/policy/parser"
|
|
"github.com/pomerium/pomerium/pkg/policy/rules"
|
|
"github.com/pomerium/pomerium/pkg/webauthnutil"
|
|
)
|
|
|
|
const (
|
|
deviceOperatorApproved = "approved"
|
|
deviceOperatorIs = "is"
|
|
deviceOperatorType = "type"
|
|
)
|
|
|
|
var deviceOperatorLookup = map[string]struct{}{
|
|
deviceOperatorApproved: {},
|
|
deviceOperatorIs: {},
|
|
deviceOperatorType: {},
|
|
}
|
|
|
|
type deviceCriterion struct {
|
|
g *Generator
|
|
}
|
|
|
|
func (deviceCriterion) DataType() CriterionDataType {
|
|
return generator.CriterionDataTypeUnknown
|
|
}
|
|
|
|
func (deviceCriterion) Name() string {
|
|
return "device"
|
|
}
|
|
|
|
func (c deviceCriterion) GenerateRule(_ string, data parser.Value) (*ast.Rule, []*ast.Rule, error) {
|
|
obj, ok := data.(parser.Object)
|
|
if !ok {
|
|
return nil, nil, fmt.Errorf("expected object for device criterion, got: %T", data)
|
|
}
|
|
|
|
for k := range obj {
|
|
_, ok := deviceOperatorLookup[k]
|
|
if !ok {
|
|
return nil, nil, fmt.Errorf("unexpected field in device criterion: %s", k)
|
|
}
|
|
}
|
|
|
|
var body ast.Body
|
|
|
|
switch {
|
|
case obj.Truthy(deviceOperatorApproved):
|
|
// must be approved
|
|
body = append(body, ast.Body{
|
|
ast.MustParseExpr(`count([x|x:=device_enrollment.approved_by]) > 0`),
|
|
}...)
|
|
case obj.Falsy(deviceOperatorApproved):
|
|
// must *not* be approved
|
|
body = append(body, ast.Body{
|
|
ast.MustParseExpr(`count([x|x:=device_enrollment.approved_by]) == 0`),
|
|
}...)
|
|
}
|
|
|
|
if v, ok := obj[deviceOperatorIs]; ok {
|
|
s, ok := v.(parser.String)
|
|
if !ok {
|
|
return nil, nil, fmt.Errorf("expected string for device criterion is operator, got %T", v)
|
|
}
|
|
body = append(body, ast.Body{
|
|
ast.Assign.Expr(ast.VarTerm("is_expect"), ast.StringTerm(string(s))),
|
|
ast.MustParseExpr(`is_expect == device_credential.id`),
|
|
}...)
|
|
}
|
|
|
|
deviceType := webauthnutil.DefaultDeviceType
|
|
if v, ok := obj[deviceOperatorType]; ok {
|
|
s, ok := v.(parser.String)
|
|
if !ok {
|
|
return nil, nil, fmt.Errorf("expected string for device criterion type operator, got %T", v)
|
|
}
|
|
deviceType = string(s)
|
|
body = append(body, ast.Body{
|
|
ast.MustParseExpr(`device_credential.id != ""`),
|
|
}...)
|
|
}
|
|
|
|
rule := NewCriterionDeviceRule(c.g, c.Name(),
|
|
ReasonDeviceOK, ReasonDeviceUnauthorized,
|
|
body, deviceType)
|
|
return rule, []*ast.Rule{
|
|
rules.GetDeviceCredential(),
|
|
rules.GetDeviceEnrollment(),
|
|
rules.GetSession(),
|
|
rules.ObjectGet(),
|
|
}, nil
|
|
}
|
|
|
|
// Device returns a Criterion based on the User's device state.
|
|
func Device(generator *Generator) Criterion {
|
|
return deviceCriterion{g: generator}
|
|
}
|
|
|
|
func init() {
|
|
Register(Device)
|
|
}
|