Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Kuadrants AuthPolicy #158

Merged
merged 3 commits into from
Jan 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion config/settings.local.yaml.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,10 @@
# deploy: false # If false, the testsuite will use already deployed authorino for testing
# url: "" # URL for already deployed Authorino
# envoy:
# image: "docker.io/envoyproxy/envoy:v1.23-latest" # Envoy image, the testsuite should use, only for Authorino tests now
# image: "docker.io/envoyproxy/envoy:v1.23-latest" # Envoy image, the testsuite should use, only for Authorino tests now
# kuadrant:
# enabled: true # True, if Testsuite should test Kuadrant instead of individual operators
# namespace: "kuadrant" # Namespaces where Kuadrant resides
# gateway: # Reference to Gateway that should be used
# namespace: "istio-system"
# name: "istio-ingressgateway"
8 changes: 7 additions & 1 deletion config/settings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,10 @@ default:
deploy: true
log_level: "debug"
envoy:
image: "docker.io/envoyproxy/envoy:v1.23-latest"
image: "docker.io/envoyproxy/envoy:v1.23-latest"
kuadrant:
enabled: true
pehala marked this conversation as resolved.
Show resolved Hide resolved
project: "kuadrant"
gateway:
project: "istio-system"
name: "istio-ingressgateway"
3 changes: 2 additions & 1 deletion testsuite/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ def __init__(self, name, default, **kwargs) -> None:
DefaultValueValidator("rhsso.url", default=fetch_route("no-ssl-sso")),
DefaultValueValidator("rhsso.password", default=fetch_secret("credential-sso", "ADMIN_PASSWORD")),
DefaultValueValidator("mockserver.url", default=fetch_route("mockserver", force_http=True)),
Validator("kuadrant.enable", must_exist=False, eq=False) | Validator("kuadrant.gateway.name", must_exist=True),
],
validate_only=["authorino"],
validate_only=["authorino", "kuadrant"],
loaders=["dynaconf.loaders.env_loader", "testsuite.config.openshift_loader"]
)
9 changes: 8 additions & 1 deletion testsuite/openshift/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import os
from functools import cached_property
from typing import Dict, Optional
from urllib.parse import urlparse

