1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2024-12-14 11:57:48 +00:00

Merge pull request #947 from NoSkillGirl/feature/new_operators

Feature/new operators
This commit is contained in:
Jim Bugwadia 2020-06-26 17:26:24 -07:00 committed by GitHub
commit ec7969df31
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 219 additions and 3 deletions

View file

@ -226,6 +226,8 @@ spec:
- Equals
- NotEqual
- NotEquals
- In
- NotIn
type: string
value:
type: string

View file

@ -228,10 +228,15 @@ spec:
- Equals
- NotEqual
- NotEquals
- In
- NotIn
key:
type: string
value:
type: string
anyOf:
- type: string
- type: array
items: {}
generate:
type: object
required:

View file

@ -231,9 +231,14 @@ spec:
- Equals
- NotEqual
- NotEquals
- In
- NotIn
type: string
value:
type: string
anyOf:
- type: string
- type: array
items: {}
required:
- key
- operator

View file

@ -231,9 +231,14 @@ spec:
- Equals
- NotEqual
- NotEquals
- In
- NotIn
type: string
value:
type: string
anyOf:
- type: string
- type: array
items: {}
required:
- key
- operator

View file

@ -9,6 +9,8 @@ While `match` & `exclude` conditions allow filtering requests based on resource
The following operators are currently supported for preconditon evaluation:
- Equal
- NotEqual
- In
- NotIn
## Example
@ -26,5 +28,19 @@ The following operators are currently supported for preconditon evaluation:
In the above example, the rule is only applied to requests from service accounts i.e. when the `{{serviceAccountName}}` is not empty.
```yaml
- name: generate-default-build-role
match:
resources:
kinds:
- Namespace
preconditions:
- key: "{{serviceAccountName}}"
operator: In
value: ["build-default", "build-base"]
```
In the above example, the rule is only applied to requests from service account with name `build-default` and `build-base`.
<small>*Read Next >> [Auto-Generation for Pod Controllers](/documentation/writing-policies-autogen.md)*</small>

2
go.sum
View file

@ -1068,6 +1068,8 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gotest.tools v1.4.0 h1:BjtEgfuw8Qyd+jPvQz8CfoxiO/UjFEidWinwEXZiWv0=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

View file

@ -0,0 +1,96 @@
package operator
import (
"fmt"
"reflect"
"github.com/go-logr/logr"
"github.com/nirmata/kyverno/pkg/engine/context"
)
//NewInHandler returns handler to manage In operations
func NewInHandler(log logr.Logger, ctx context.EvalInterface, subHandler VariableSubstitutionHandler) OperatorHandler {
return InHandler{
ctx: ctx,
subHandler: subHandler,
log: log,
}
}
//InHandler provides implementation to handle In Operator
type InHandler struct {
ctx context.EvalInterface
subHandler VariableSubstitutionHandler
log logr.Logger
}
//Evaluate evaluates expression with In Operator
func (in InHandler) Evaluate(key, value interface{}) bool {
var err error
// substitute the variables
if key, err = in.subHandler(in.log, in.ctx, key); err != nil {
in.log.Error(err, "Failed to resolve variable", "variable", key)
return false
}
if value, err = in.subHandler(in.log, in.ctx, value); err != nil {
in.log.Error(err, "Failed to resolve variable", "variable", value)
return false
}
switch typedKey := key.(type) {
case string:
return in.validateValuewithStringPattern(typedKey, value)
default:
in.log.Info("Unsupported type", "value", typedKey, "type", fmt.Sprintf("%T", typedKey))
return false
}
}
func (in InHandler) validateValuewithStringPattern(key string, value interface{}) (keyExists bool) {
invalidType, keyExists := ValidateStringPattern(key, value)
if invalidType {
in.log.Info("expected type []string", "value", value, "type", fmt.Sprintf("%T", value))
return false
}
return keyExists
}
func ValidateStringPattern(key string, value interface{}) (invalidType bool, keyExists bool) {
stringType := reflect.TypeOf("")
switch valuesAvaliable := value.(type) {
case []interface{}:
for _, val := range valuesAvaliable {
if reflect.TypeOf(val) != stringType {
return true, false
}
if key == val {
keyExists = true
}
}
default:
return true, false
}
return invalidType, keyExists
}
func (in InHandler) validateValuewithBoolPattern(key bool, value interface{}) bool {
return false
}
func (in InHandler) validateValuewithIntPattern(key int64, value interface{}) bool {
return false
}
func (in InHandler) validateValuewithFloatPattern(key float64, value interface{}) bool {
return false
}
func (in InHandler) validateValueWithMapPattern(key map[string]interface{}, value interface{}) bool {
return false
}
func (in InHandler) validateValueWithSlicePattern(key []interface{}, value interface{}) bool {
return false
}

View file

@ -0,0 +1,81 @@
package operator
import (
"fmt"
"github.com/go-logr/logr"
"github.com/nirmata/kyverno/pkg/engine/context"
)
//NewNotInHandler returns handler to manage NotIn operations
func NewNotInHandler(log logr.Logger, ctx context.EvalInterface, subHandler VariableSubstitutionHandler) OperatorHandler {
return NotInHandler{
ctx: ctx,
subHandler: subHandler,
log: log,
}
}
//NotInHandler provides implementation to handle NotIn Operator
type NotInHandler struct {
ctx context.EvalInterface
subHandler VariableSubstitutionHandler
log logr.Logger
}
//Evaluate evaluates expression with NotIn Operator
func (nin NotInHandler) Evaluate(key, value interface{}) bool {
var err error
// substitute the variables
if key, err = nin.subHandler(nin.log, nin.ctx, key); err != nil {
nin.log.Error(err, "Failed to resolve variable", "variable", key)
return false
}
if value, err = nin.subHandler(nin.log, nin.ctx, value); err != nil {
nin.log.Error(err, "Failed to resolve variable", "variable", value)
return false
}
switch typedKey := key.(type) {
case string:
return nin.validateValuewithStringPattern(typedKey, value)
default:
nin.log.Info("Unsupported type", "value", typedKey, "type", fmt.Sprintf("%T", typedKey))
return false
}
}
func (nin NotInHandler) validateValuewithStringPattern(key string, value interface{}) bool {
invalidType, keyExists := ValidateStringPattern(key, value)
if invalidType {
nin.log.Info("expected type []string", "value", value, "type", fmt.Sprintf("%T", value))
return false
}
if !keyExists {
return true
}
return false
}
func (nin NotInHandler) validateValuewithBoolPattern(key bool, value interface{}) bool {
return false
}
func (nin NotInHandler) validateValuewithIntPattern(key int64, value interface{}) bool {
return false
}
func (nin NotInHandler) validateValuewithFloatPattern(key float64, value interface{}) bool {
return false
}
func (nin NotInHandler) validateValueWithMapPattern(key map[string]interface{}, value interface{}) bool {
return false
}
func (nin NotInHandler) validateValueWithSlicePattern(key []interface{}, value interface{}) bool {
return false
}

View file

@ -30,6 +30,10 @@ func CreateOperatorHandler(log logr.Logger, ctx context.EvalInterface, op kyvern
return NewEqualHandler(log, ctx, subHandler)
case kyverno.NotEquals:
return NewNotEqualHandler(log, ctx, subHandler)
case kyverno.In:
return NewInHandler(log, ctx, subHandler)
case kyverno.NotIn:
return NewNotInHandler(log, ctx, subHandler)
default:
log.Info("operator not supported", "operator", string(op))
}