Skip to content

Commit

Permalink
Add support for common_features
Browse files Browse the repository at this point in the history
- Implemented as kwargs
  • Loading branch information
pehala committed Nov 29, 2022
1 parent 9b2f281 commit f670694
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 38 deletions.
37 changes: 36 additions & 1 deletion testsuite/objects/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class MatchExpression:
@dataclass
class Rule:
"""
Data class for authorization rules represented by simple pattern-matching expressions.
Data class for rules represented by simple pattern-matching expressions.
Args:
:param selector: that is fetched from the Authorization JSON
:param operator: `eq` (equals), `neq` (not equal), `incl` (includes) and `excl` (excludes), for arrays
Expand All @@ -35,6 +35,41 @@ class Rule:
value: str


class Value:
"""Dataclass for specifying a Value in Authorization, can be either constant on value from AuthJson (jsonPath)"""

# pylint: disable=invalid-name
def __init__(self, value=None, jsonPath=None) -> None:
super().__init__()
if not (value is None) ^ (jsonPath is None):
raise AttributeError("Exactly one of the `value` and `jsonPath` argument must be specified")
self.value = value
self.jsonPath = jsonPath

def to_dict(self):
"""Returns dict representation of itself (shallow copy only)"""
return {"value": self.value} if self.value else {"valueFrom": {"authJson": self.jsonPath}}


@dataclass
class Cache:
"""Dataclass for specifying Cache in Authorization"""
ttl: int
# pylint: disable=invalid-name
value: Value

def to_dict(self):
"""Returns dict representation of itself (shallow copy only)"""
return {"ttl": self.ttl, "value": self.value.to_dict()}


@dataclass
class PatternRef:
"""Dataclass for specifying Pattern reference in Authorization"""
# pylint: disable=invalid-name
patternRef: str


class LifecycleObject(abc.ABC):
"""Any objects which has its lifecycle controlled by create() and delete() methods"""

Expand Down
22 changes: 11 additions & 11 deletions testsuite/objects/sections.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,39 +11,39 @@ class Authorizations(abc.ABC):
"""Authorization configuration"""

@abc.abstractmethod
def opa_policy(self, name, rego_policy):
def opa_policy(self, name, rego_policy, **common_features):
"""Adds OPA inline Rego policy"""

@abc.abstractmethod
def external_opa_policy(self, name, endpoint, ttl):
def external_opa_policy(self, name, endpoint, ttl, **common_features):
"""Adds OPA policy from external registry"""

@abc.abstractmethod
def role_rule(self, name: str, role: str, path: str, metrics: bool, priority: int):
def role_rule(self, name: str, role: str, path: str, metrics: bool, priority: int, **common_features):
"""Adds a rule, which allows access to 'path' only to users with 'role'"""

@abc.abstractmethod
def auth_rule(self, name: str, rule: "Rule", when: "Rule", metrics: bool, priority: int):
def auth_rule(self, name: str, rule: "Rule", when: "Rule", metrics: bool, priority: int, **common_features):
"""Adds JSON pattern-matching authorization rule (authorization.json)"""


class Identities(abc.ABC):
"""Identities configuration"""

@abc.abstractmethod
def oidc(self, name, endpoint, credentials, selector):
def oidc(self, name, endpoint, credentials, selector, **common_features):
"""Adds OIDC identity provider"""

@abc.abstractmethod
def api_key(self, name, all_namespaces, match_label, match_expression, credentials, selector):
def api_key(self, name, all_namespaces, match_label, match_expression, credentials, selector, **common_features):
"""Adds API Key identity"""

@abc.abstractmethod
def mtls(self, name: str, selector_key: str, selector_value: str):
def mtls(self, name: str, selector_key: str, selector_value: str, **common_features):
"""Adds mTLS identity"""

@abc.abstractmethod
def anonymous(self, name):
def anonymous(self, name, **common_features):
"""Adds anonymous identity"""

@abc.abstractmethod
Expand All @@ -55,17 +55,17 @@ class Metadata(abc.ABC):
"""Metadata configuration"""

@abc.abstractmethod
def http_metadata(self, name, endpoint, method):
def http_metadata(self, name, endpoint, method, **common_features):
"""Set metadata http external auth feature"""

@abc.abstractmethod
def user_info_metadata(self, name, identity_source):
def user_info_metadata(self, name, identity_source, **common_features):
"""Set metadata OIDC user info"""


class Responses(abc.ABC):
"""Responses configuration"""

@abc.abstractmethod
def add(self, response):
def add(self, response, **common_features):
"""Add response to AuthConfig"""
62 changes: 36 additions & 26 deletions testsuite/openshift/objects/auth_config/sections.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"""AuthConfig CR object"""
from dataclasses import asdict
from typing import Dict, Literal
from typing import Dict, Literal, Iterable

from testsuite.objects import Identities, Metadata, Responses, MatchExpression, Authorizations, Rule
from testsuite.objects import Identities, Metadata, Responses, MatchExpression, Authorizations, Rule, Cache
from testsuite.openshift.objects import OpenShiftObject, modify


Expand All @@ -29,16 +29,26 @@ def section(self):
"""The actual dict section which will be edited"""
return self.obj.model.spec.setdefault(self.section_name, [])

def add_item(self, name, value):
def add_item(self, name, value, priority: int = None, when: Iterable[Rule] = None,
metrics: bool = None, cache: Cache = None):
"""Adds item to the section"""
self.section.append({"name": name, **value})
item = {"name": name, **value}
if when:
item["when"] = [asdict(x) for x in when]
if metrics:
item["metrics"] = metrics
if cache:
item["cache"] = cache.to_dict()
if priority:
item["priority"] = priority
self.section.append(item)


class IdentitySection(Section, Identities):
"""Section which contains identity configuration"""

@modify
def mtls(self, name: str, selector_key: str, selector_value: str):
def mtls(self, name: str, selector_key: str, selector_value: str, **common_features):
"""Adds mTLS identity
Args:
:param name: name of the identity
Expand All @@ -53,10 +63,10 @@ def mtls(self, name: str, selector_key: str, selector_value: str):
}
}
}
})
}, **common_features)

