콘텐츠로 이동

spakky-openfga

Spakky Auth relation 인가를 위한 OpenFGA provider API입니다.

패키지 루트

OpenFGA relationship authorization provider plugin for Spakky Auth.

PLUGIN_NAME = Plugin(name='spakky-openfga') module-attribute

Plugin identifier for the OpenFGA auth provider package.

IOpenFgaCheckClient

Bases: ABC

Boundary used by the auth provider to execute OpenFGA checks.

check(request) abstractmethod

Execute an OpenFGA check request.

Source code in plugins/spakky-openfga/src/spakky/plugins/openfga/client.py
@abstractmethod
def check(self, request: OpenFgaCheckRequest) -> OpenFgaCheckResult:
    """Execute an OpenFGA check request."""
    ...

OpenFgaCheckRequest(*, user, relation, object) dataclass

Provider-local tuple check request mapped from Spakky auth refs.

user instance-attribute

OpenFGA user string.

relation instance-attribute

OpenFGA relation string.

object instance-attribute

OpenFGA object string.

OpenFgaCheckResult(*, allowed) dataclass

Provider-local check result.

allowed instance-attribute

Whether OpenFGA allowed the tuple check.

OpenFgaSdkCheckClient(config)

Bases: IOpenFgaCheckClient

Synchronous OpenFGA SDK-backed check client.

Source code in plugins/spakky-openfga/src/spakky/plugins/openfga/client.py
def __init__(self, config: OpenFgaConfig) -> None:
    self._config = config

check(request)

Execute an OpenFGA check request with the official SDK.

Source code in plugins/spakky-openfga/src/spakky/plugins/openfga/client.py
@override
def check(self, request: OpenFgaCheckRequest) -> OpenFgaCheckResult:
    """Execute an OpenFGA check request with the official SDK."""
    try:
        with OpenFgaClient(self._client_configuration()) as client:
            response = client.check(
                ClientCheckRequest(
                    user=request.user,
                    relation=request.relation,
                    object=request.object,
                )
            )
    except (ApiException, FgaValidationException) as e:
        raise OpenFgaProviderUnavailableError from e
    return OpenFgaCheckResult(allowed=response.allowed is True)

OpenFgaConfig()

Bases: BaseSettings

Runtime config for OpenFGA check-only authorization.

Source code in plugins/spakky-openfga/src/spakky/plugins/openfga/config.py
def __init__(self) -> None:
    super().__init__()

api_url = DEFAULT_OPENFGA_API_URL class-attribute instance-attribute

OpenFGA API URL.

store_id = '' class-attribute instance-attribute

OpenFGA store id used for check requests.

authorization_model_id = None class-attribute instance-attribute

Optional authorization model id for check requests.

principal_type = DEFAULT_OPENFGA_USER_TYPE class-attribute instance-attribute

OpenFGA object type prepended to principal ids without a type prefix.

tenant_separator = DEFAULT_OPENFGA_TENANT_SEPARATOR class-attribute instance-attribute

Separator used to embed tenant refs into checked object ids.

include_tenant_in_object = True class-attribute instance-attribute

Whether tenant refs are prefixed into OpenFGA object strings.

relation_check_available = True class-attribute instance-attribute

Whether OpenFGA relationship checking is available at runtime.

AbstractOpenFgaError

Bases: AbstractSpakkyFrameworkError, ABC

Base class for OpenFGA provider errors.

OpenFgaProviderUnavailableError

Bases: AbstractOpenFgaError

Raised when the OpenFGA check provider cannot be reached or used.

OpenFgaReferenceMappingError

Bases: AbstractOpenFgaError

Raised when canonical auth refs cannot be mapped to OpenFGA refs.

OpenFgaAuthProvider(client, config)

Bases: IRelationChecker, IAuthorizationPolicyEvaluator

OpenFGA check-only provider for ReBAC authorization decisions.

Source code in plugins/spakky-openfga/src/spakky/plugins/openfga/provider.py
def __init__(
    self,
    client: IOpenFgaCheckClient,
    config: OpenFgaConfig,
) -> None:
    self._client = client
    self._config = config

check_relation(request)

Check whether the subject has a relation to a resource.

Source code in plugins/spakky-openfga/src/spakky/plugins/openfga/provider.py
@override
def check_relation(self, request: RelationCheckRequest) -> AuthorizationDecision:
    """Check whether the subject has a relation to a resource."""
    return self._check(
        auth_context_subject_id=request.auth_context.subject.id,
        relation=request.relation,
        resource=request.resource,
        tenant=self._effective_tenant(request.tenant, request.auth_context.tenant),
    )

