Skip to content

profiles

profiles

Allowlist profile loading and composition.

Finds, reads, and merges .txt allowlist profiles from user and bundled directories. User profiles override bundled ones with the same name, so site-specific customisation works without forking.

Profiles are unified +/- policy files; a loaded profile yields its admitted (+) targets. The bundled profiles ship under resources/examples as samples a caller names explicitly; the curated egress sets belong to terok, and the OS-package and provider hosts to terok-executor.

ProfileLoader(*, user_dir, bundled_dir=None)

Loads and composes .txt allowlist profiles.

Searches user profiles first (overriding bundled), then falls back to the bundled profiles shipped with the package.

Create a profile loader.

Parameters:

Name Type Description Default
user_dir Path

User profiles directory (overrides bundled).

required
bundled_dir Path | None

Bundled profiles directory (auto-detected if None).

None
Source code in src/terok_shield/profiles.py
def __init__(
    self,
    *,
    user_dir: Path,
    bundled_dir: Path | None = None,
) -> None:
    """Create a profile loader.

    Args:
        user_dir: User profiles directory (overrides bundled).
        bundled_dir: Bundled profiles directory (auto-detected if None).
    """
    self._user_dir = user_dir
    self._bundled_dir = bundled_dir or _bundled_dir()

load_profile(name)

Load a profile by name and return its admitted (+) targets.

User profiles take precedence over bundled profiles.

Raises:

Type Description
UnknownProfileError

If no profile carries name; the message names the available profiles.

Source code in src/terok_shield/profiles.py
def load_profile(self, name: str) -> list[str]:
    """Load a profile by name and return its admitted (``+``) targets.

    User profiles take precedence over bundled profiles.

    Raises:
        UnknownProfileError: If no profile carries *name*; the message
            names the available profiles.
    """
    profiles = self._profile_paths()
    path = profiles.get(name)
    if path is None:
        available = ", ".join(sorted(profiles)) or "none"
        raise UnknownProfileError(f"Unknown profile {name!r}; available profiles: {available}")
    return [e.target for e in parse_policy(path.read_text()) if e.action == "+"]

compose_profiles(names)

Load and merge multiple profiles, deduplicating entries.

Preserves insertion order (first occurrence wins).

Raises:

Type Description
UnknownProfileError

If any name carries no profile.

Source code in src/terok_shield/profiles.py
def compose_profiles(self, names: list[str]) -> list[str]:
    """Load and merge multiple profiles, deduplicating entries.

    Preserves insertion order (first occurrence wins).

    Raises:
        UnknownProfileError: If any name carries no profile.
    """
    seen: set[str] = set()
    result: list[str] = []
    for name in names:
        for entry in self.load_profile(name):
            if entry not in seen:
                seen.add(entry)
                result.append(entry)
    return result

list_profiles()

List available profile names (bundled + user, deduplicated).

Source code in src/terok_shield/profiles.py
def list_profiles(self) -> list[str]:
    """List available profile names (bundled + user, deduplicated)."""
    return sorted(self._profile_paths())

UnknownProfileError

Bases: ValueError

A requested name matches no profile, user or bundled.