import openshift as oc
from openshift import Context, Selector, OpenShiftPythonException
Expand Down Expand Up @@ -34,7 +35,7 @@ def __init__(self, project: str, api_url: str = None, token: str = None, kubecon
self.token = token
self._kubeconfig_path = kubeconfig_path

def change_project(self, project):
def change_project(self, project) -> "OpenShiftClient":
"""Return new OpenShiftClient with a different project"""
return OpenShiftClient(project, self._api_url, self.token, self._kubeconfig_path)

Expand All @@ -56,6 +57,12 @@ def api_url(self):
with self.context:
return oc.whoami("--show-server=true")

@cached_property
def apps_url(self):
"""Return URL under which all routes are routed"""
hostname = urlparse(self.api_url).hostname
return "apps." + hostname.split(".", 1)[1]

@property
def project(self):
"""Returns real OpenShift project name"""
Expand Down
28 changes: 16 additions & 12 deletions testsuite/openshift/envoy.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,47 @@
from functools import cached_property
from importlib import resources

from openshift import Selector

from testsuite.httpx import HttpxBackoffClient
from testsuite.objects import LifecycleObject
from testsuite.openshift.client import OpenShiftClient
from testsuite.openshift.httpbin import Httpbin
from testsuite.openshift.objects.proxy import Proxy
from testsuite.openshift.objects.route import OpenshiftRoute, Route


class Envoy(LifecycleObject):
class Envoy(Proxy):
"""Envoy deployed from template"""
def __init__(self, openshift: OpenShiftClient, authorino, name, label, httpbin_hostname, image) -> None:
def __init__(self, openshift: OpenShiftClient, authorino, name, label, httpbin: Httpbin, image) -> None:
self.openshift = openshift
self.authorino = authorino
self.name = name
self.label = label
self.httpbin_hostname = httpbin_hostname
self.httpbin_hostname = httpbin.url
self.image = image

self.envoy_objects = None
self.envoy_objects: Selector = None # type: ignore

@cached_property
def route(self):
def route(self) -> Route:
"""Returns route for object"""
with self.openshift.context:
return self.envoy_objects\
.narrow("route")\
.narrow(lambda route: route.model.metadata.name == self.name)\
.object()
.object(cls=OpenshiftRoute)

def create_route(self, name):
jsmolar marked this conversation as resolved.
Show resolved Hide resolved
"""Creates another route pointing to this Envoy"""
route = self.openshift.routes.expose(name, self.name)
def add_hostname(self, name) -> str:
"""Add another hostname that points to this Envoy"""
route = OpenshiftRoute(dict_to_model=self.openshift.routes.expose(name, self.name).as_dict())
with self.openshift.context:
self.envoy_objects = self.envoy_objects.union(route.self_selector())
return route
return route.hostnames[0]

@cached_property
def hostname(self):
jsmolar marked this conversation as resolved.
Show resolved Hide resolved
"""Returns hostname of this envoy"""
return self.route.model.spec.host
return self.route.hostnames[0]

def client(self, **kwargs):
"""Return Httpx client for the requests to this backend"""
Expand Down
13 changes: 12 additions & 1 deletion testsuite/openshift/httpbin.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@

from testsuite.objects import LifecycleObject
from testsuite.openshift.client import OpenShiftClient
from testsuite.openshift.objects.gateway_api import Referencable


class Httpbin(LifecycleObject):
class Httpbin(LifecycleObject, Referencable):
"""Httpbin deployed in OpenShift through template"""
def __init__(self, openshift: OpenShiftClient, name, label) -> None:
super().__init__()
Expand All @@ -16,6 +17,16 @@ def __init__(self, openshift: OpenShiftClient, name, label) -> None:

self.httpbin_objects = None

@property
def reference(self):
return {
"group": "",
"kind": "Service",
"port": 8080,
"name": self.name,
"namespace": self.openshift.project
}

@property
def url(self):
"""URL for the httpbin service"""
Expand Down
13 changes: 10 additions & 3 deletions testsuite/openshift/objects/auth_config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,17 @@
from testsuite.openshift.objects import OpenShiftObject, modify
from .sections import AuthorizationsSection, IdentitySection, MetadataSection, \
ResponsesSection
from ..route import Route


class AuthConfig(OpenShiftObject, Authorization):
"""Represents AuthConfig CR from Authorino"""

@property
def auth_section(self):
"""Returns objects where all auth related things should be added"""
return self.model.spec

@cached_property
def authorization(self) -> Authorizations:
"""Gives access to authorization settings"""
Expand All @@ -33,7 +39,8 @@ def responses(self) -> Responses:
return ResponsesSection(self, "response")

@classmethod
def create_instance(cls, openshift: OpenShiftClient, name, host, labels: Dict[str, str] = None):
def create_instance(cls, openshift: OpenShiftClient, name, route: Route,
jsmolar marked this conversation as resolved.
Show resolved Hide resolved
labels: Dict[str, str] = None, hostnames=None):
"""Creates base instance"""
model: Dict = {
"apiVersion": "authorino.kuadrant.io/v1beta1",
Expand All @@ -43,7 +50,7 @@ def create_instance(cls, openshift: OpenShiftClient, name, host, labels: Dict[st
"namespace": openshift.project
},
"spec": {
"hosts": [host]
"hosts": hostnames or route.hostnames
}
}

Expand All @@ -70,5 +77,5 @@ def remove_all_hosts(self):
@modify
def set_deny_with(self, code, value):
"""Set denyWith"""
self.model.spec["denyWith"] = {
self.auth_section["denyWith"] = {
"unauthenticated": {"code": code, "headers": [{"name": "Location", "valueFrom": {"authJSON": value}}]}}
42 changes: 42 additions & 0 deletions testsuite/openshift/objects/auth_config/auth_policy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"""Module containing classes related to Auth Policy"""
from typing import Dict

from testsuite.openshift.client import OpenShiftClient
from testsuite.openshift.objects.auth_config import AuthConfig
from testsuite.openshift.objects.gateway_api import Referencable


class AuthPolicy(AuthConfig):
"""AuthPolicy object, it serves as Kuadrants AuthConfig"""

@property
def auth_section(self):
return self.model.spec.setdefault("authScheme", {})

# pylint: disable=unused-argument
@classmethod
def create_instance( # type: ignore
cls,
openshift: OpenShiftClient,
name,
route: Referencable,
labels: Dict[str, str] = None,
hostnames=None,
):
"""Creates base instance"""
model: Dict = {
"apiVersion": "kuadrant.io/v1beta1",
"kind": "AuthPolicy",
"metadata": {
"name": name,
"namespace": openshift.project,
},
"spec": {
"targetRef": route.reference,
},
}

if labels is not None:
model["metadata"]["labels"] = labels

return cls(model, context=openshift.context)
11 changes: 7 additions & 4 deletions testsuite/openshift/objects/auth_config/sections.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
"""AuthConfig CR object"""
from dataclasses import asdict
from typing import Dict, Literal, Iterable
from typing import Dict, Literal, Iterable, TYPE_CHECKING

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

if TYPE_CHECKING:
from testsuite.openshift.objects.auth_config import AuthConfig


class Section:
"""Common class for all Sections"""
def __init__(self, obj: OpenShiftObject, section_name) -> None:
def __init__(self, obj: "AuthConfig", section_name) -> None:
super().__init__()
self.obj = obj
self.section_name = section_name
Expand All @@ -27,7 +30,7 @@ def committed(self):
@property
def section(self):
"""The actual dict section which will be edited"""
return self.obj.model.spec.setdefault(self.section_name, [])
return self.obj.auth_section.setdefault(self.section_name, [])

def add_item(self, name, value, priority: int = None, when: Iterable[Rule] = None,
metrics: bool = None, cache: Cache = None):
Expand Down
Loading