evaluate_policy(request)

Map resource/action policy evaluation to an OpenFGA relation check.

Source code in plugins/spakky-openfga/src/spakky/plugins/openfga/provider.py
@override
def evaluate_policy(self, request: AuthorizationRequest) -> AuthorizationDecision:
    """Map resource/action policy evaluation to an OpenFGA relation check."""
    return self._check(
        auth_context_subject_id=request.auth_context.subject.id,
        relation=request.action,
        resource=request.resource,
        tenant=self._effective_tenant(request.tenant, request.auth_context.tenant),
    )

openfga_auth_provider_contribution()

Return the auth capabilities contributed by spakky-openfga.

Source code in plugins/spakky-openfga/src/spakky/plugins/openfga/provider.py
@Pod(name="spakky_openfga_auth_provider_contribution")
def openfga_auth_provider_contribution() -> AuthProviderContribution:
    """Return the auth capabilities contributed by spakky-openfga."""
    return AuthProviderContribution(
        provider_id=OPENFGA_AUTH_PROVIDER_ID,
        capabilities=frozenset(
            {
                AuthCapability.POLICY_EVALUATION,
                AuthCapability.RELATION_CHECK,
            }
        ),
    )

플러그인 진입점

Plugin initialization for the OpenFGA auth provider.

initialize(app)

Register OpenFGA check client and auth provider bindings.

Source code in plugins/spakky-openfga/src/spakky/plugins/openfga/main.py
def initialize(app: SpakkyApplication) -> None:
    """Register OpenFGA check client and auth provider bindings."""
    app.add(OpenFgaConfig)
    app.add(OpenFgaSdkCheckClient)
    app.add(OpenFgaAuthProvider)
    app.container.bind_to_type(IOpenFgaCheckClient, OpenFgaSdkCheckClient)
    app.container.bind_to_type(IRelationChecker, OpenFgaAuthProvider)
    app.container.bind_to_type(IAuthorizationPolicyEvaluator, OpenFgaAuthProvider)

Auth Provider

OpenFGA-backed auth provider for relationship authorization.

OpenFgaAuthProvider(client, config)

Bases: IRelationChecker, IAuthorizationPolicyEvaluator

OpenFGA check-only provider for ReBAC authorization decisions.

Source code in plugins/spakky-openfga/src/spakky/plugins/openfga/provider.py
def __init__(
    self,
    client: IOpenFgaCheckClient,
    config: OpenFgaConfig,
) -> None:
    self._client = client
    self._config = config

check_relation(request)

Check whether the subject has a relation to a resource.

Source code in plugins/spakky-openfga/src/spakky/plugins/openfga/provider.py
@override
def check_relation(self, request: RelationCheckRequest) -> AuthorizationDecision:
    """Check whether the subject has a relation to a resource."""
    return self._check(
        auth_context_subject_id=request.auth_context.subject.id,
        relation=request.relation,
        resource=request.resource,
        tenant=self._effective_tenant(request.tenant, request.auth_context.tenant),
    )

evaluate_policy(request)

Map resource/action policy evaluation to an OpenFGA relation check.

Source code in plugins/spakky-openfga/src/spakky/plugins/openfga/provider.py
@override
def evaluate_policy(self, request: AuthorizationRequest) -> AuthorizationDecision:
    """Map resource/action policy evaluation to an OpenFGA relation check."""
    return self._check(
        auth_context_subject_id=request.auth_context.subject.id,
        relation=request.action,
        resource=request.resource,
        tenant=self._effective_tenant(request.tenant, request.auth_context.tenant),
    )

openfga_auth_provider_contribution()

Return the auth capabilities contributed by spakky-openfga.

Source code in plugins/spakky-openfga/src/spakky/plugins/openfga/provider.py
@Pod(name="spakky_openfga_auth_provider_contribution")
def openfga_auth_provider_contribution() -> AuthProviderContribution:
    """Return the auth capabilities contributed by spakky-openfga."""
    return AuthProviderContribution(
        provider_id=OPENFGA_AUTH_PROVIDER_ID,
        capabilities=frozenset(
            {
                AuthCapability.POLICY_EVALUATION,
                AuthCapability.RELATION_CHECK,
            }
        ),
    )

Client / Config

OpenFGA check client boundary and SDK adapter.

OpenFgaCheckRequest(*, user, relation, object) dataclass

Provider-local tuple check request mapped from Spakky auth refs.