@modify
def oidc(self, name, endpoint, credentials="authorization_header", selector="Bearer"):
def oidc(self, name, endpoint, credentials="authorization_header", selector="Bearer", **common_features):
"""Adds OIDC identity"""
self.add_item(name, {
"oidc": {
Expand All @@ -66,12 +76,12 @@ def oidc(self, name, endpoint, credentials="authorization_header", selector="Bea
"in": credentials,
"keySelector": selector
}
})
}, **common_features)

@modify
def api_key(self, name, all_namespaces: bool = False,
match_label=None, match_expression: MatchExpression = None,
credentials="authorization_header", selector="APIKEY"):
credentials="authorization_header", selector="APIKEY", **common_features):
"""
Adds API Key identity
Args:
Expand Down Expand Up @@ -107,12 +117,12 @@ def api_key(self, name, all_namespaces: bool = False,
"in": credentials,
"keySelector": selector
}
})
}, **common_features)

@modify
def anonymous(self, name):
def anonymous(self, name, **common_features):
"""Adds anonymous identity"""
self.add_item(name, {"anonymous": {}})
self.add_item(name, {"anonymous": {}}, **common_features)

@modify
def remove_all(self):
Expand All @@ -123,40 +133,40 @@ def remove_all(self):
class MetadataSection(Section, Metadata):
"""Section which contains metadata configuration"""
@modify
def http_metadata(self, name, endpoint, method: Literal["GET", "POST"]):
def http_metadata(self, name, endpoint, method: Literal["GET", "POST"], **common_features):
"""Set metadata http external auth feature"""
self.add_item(name, {
"http": {
"endpoint": endpoint,
"method": method,
"headers": [{"name": "Accept", "value": "application/json"}]
}
})
}, **common_features)

@modify
def user_info_metadata(self, name, identity_source):
def user_info_metadata(self, name, identity_source, **common_features):
"""Set metadata OIDC user info"""
self.add_item(name, {
"userInfo": {
"identitySource": identity_source
}
})
}, **common_features)


class ResponsesSection(Section, Responses):
"""Section which contains response configuration"""

@modify
def add(self, response):
def add(self, response, **common_features):
"""Adds response section to AuthConfig."""
self.add_item(response.pop("name"), response)
self.add_item(response.pop("name"), response, **common_features)


class AuthorizationsSection(Section, Authorizations):
"""Section which contains authorization configuration"""

@modify
def auth_rule(self, name, rule: Rule, when: Rule = None, metrics=False, priority=0):
def auth_rule(self, name, rule: Rule, when: Rule = None, metrics=False, priority=0, **common_features):
"""Adds JSON pattern-matching authorization rule (authorization.json)"""
section = {
"metrics": metrics,
Expand All @@ -167,9 +177,9 @@ def auth_rule(self, name, rule: Rule, when: Rule = None, metrics=False, priority
}
if when:
section["when"] = [asdict(when)]
self.add_item(name, section)
self.add_item(name, section, **common_features)

def role_rule(self, name: str, role: str, path: str, metrics=False, priority=0):
def role_rule(self, name: str, role: str, path: str, metrics=False, priority=0, **common_features):
"""
Adds a rule, which allows access to 'path' only to users with 'role'
Args:
Expand All @@ -181,19 +191,19 @@ def role_rule(self, name: str, role: str, path: str, metrics=False, priority=0):
"""
rule = Rule("auth.identity.realm_access.roles", "incl", role)
when = Rule("context.request.http.path", "matches", path)
self.auth_rule(name, rule, when, metrics, priority)
self.auth_rule(name, rule, when, metrics, priority, **common_features)

@modify
def opa_policy(self, name, rego_policy):
def opa_policy(self, name, rego_policy, **common_features):
"""Adds Opa (https://www.openpolicyagent.org/docs/latest/) policy to the AuthConfig"""
self.add_item(name, {
"opa": {
"inlineRego": rego_policy
}
})
}, **common_features)

@modify
def external_opa_policy(self, name, endpoint, ttl=0):
def external_opa_policy(self, name, endpoint, ttl=0, **common_features):
"""
Adds OPA policy that is declared as an HTTP endpoint
"""
Expand All @@ -204,4 +214,4 @@ def external_opa_policy(self, name, endpoint, ttl=0):
"ttl": ttl
}
}
})
}, **common_features)

0 comments on commit f670694

Please sign in to comment.