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 ENTITIES_SERVICE_ACCESS_TOKEN env var #110

Merged
merged 5 commits into from
Apr 9, 2024
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
17 changes: 15 additions & 2 deletions entities_service/cli/_utils/generics.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from httpx_auth import (
AuthenticationFailed,
GrantNotProvided,
HeaderApiKey,
InvalidGrantRequest,
InvalidToken,
JsonTokenFileCache,
Expand All @@ -36,6 +37,7 @@
from rich.console import Console

from entities_service.models.auth import OpenIDConfiguration
from entities_service.service.config import CONFIG

if TYPE_CHECKING: # pragma: no cover
from typing import Any, TextIO
Expand Down Expand Up @@ -107,6 +109,17 @@ def pretty_compare_dicts(
)


def initialize_access_token() -> HeaderApiKey | None:
"""Create an API key header."""
if CONFIG.access_token is None:
return None

return HeaderApiKey(
api_key=f"Bearer {CONFIG.access_token.get_secret_value()}",
header_name="Authorization",
)


def initialize_oauth2(
openid_config_url: str | None = None,
) -> OAuth2AuthorizationCodePKCE:
Expand Down Expand Up @@ -161,5 +174,5 @@ def initialize_oauth2(
)


# OAuth2 authorization code flow
oauth = initialize_oauth2()
# Access Token and OAuth2 authorization code flow
oauth = initialize_access_token() or initialize_oauth2()
46 changes: 45 additions & 1 deletion entities_service/models/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from __future__ import annotations

from enum import IntEnum
from typing import Annotated

from pydantic import (
Expand Down Expand Up @@ -147,7 +148,7 @@ class OpenIDConfiguration(BaseModel):
] = None


class GitLabUserInfo(BaseModel):
class GitLabOpenIDUserInfo(BaseModel):
"""OpenID userinfo response from GitLab.

This is defined in the OpenID Connect specification.
Expand Down Expand Up @@ -222,3 +223,46 @@ class GitLabUserInfo(BaseModel):
),
),
] = []


class GitLabUser(BaseModel):
"""GitLab user response.

This is defined in the GitLab API documentation.
Reference: https://docs.gitlab.com/ee/api/users.html#single-user
"""

id: Annotated[int, Field(description="User ID.")]
name: Annotated[str, Field(description="Name of the user.")]
username: Annotated[str, Field(description="Username of the user.")]
state: Annotated[str, Field(description="State of the user.")]
locked: Annotated[bool, Field(description="Whether the user is locked.")]
bot: Annotated[bool, Field(description="Whether the user is a bot.")]


class GitLabRole(IntEnum):
"""Enumeration of GitLab roles."""

NO_ACCESS = 0
MINIMAL_ACCESS = 5
GUEST = 10
REPORTER = 20
DEVELOPER = 30
MAINTAINER = 40
OWNER = 50


class GitLabGroupProjectMember(BaseModel):
"""GitLab group or project member response.

This is defined in the GitLab API documentation.
Reference: https://docs.gitlab.com/ee/api/members.html#get-a-member-of-a-group-or-project
"""

id: Annotated[int, Field(description="Member ID.")]
username: Annotated[str, Field(description="Username of the member.")]
name: Annotated[str, Field(description="Name of the member.")]
state: Annotated[str, Field(description="State of the member.")]
access_level: Annotated[
GitLabRole, Field(description="Access level of the member.")
]
3 changes: 1 addition & 2 deletions entities_service/service/backend/mongodb.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ def get_client(
LOGGER.debug("Using cached MongoDB client for %r.", auth_level)
return MONGO_CLIENTS[auth_level]

LOGGER.debug("Creating new MongoDB client for %r.", username)
LOGGER.debug("Creating new MongoDB client for %r.", username or "X.509 certificate")

# Ensure all required settings are set
if auth_level == "read":
Expand Down Expand Up @@ -342,7 +342,6 @@ def create(
) -> list[dict[str, Any]] | dict[str, Any] | None:
"""Create one or more entities in the MongoDB."""
LOGGER.info("Creating entities: %s", entities)
LOGGER.info("The creator's user name: %s", self._settings.mongo_username)

entities = [self._prepare_entity(entity) for entity in entities]

Expand Down
18 changes: 18 additions & 0 deletions entities_service/service/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from __future__ import annotations

from enum import Enum
from pathlib import Path
from typing import Annotated, Any

Expand All @@ -17,6 +18,12 @@
"""Support MongoDB schemes with hidden port (no default port)."""


class OAuth2Provider(Enum):
"""Enumeration of supported OAuth2 providers."""

GITLAB = "gitlab"


class ServiceSettings(BaseSettings):
"""Service app configuration."""

Expand Down Expand Up @@ -47,9 +54,20 @@ class ServiceSettings(BaseSettings):

# Security
oauth2_provider: Annotated[
OAuth2Provider,
Field(
description="OAuth2 provider. (Currently only GitLab is supported.)",
),
] = OAuth2Provider.GITLAB

oauth2_provider_base_url: Annotated[
AnyHttpUrl, Field(description="OAuth2 provider base URL.")
] = AnyHttpUrl("https://gitlab.sintef.no")

access_token: Annotated[
SecretStr | None, Field(description="Access token for the OAuth2 provider.")
] = None

roles_group: Annotated[str, Field(description="GitLab group for roles.")] = (
"team4.0-authentication/entities-service"
)
Expand Down
Loading
Loading