user instance-attribute

OpenFGA user string.

relation instance-attribute

OpenFGA relation string.

object instance-attribute

OpenFGA object string.

OpenFgaCheckResult(*, allowed) dataclass

Provider-local check result.

allowed instance-attribute

Whether OpenFGA allowed the tuple check.

IOpenFgaCheckClient

Bases: ABC

Boundary used by the auth provider to execute OpenFGA checks.

check(request) abstractmethod

Execute an OpenFGA check request.

Source code in plugins/spakky-openfga/src/spakky/plugins/openfga/client.py
@abstractmethod
def check(self, request: OpenFgaCheckRequest) -> OpenFgaCheckResult:
    """Execute an OpenFGA check request."""
    ...

OpenFgaSdkCheckClient(config)

Bases: IOpenFgaCheckClient

Synchronous OpenFGA SDK-backed check client.

Source code in plugins/spakky-openfga/src/spakky/plugins/openfga/client.py
def __init__(self, config: OpenFgaConfig) -> None:
    self._config = config

check(request)

Execute an OpenFGA check request with the official SDK.

Source code in plugins/spakky-openfga/src/spakky/plugins/openfga/client.py
@override
def check(self, request: OpenFgaCheckRequest) -> OpenFgaCheckResult:
    """Execute an OpenFGA check request with the official SDK."""
    try:
        with OpenFgaClient(self._client_configuration()) as client:
            response = client.check(
                ClientCheckRequest(
                    user=request.user,
                    relation=request.relation,
                    object=request.object,
                )
            )
    except (ApiException, FgaValidationException) as e:
        raise OpenFgaProviderUnavailableError from e
    return OpenFgaCheckResult(allowed=response.allowed is True)

Configuration for OpenFGA relationship checks.

OpenFgaConfig()

Bases: BaseSettings

Runtime config for OpenFGA check-only authorization.

Source code in plugins/spakky-openfga/src/spakky/plugins/openfga/config.py
def __init__(self) -> None:
    super().__init__()

api_url = DEFAULT_OPENFGA_API_URL class-attribute instance-attribute

OpenFGA API URL.

store_id = '' class-attribute instance-attribute

OpenFGA store id used for check requests.

authorization_model_id = None class-attribute instance-attribute

Optional authorization model id for check requests.

principal_type = DEFAULT_OPENFGA_USER_TYPE class-attribute instance-attribute

OpenFGA object type prepended to principal ids without a type prefix.

tenant_separator = DEFAULT_OPENFGA_TENANT_SEPARATOR class-attribute instance-attribute

Separator used to embed tenant refs into checked object ids.

include_tenant_in_object = True class-attribute instance-attribute

Whether tenant refs are prefixed into OpenFGA object strings.

relation_check_available = True class-attribute instance-attribute

Whether OpenFGA relationship checking is available at runtime.

에러

Error classes for the spakky-openfga plugin.

AbstractOpenFgaError

Bases: AbstractSpakkyFrameworkError, ABC

Base class for OpenFGA provider errors.

OpenFgaProviderUnavailableError

Bases: AbstractOpenFgaError

Raised when the OpenFGA check provider cannot be reached or used.

OpenFgaReferenceMappingError

Bases: AbstractOpenFgaError

Raised when canonical auth refs cannot be mapped to OpenFGA refs.

추가 모듈

Constants for the spakky-openfga plugin.

OPENFGA_AUTH_PROVIDER_ID = 'provider:spakky-openfga' module-attribute

Stable auth provider id advertised by spakky-openfga.

DEFAULT_OPENFGA_API_URL = 'http://localhost:8080' module-attribute

Default OpenFGA API URL for local development.

DEFAULT_OPENFGA_USER_TYPE = 'user' module-attribute

Default OpenFGA object type used for AuthContext principals.

DEFAULT_OPENFGA_TENANT_SEPARATOR = '/' module-attribute

Separator used when tenant refs are embedded into OpenFGA object ids.

SPAKKY_OPENFGA_CONFIG_ENV_PREFIX = 'SPAKKY_OPENFGA_' module-attribute

Environment variable prefix for OpenFGA provider settings.

Auth feature contribution for the OpenFGA provider.

initialize(app)

Register OpenFGA auth capability metadata.

Source code in plugins/spakky-openfga/src/spakky/plugins/openfga/contributions/auth.py
7
8
9
def initialize(app: SpakkyApplication) -> None:
    """Register OpenFGA auth capability metadata."""
    app.add(openfga_auth_provider_contribution)