Documentation ¶
Index ¶
- Variables
- func Authz() cel.EnvOption
- func CIDR() cel.EnvOption
- func IP() cel.EnvOption
- func Lists() cel.EnvOption
- func NewAuthorizerVal(userInfo user.Info, authorizer authorizer.Authorizer) ref.Val
- func NewResourceAuthorizerVal(userInfo user.Info, authorizer authorizer.Authorizer, requestResource Resource) ref.Val
- func Quantity() cel.EnvOption
- func Regex() cel.EnvOption
- func Test(options ...TestOption) cel.EnvOption
- func TestVersion(version uint32) func(lib *testLib) *testLib
- func URLs() cel.EnvOption
- type CostEstimator
- func (l *CostEstimator) CallCost(function, overloadId string, args []ref.Val, result ref.Val) *uint64
- func (l *CostEstimator) EstimateCallCost(function, overloadId string, target *checker.AstNode, args []checker.AstNode) *checker.CallEstimate
- func (l *CostEstimator) EstimateSize(element checker.AstNode) *checker.SizeEstimate
- type Resource
- type TestOption
Constants ¶
This section is empty.
Variables ¶
var ( AuthorizerType = cel.ObjectType("kubernetes.authorization.Authorizer") PathCheckType = cel.ObjectType("kubernetes.authorization.PathCheck") GroupCheckType = cel.ObjectType("kubernetes.authorization.GroupCheck") ResourceCheckType = cel.ObjectType("kubernetes.authorization.ResourceCheck") DecisionType = cel.ObjectType("kubernetes.authorization.Decision") )
var FindAllRegexOptimization = &interpreter.RegexOptimization{ Function: "findAll", RegexIndex: 1, Factory: func(call interpreter.InterpretableCall, regexPattern string) (interpreter.InterpretableCall, error) { compiledRegex, err := regexp.Compile(regexPattern) if err != nil { return nil, err } return interpreter.NewCall(call.ID(), call.Function(), call.OverloadID(), call.Args(), func(args ...ref.Val) ref.Val { argn := len(args) if argn < 2 || argn > 3 { return types.NoSuchOverloadErr() } str, ok := args[0].Value().(string) if !ok { return types.MaybeNoSuchOverloadErr(args[0]) } n := int64(-1) if argn == 3 { n, ok = args[2].Value().(int64) if !ok { return types.MaybeNoSuchOverloadErr(args[2]) } } result := compiledRegex.FindAllString(str, int(n)) return types.NewStringList(types.DefaultTypeAdapter, result) }), nil }, }
FindAllRegexOptimization optimizes the 'findAll' function by compiling the regex pattern and reporting any compilation errors at program creation time, and using the compiled regex pattern for all function call invocations.
var FindRegexOptimization = &interpreter.RegexOptimization{ Function: "find", RegexIndex: 1, Factory: func(call interpreter.InterpretableCall, regexPattern string) (interpreter.InterpretableCall, error) { compiledRegex, err := regexp.Compile(regexPattern) if err != nil { return nil, err } return interpreter.NewCall(call.ID(), call.Function(), call.OverloadID(), call.Args(), func(args ...ref.Val) ref.Val { if len(args) != 2 { return types.NoSuchOverloadErr() } in, ok := args[0].Value().(string) if !ok { return types.MaybeNoSuchOverloadErr(args[0]) } return types.String(compiledRegex.FindString(in)) }), nil }, }
FindRegexOptimization optimizes the 'find' function by compiling the regex pattern and reporting any compilation errors at program creation time, and using the compiled regex pattern for all function call invocations.
Functions ¶
func Authz ¶ added in v0.27.0
Authz provides a CEL function library extension for performing authorization checks. Note that authorization checks are only supported for CEL expression fields in the API where an 'authorizer' variable is provided to the CEL expression. See the documentation of API fields where CEL expressions are used to learn if the 'authorizer' variable is provided.
path
Returns a PathCheck configured to check authorization for a non-resource request path (e.g. /healthz). If path is an empty string, an error is returned. Note that the leading '/' is not required.
<Authorizer>.path(<string>) <PathCheck>
Examples:
authorizer.path('/healthz') // returns a PathCheck for the '/healthz' API path authorizer.path('') // results in "path must not be empty" error authorizer.path(' ') // results in "path must not be empty" error
group
Returns a GroupCheck configured to check authorization for the API resources for a particular API group. Note that authorization checks are only supported for CEL expression fields in the API where an 'authorizer' variable is provided to the CEL expression. Check the documentation of API fields where CEL expressions are used to learn if the 'authorizer' variable is provided.
<Authorizer>.group(<string>) <GroupCheck>
Examples:
authorizer.group('apps') // returns a GroupCheck for the 'apps' API group authorizer.group('') // returns a GroupCheck for the core API group authorizer.group('example.com') // returns a GroupCheck for the custom resources in the 'example.com' API group
serviceAccount
Returns an Authorizer configured to check authorization for the provided service account namespace and name. If the name is not a valid DNS subdomain string (as defined by RFC 1123), an error is returned. If the namespace is not a valid DNS label (as defined by RFC 1123), an error is returned.
<Authorizer>.serviceAccount(<string>, <string>) <Authorizer>
Examples:
authorizer.serviceAccount('default', 'myserviceaccount') // returns an Authorizer for the service account with namespace 'default' and name 'myserviceaccount' authorizer.serviceAccount('not@a#valid!namespace', 'validname') // returns an error authorizer.serviceAccount('valid.example.com', 'invalid@*name') // returns an error
resource
Returns a ResourceCheck configured to check authorization for a particular API resource. Note that the provided resource string should be a lower case plural name of a Kubernetes API resource.
<GroupCheck>.resource(<string>) <ResourceCheck>
Examples:
authorizer.group('apps').resource('deployments') // returns a ResourceCheck for the 'deployments' resources in the 'apps' group. authorizer.group('').resource('pods') // returns a ResourceCheck for the 'pods' resources in the core group. authorizer.group('apps').resource('') // results in "resource must not be empty" error authorizer.group('apps').resource(' ') // results in "resource must not be empty" error
subresource
Returns a ResourceCheck configured to check authorization for a particular subresource of an API resource. If subresource is set to "", the subresource field of this ResourceCheck is considered unset.
<ResourceCheck>.subresource(<string>) <ResourceCheck>
Examples:
authorizer.group('').resource('pods').subresource('status') // returns a ResourceCheck the 'status' subresource of 'pods' authorizer.group('apps').resource('deployments').subresource('scale') // returns a ResourceCheck the 'scale' subresource of 'deployments' authorizer.group('example.com').resource('widgets').subresource('scale') // returns a ResourceCheck for the 'scale' subresource of the 'widgets' custom resource authorizer.group('example.com').resource('widgets').subresource('') // returns a ResourceCheck for the 'widgets' resource.
namespace
Returns a ResourceCheck configured to check authorization for a particular namespace. For cluster scoped resources, namespace() does not need to be called; namespace defaults to "", which is the correct namespace value to use to check cluster scoped resources. If namespace is set to "", the ResourceCheck will check authorization for the cluster scope.
<ResourceCheck>.namespace(<string>) <ResourceCheck>
Examples:
authorizer.group('apps').resource('deployments').namespace('test') // returns a ResourceCheck for 'deployments' in the 'test' namespace authorizer.group('').resource('pods').namespace('default') // returns a ResourceCheck for 'pods' in the 'default' namespace authorizer.group('').resource('widgets').namespace('') // returns a ResourceCheck for 'widgets' in the cluster scope
name
Returns a ResourceCheck configured to check authorization for a particular resource name. If name is set to "", the name field of this ResourceCheck is considered unset.
<ResourceCheck>.name(<name>) <ResourceCheck>
Examples:
authorizer.group('apps').resource('deployments').namespace('test').name('backend') // returns a ResourceCheck for the 'backend' 'deployments' resource in the 'test' namespace authorizer.group('apps').resource('deployments').namespace('test').name('') // returns a ResourceCheck for the 'deployments' resource in the 'test' namespace
check
For PathCheck, checks if the principal (user or service account) that sent the request is authorized for the HTTP request verb of the path. For ResourceCheck, checks if the principal (user or service account) that sent the request is authorized for the API verb and the configured authorization checks of the ResourceCheck. The check operation can be expensive, particularly in clusters using the webhook authorization mode.
<PathCheck>.check(<check>) <Decision> <ResourceCheck>.check(<check>) <Decision>
Examples:
authorizer.group('').resource('pods').namespace('default').check('create') // Checks if the principal (user or service account) is authorized create pods in the 'default' namespace. authorizer.path('/healthz').check('get') // Checks if the principal (user or service account) is authorized to make HTTP GET requests to the /healthz API path.
allowed
Returns true if the authorizer's decision for the check is "allow". Note that if the authorizer's decision is "no opinion", that the 'allowed' function will return false.
<Decision>.allowed() <bool>
Examples:
authorizer.group('').resource('pods').namespace('default').check('create').allowed() // Returns true if the principal (user or service account) is allowed create pods in the 'default' namespace. authorizer.path('/healthz').check('get').allowed() // Returns true if the principal (user or service account) is allowed to make HTTP GET requests to the /healthz API path.
reason
Returns a string reason for the authorization decision
<Decision>.reason() <string>
Examples:
authorizer.path('/healthz').check('GET').reason()
errored
Returns true if the authorization check resulted in an error.
<Decision>.errored() <bool>
Examples:
authorizer.group('').resource('pods').namespace('default').check('create').errored() // Returns true if the authorization check resulted in an error
error
If the authorization check resulted in an error, returns the error. Otherwise, returns the empty string.
<Decision>.error() <string>
Examples:
authorizer.group('').resource('pods').namespace('default').check('create').error()
func CIDR ¶ added in v0.30.0
CIDR provides a CEL function library extension of CIDR notation parsing functions.
cidr
Converts a string in CIDR notation to a network address representation or results in an error if the string is not a valid CIDR notation. The CIDR must be an IPv4 or IPv6 subnet address with a mask. Leading zeros in IPv4 address octets are not allowed. IPv4-mapped IPv6 addresses (e.g. ::ffff:1.2.3.4/24) are not allowed.
cidr(<string>) <CIDR>
Examples:
cidr('192.168.0.0/16') // returns an IPv4 address with a CIDR mask cidr('::1/128') // returns an IPv6 address with a CIDR mask cidr('192.168.0.0/33') // error cidr('::1/129') // error cidr('192.168.0.1/16') // error, because there are non-0 bits after the prefix
isCIDR
Returns true if a string is a valid CIDR notation respresentation of a subnet with mask. The CIDR must be an IPv4 or IPv6 subnet address with a mask. Leading zeros in IPv4 address octets are not allowed. IPv4-mapped IPv6 addresses (e.g. ::ffff:1.2.3.4/24) are not allowed.
isCIDR(<string>) <bool>
Examples:
isCIDR('192.168.0.0/16') // returns true isCIDR('::1/128') // returns true isCIDR('192.168.0.0/33') // returns false isCIDR('::1/129') // returns false
containsIP / containerCIDR / ip / masked / prefixLength
- containsIP: Returns true if a the CIDR contains the given IP address. The IP address must be an IPv4 or IPv6 address. May take either a string or IP address as an argument.
- containsCIDR: Returns true if a the CIDR contains the given CIDR. The CIDR must be an IPv4 or IPv6 subnet address with a mask. May take either a string or CIDR as an argument.
- ip: Returns the IP address representation of the CIDR.
- masked: Returns the CIDR representation of the network address with a masked prefix. This can be used to return the canonical form of the CIDR network.
- prefixLength: Returns the prefix length of the CIDR in bits. This is the number of bits in the mask.
Examples:
cidr('192.168.0.0/24').containsIP(ip('192.168.0.1')) // returns true cidr('192.168.0.0/24').containsIP(ip('192.168.1.1')) // returns false cidr('192.168.0.0/24').containsIP('192.168.0.1') // returns true cidr('192.168.0.0/24').containsIP('192.168.1.1') // returns false cidr('192.168.0.0/16').containsCIDR(cidr('192.168.10.0/24')) // returns true cidr('192.168.1.0/24').containsCIDR(cidr('192.168.2.0/24')) // returns false cidr('192.168.0.0/16').containsCIDR('192.168.10.0/24') // returns true cidr('192.168.1.0/24').containsCIDR('192.168.2.0/24') // returns false cidr('192.168.0.1/24').ip() // returns ipAddr('192.168.0.1') cidr('192.168.0.1/24').ip().family() // returns '4' cidr('::1/128').ip() // returns ipAddr('::1') cidr('::1/128').ip().family() // returns '6' cidr('192.168.0.0/24').masked() // returns cidr('192.168.0.0/24') cidr('192.168.0.1/24').masked() // returns cidr('192.168.0.0/24') cidr('192.168.0.0/24') == cidr('192.168.0.0/24').masked() // returns true, CIDR was already in canonical format cidr('192.168.0.1/24') == cidr('192.168.0.1/24').masked() // returns false, CIDR was not in canonical format cidr('192.168.0.0/16').prefixLength() // returns 16 cidr('::1/128').prefixLength() // returns 128
func IP ¶ added in v0.30.0
IP provides a CEL function library extension of IP address parsing functions.
ip
Converts a string to an IP address or results in an error if the string is not a valid IP address. The IP address must be an IPv4 or IPv6 address. IPv4-mapped IPv6 addresses (e.g. ::ffff:1.2.3.4) are not allowed. IP addresses with zones (e.g. fe80::1%eth0) are not allowed. Leading zeros in IPv4 address octets are not allowed.
ip(<string>) <IPAddr>
Examples:
ip('127.0.0.1') // returns an IPv4 address ip('::1') // returns an IPv6 address ip('127.0.0.256') // error ip(':::1') // error
isIP
Returns true if a string is a valid IP address. The IP address must be an IPv4 or IPv6 address. IPv4-mapped IPv6 addresses (e.g. ::ffff:1.2.3.4) are not allowed. IP addresses with zones (e.g. fe80::1%eth0) are not allowed. Leading zeros in IPv4 address octets are not allowed.
isIP(<string>) <bool>
Examples:
isIP('127.0.0.1') // returns true isIP('::1') // returns true isIP('127.0.0.256') // returns false isIP(':::1') // returns false
ip.isCanonical
Returns true if the IP address is in its canonical form. There is exactly one canonical form for every IP address, so fields containing IPs in canonical form can just be treated as strings when checking for equality or uniqueness.
ip.isCanonical(<string>) <bool>
Examples:
ip.isCanonical('127.0.0.1') // returns true; all valid IPv4 addresses are canonical ip.isCanonical('2001:db8::abcd') // returns true ip.isCanonical('2001:DB8::ABCD') // returns false ip.isCanonical('2001:db8::0:0:0:abcd') // returns false
family / isUnspecified / isLoopback / isLinkLocalMulticast / isLinkLocalUnicast / isGlobalUnicast
- family: returns the IP addresses' family (IPv4 or IPv6) as an integer, either '4' or '6'.
- isUnspecified: returns true if the IP address is the unspecified address. Either the IPv4 address "0.0.0.0" or the IPv6 address "::".
- isLoopback: returns true if the IP address is the loopback address. Either an IPv4 address with a value of 127.x.x.x or an IPv6 address with a value of ::1.
- isLinkLocalMulticast: returns true if the IP address is a link-local multicast address. Either an IPv4 address with a value of 224.0.0.x or an IPv6 address in the network ff00::/8.
- isLinkLocalUnicast: returns true if the IP address is a link-local unicast address. Either an IPv4 address with a value of 169.254.x.x or an IPv6 address in the network fe80::/10.
- isGlobalUnicast: returns true if the IP address is a global unicast address. Either an IPv4 address that is not zero or 255.255.255.255 or an IPv6 address that is not a link-local unicast, loopback or multicast address.
Examples:
ip('127.0.0.1').family() // returns '4” ip('::1').family() // returns '6' ip('127.0.0.1').family() == 4 // returns true ip('::1').family() == 6 // returns true ip('0.0.0.0').isUnspecified() // returns true ip('127.0.0.1').isUnspecified() // returns false ip('::').isUnspecified() // returns true ip('::1').isUnspecified() // returns false ip('127.0.0.1').isLoopback() // returns true ip('192.168.0.1').isLoopback() // returns false ip('::1').isLoopback() // returns true ip('2001:db8::abcd').isLoopback() // returns false ip('224.0.0.1').isLinkLocalMulticast() // returns true ip('224.0.1.1').isLinkLocalMulticast() // returns false ip('ff02::1').isLinkLocalMulticast() // returns true ip('fd00::1').isLinkLocalMulticast() // returns false ip('169.254.169.254').isLinkLocalUnicast() // returns true ip('192.168.0.1').isLinkLocalUnicast() // returns false ip('fe80::1').isLinkLocalUnicast() // returns true ip('fd80::1').isLinkLocalUnicast() // returns false ip('192.168.0.1').isGlobalUnicast() // returns true ip('255.255.255.255').isGlobalUnicast() // returns false ip('2001:db8::abcd').isGlobalUnicast() // returns true ip('ff00::1').isGlobalUnicast() // returns false
func Lists ¶
Lists provides a CEL function library extension of list utility functions.
isSorted
Returns true if the provided list of comparable elements is sorted, else returns false.
<list<T>>.isSorted() <bool>, T must be a comparable type
Examples:
[1, 2, 3].isSorted() // return true ['a', 'b', 'b', 'c'].isSorted() // return true [2.0, 1.0].isSorted() // return false [1].isSorted() // return true [].isSorted() // return true
sum
Returns the sum of the elements of the provided list. Supports CEL number (int, uint, double) and duration types.
<list<T>>.sum() <T>, T must be a numeric type or a duration
Examples:
[1, 3].sum() // returns 4 [1.0, 3.0].sum() // returns 4.0 ['1m', '1s'].sum() // returns '1m1s' emptyIntList.sum() // returns 0 emptyDoubleList.sum() // returns 0.0 [].sum() // returns 0
min / max
Returns the minimum/maximum valued element of the provided list. Supports all comparable types. If the list is empty, an error is returned.
<list<T>>.min() <T>, T must be a comparable type <list<T>>.max() <T>, T must be a comparable type
Examples:
[1, 3].min() // returns 1 [1, 3].max() // returns 3 [].min() // error [1].min() // returns 1 ([0] + emptyList).min() // returns 0
indexOf / lastIndexOf
Returns either the first or last positional index of the provided element in the list. If the element is not found, -1 is returned. Supports all equatable types.
<list<T>>.indexOf(<T>) <int>, T must be an equatable type <list<T>>.lastIndexOf(<T>) <int>, T must be an equatable type
Examples:
[1, 2, 2, 3].indexOf(2) // returns 1 ['a', 'b', 'b', 'c'].lastIndexOf('b') // returns 2 [1.0].indexOf(1.1) // returns -1 [].indexOf('string') // returns -1
func NewAuthorizerVal ¶ added in v0.27.0
func NewAuthorizerVal(userInfo user.Info, authorizer authorizer.Authorizer) ref.Val
func NewResourceAuthorizerVal ¶ added in v0.27.0
func NewResourceAuthorizerVal(userInfo user.Info, authorizer authorizer.Authorizer, requestResource Resource) ref.Val
func Regex ¶
Regex provides a CEL function library extension of regex utility functions.
find / findAll
Returns substrings that match the provided regular expression. find returns the first match. findAll may optionally be provided a limit. If the limit is set and >= 0, no more than the limit number of matches are returned.
<string>.find(<string>) <string> <string>.findAll(<string>) <list <string>> <string>.findAll(<string>, <int>) <list <string>>
Examples:
"abc 123".find('[0-9]*') // returns '123' "abc 123".find('xyz') // returns '' "123 abc 456".findAll('[0-9]*') // returns ['123', '456'] "123 abc 456".findAll('[0-9]*', 1) // returns ['123'] "123 abc 456".findAll('xyz') // returns []
func Test ¶ added in v0.28.0
func Test(options ...TestOption) cel.EnvOption
Test provides a test() function that returns true.
func TestVersion ¶ added in v0.28.0
func TestVersion(version uint32) func(lib *testLib) *testLib
func URLs ¶
URLs provides a CEL function library extension of URL parsing functions.
url
Converts a string to a URL or results in an error if the string is not a valid URL. The URL must be an absolute URI or an absolute path.
url(<string>) <URL>
Examples:
url('https://user:pass@example.com:80/path?query=val#fragment') // returns a URL url('/absolute-path') // returns a URL url('https://a:b:c/') // error url('../relative-path') // error
isURL
Returns true if a string is a valid URL. The URL must be an absolute URI or an absolute path.
isURL( <string>) <bool>
Examples:
isURL('https://user:pass@example.com:80/path?query=val#fragment') // returns true isURL('/absolute-path') // returns true isURL('https://a:b:c/') // returns false isURL('../relative-path') // returns false
getScheme / getHost / getHostname / getPort / getEscapedPath / getQuery
Return the parsed components of a URL.
getScheme: If absent in the URL, returns an empty string.
getHostname: IPv6 addresses are returned without braces, e.g. "::1". If absent in the URL, returns an empty string.
getHost: IPv6 addresses are returned with braces, e.g. "[::1]". If absent in the URL, returns an empty string.
getEscapedPath: The string returned by getEscapedPath is URL escaped, e.g. "with space" becomes "with%20space". If absent in the URL, returns an empty string.
getPort: If absent in the URL, returns an empty string.
getQuery: Returns the query parameters in "matrix" form where a repeated query key is interpreted to mean that there are multiple values for that key. The keys and values are returned unescaped. If absent in the URL, returns an empty map.
<URL>.getScheme() <string> <URL>.getHost() <string> <URL>.getHostname() <string> <URL>.getPort() <string> <URL>.getEscapedPath() <string> <URL>.getQuery() <map <string>, <list <string>>
Examples:
url('/path').getScheme() // returns '' url('https://example.com/').getScheme() // returns 'https' url('https://example.com:80/').getHost() // returns 'example.com:80' url('https://example.com/').getHost() // returns 'example.com' url('https://[::1]:80/').getHost() // returns '[::1]:80' url('https://[::1]/').getHost() // returns '[::1]' url('/path').getHost() // returns '' url('https://example.com:80/').getHostname() // returns 'example.com' url('https://127.0.0.1:80/').getHostname() // returns '127.0.0.1' url('https://[::1]:80/').getHostname() // returns '::1' url('/path').getHostname() // returns '' url('https://example.com:80/').getPort() // returns '80' url('https://example.com/').getPort() // returns '' url('/path').getPort() // returns '' url('https://example.com/path').getEscapedPath() // returns '/path' url('https://example.com/path with spaces/').getEscapedPath() // returns '/path%20with%20spaces/' url('https://example.com').getEscapedPath() // returns '' url('https://example.com/path?k1=a&k2=b&k2=c').getQuery() // returns { 'k1': ['a'], 'k2': ['b', 'c']} url('https://example.com/path?key with spaces=value with spaces').getQuery() // returns { 'key with spaces': ['value with spaces']} url('https://example.com/path?').getQuery() // returns {} url('https://example.com/path').getQuery() // returns {}
Types ¶
type CostEstimator ¶
type CostEstimator struct { // SizeEstimator provides a CostEstimator.EstimateSize that this CostEstimator will delegate size estimation // calculations to if the size is not well known (i.e. a constant). SizeEstimator checker.CostEstimator }
CostEstimator implements CEL's interpretable.ActualCostEstimator and checker.CostEstimator.
func (*CostEstimator) EstimateCallCost ¶
func (l *CostEstimator) EstimateCallCost(function, overloadId string, target *checker.AstNode, args []checker.AstNode) *checker.CallEstimate
func (*CostEstimator) EstimateSize ¶
func (l *CostEstimator) EstimateSize(element checker.AstNode) *checker.SizeEstimate
type Resource ¶ added in v0.27.0
type Resource interface { // GetName returns the name of the object as presented in the request. On a CREATE operation, the client // may omit name and rely on the server to generate the name. If that is the case, this method will return // the empty string GetName() string // GetNamespace is the namespace associated with the request (if any) GetNamespace() string // GetResource is the name of the resource being requested. This is not the kind. For example: pods GetResource() schema.GroupVersionResource // GetSubresource is the name of the subresource being requested. This is a different resource, scoped to the parent resource, but it may have a different kind. // For instance, /pods has the resource "pods" and the kind "Pod", while /pods/foo/status has the resource "pods", the sub resource "status", and the kind "Pod" // (because status operates on pods). The binding resource for a pod though may be /pods/foo/binding, which has resource "pods", subresource "binding", and kind "Binding". GetSubresource() string }
Resource represents an API resource
type TestOption ¶ added in v0.28.0
type TestOption func(*testLib) *testLib