Skip to content

Secrets Managers

zenml.secrets_managers special

Initialization for the ZenML secrets manager module.

base_secrets_manager

Base class for ZenML secrets managers.

BaseSecretsManager (StackComponent, ABC)

Base class for all ZenML secrets managers.

Attributes:

Name Type Description
scope

The Secrets Manager scope determines how secrets are visible and shared across different Secrets Manager instances:

  • global: secrets are shared across all Secrets Manager instances that connect to the same backend and have a global scope.
  • component: secrets are not shared outside this Secrets Manager instance.
  • namespace: secrets are shared only by Secrets Manager instances that connect to the same backend and have the same namespace value configured.
  • none: only used to preserve backwards compatibility with old Secrets Manager instances that do not yet understand the concept of secrets scoping. Will be deprecated and removed in future versions.
namespace

Optional namespace to use with a namespace scoped Secrets Manager.

Source code in zenml/secrets_managers/base_secrets_manager.py
class BaseSecretsManager(StackComponent, ABC):
    """Base class for all ZenML secrets managers.

    Attributes:
        scope: The Secrets Manager scope determines how secrets are visible and
            shared across different Secrets Manager instances:

            * global: secrets are shared across all Secrets Manager instances
            that connect to the same backend and have a global scope.
            * component: secrets are not shared outside this Secrets Manager
            instance.
            * namespace: secrets are shared only by Secrets Manager instances
            that connect to the same backend *and* have the same `namespace`
            value configured.
            * none: only used to preserve backwards compatibility with
            old Secrets Manager instances that do not yet understand the
            concept of secrets scoping. Will be deprecated and removed in
            future versions.
        namespace: Optional namespace to use with a `namespace` scoped Secrets
            Manager.
    """

    @property
    def config(self) -> BaseSecretsManagerConfig:
        """Returns the `BaseSecretsManagerConfig` config.

        Returns:
            The configuration.
        """
        return cast(BaseSecretsManagerConfig, self._config)

    def _get_scope_path(self) -> List[str]:
        """Get the secret path for the current scope.

        This utility method can be used with Secrets Managers that can map
        the concept of a scope to a hierarchical path.

        Returns:
            the secret scope path
        """
        if self.config.scope == SecretsManagerScope.NONE:
            return []

        path = [ZENML_SCOPE_PATH_PREFIX, self.config.scope]
        if self.config.scope == SecretsManagerScope.COMPONENT:
            path.append(str(self.id))
        elif (
            self.config.scope == SecretsManagerScope.NAMESPACE
            and self.config.namespace
        ):
            path.append(self.config.namespace)

        return path

    def _get_scoped_secret_path(self, secret_name: str) -> List[str]:
        """Convert a ZenML secret name into a scoped secret path.

        This utility method can be used with Secrets Managers that can map
        the concept of a scope to a hierarchical path.

        Args:
            secret_name: the name of the secret

        Returns:
            The scoped secret path
        """
        path = self._get_scope_path()
        path.append(secret_name)
        return path

    def _get_secret_name_from_path(
        self, secret_path: List[str]
    ) -> Optional[str]:
        """Extract the name of a ZenML secret from a scoped secret path.

        This utility method can be used with Secrets Managers that can map
        the concept of a scope to a hierarchical path.

        Args:
            secret_path: the full scoped secret path including the secret name

        Returns:
            The ZenML secret name or None, if the input secret path does not
            belong to the current scope.
        """
        if not len(secret_path):
            return None
        secret_name = secret_path[-1]
        secret_path = secret_path[:-1]
        if not secret_name or secret_path != self._get_scope_path():
            # secret name is not in the current scope
            return None

        return secret_name

    def _get_scoped_secret_name_prefix(
        self,
        separator: str = ZENML_DEFAULT_SECRET_SCOPE_PATH_SEPARATOR,
    ) -> str:
        """Convert the ZenML secret scope into a scoped secret name prefix.

        This utility method can be used with Secrets Managers that can map
        the concept of a scope to a hierarchical path to compose a scoped
        secret name prefix from the scope path.

        Args:
            separator: the path separator to use when constructing a scoped
                secret prefix from a scope path

        Returns:
            The scoped secret name prefix
        """
        return separator.join(self._get_scope_path()) + separator

    def _get_scoped_secret_name(
        self,
        name: str,
        separator: str = ZENML_DEFAULT_SECRET_SCOPE_PATH_SEPARATOR,
    ) -> str:
        """Convert a ZenML secret name into a scoped secret name.

        This utility method can be used with Secrets Managers that can map
        the concept of a scope to a hierarchical path to compose a scoped
        secret name that includes the scope path from a ZenML secret name.

        Args:
            name: the name of the secret
            separator: the path separator to use when constructing a scoped
                secret name from a scope path

        Returns:
            The scoped secret name
        """
        return separator.join(self._get_scoped_secret_path(name))

    def _get_unscoped_secret_name(
        self,
        name: str,
        separator: str = ZENML_DEFAULT_SECRET_SCOPE_PATH_SEPARATOR,
    ) -> Optional[str]:
        """Extract the name of a ZenML secret from a scoped secret name.

        This utility method can be used with Secrets Managers that can map
        the concept of a scope to a hierarchical path to extract the original
        ZenML secret name from a scoped secret name that includes the scope
        path.

        Args:
            name: the name of the scoped secret
            separator: the path separator to use when constructing a scoped
                secret name from a scope path

        Returns:
            The ZenML secret name or None, if the input secret name does not
            belong to the current scope.
        """
        return self._get_secret_name_from_path(name.split(separator))

    def _get_secret_scope_metadata(
        self, secret_name: Optional[str] = None
    ) -> Dict[str, str]:
        """Get a dictionary with metadata uniquely identifying one or more scoped secrets.

        This utility method can be used with Secrets Managers that can
        associate metadata (e.g. tags, labels) with a secret. The scope related
        metadata can be used as a filter criteria when running queries against
        the backend to retrieve all the secrets within the current scope or
        to retrieve a named secret within the current scope (if the
        `secret_name` is supplied).

        Args:
            secret_name: Optional secret name for which to get the scope
                metadata.

        Returns:
            Dictionary with scope metadata information uniquely identifying the
            secret.
        """
        if self.config.scope == SecretsManagerScope.NONE:
            # unscoped secrets do not have tags, for backwards compatibility
            # purposes
            return {}

        metadata = {
            "zenml_scope": self.config.scope.value,
        }
        if secret_name:
            metadata[ZENML_SECRET_NAME_LABEL] = secret_name
        if (
            self.config.scope == SecretsManagerScope.NAMESPACE
            and self.config.namespace
        ):
            metadata["zenml_namespace"] = self.config.namespace
        if self.config.scope == SecretsManagerScope.COMPONENT:
            metadata["zenml_component_uuid"] = str(self.id)

        return metadata

    def _get_secret_metadata(
        self, secret: "BaseSecretSchema"
    ) -> Dict[str, str]:
        """Get a dictionary with metadata describing a secret.

        This is utility method can be used with Secrets Managers that can
        associate metadata (e.g. tags, labels) with a secret. The metadata
        can be used to relay more information about the secret in the Secrets
        Manager backend. Part of the metadata can also be used as a filter
        criteria when running queries against the backend to retrieve all the
        secrets within the current scope or to retrieve a named secret (see
        `_get_secret_scope_metadata`).

        Args:
            secret: The secret for which to get the metadata.

        Returns:
            Dictionary with metadata information describing the secret.
        """
        if self.config.scope == SecretsManagerScope.NONE:
            # unscoped secrets do not have tags, for backwards compatibility
            # purposes
            return {}

        scope_metadata = self._get_secret_scope_metadata(secret.name)
        # include additional metadata not necessarily related to the secret
        # scope
        scope_metadata.update(
            {
                "zenml_component_name": self.name,
                "zenml_component_uuid": str(self.id),
                "zenml_secret_schema": secret.TYPE,
            }
        )

        return scope_metadata

    @abstractmethod
    def register_secret(self, secret: "BaseSecretSchema") -> None:
        """Registers a new secret.

        The implementation should throw a `SecretExistsError` exception if the
        secret already exists.

        Args:
            secret: The secret to register.
        """

    @abstractmethod
    def get_secret(self, secret_name: str) -> "BaseSecretSchema":
        """Gets the value of a secret.

        The implementation should throw a `KeyError` exception if the
        secret doesn't exist.

        Args:
            secret_name: The name of the secret to get.
        """

    @abstractmethod
    def get_all_secret_keys(self) -> List[str]:
        """Get all secret keys."""

    @abstractmethod
    def update_secret(self, secret: "BaseSecretSchema") -> None:
        """Update an existing secret.

        The implementation should throw a `KeyError` exception if the
        secret doesn't exist.

        Args:
            secret: The secret to update.
        """

    @abstractmethod
    def delete_secret(self, secret_name: str) -> None:
        """Delete an existing secret.

        The implementation should throw a `KeyError` exception if the
        secret doesn't exist.

        Args:
            secret_name: The name of the secret to delete.
        """

    @abstractmethod
    def delete_all_secrets(self) -> None:
        """Delete all existing secrets."""
config: BaseSecretsManagerConfig property readonly

Returns the BaseSecretsManagerConfig config.

Returns:

Type Description
BaseSecretsManagerConfig

The configuration.

delete_all_secrets(self)

Delete all existing secrets.

Source code in zenml/secrets_managers/base_secrets_manager.py
@abstractmethod
def delete_all_secrets(self) -> None:
    """Delete all existing secrets."""
delete_secret(self, secret_name)

Delete an existing secret.

The implementation should throw a KeyError exception if the secret doesn't exist.

Parameters:

Name Type Description Default
secret_name str

The name of the secret to delete.

required
Source code in zenml/secrets_managers/base_secrets_manager.py
@abstractmethod
def delete_secret(self, secret_name: str) -> None:
    """Delete an existing secret.

    The implementation should throw a `KeyError` exception if the
    secret doesn't exist.

    Args:
        secret_name: The name of the secret to delete.
    """
get_all_secret_keys(self)

Get all secret keys.

Source code in zenml/secrets_managers/base_secrets_manager.py
@abstractmethod
def get_all_secret_keys(self) -> List[str]:
    """Get all secret keys."""
get_secret(self, secret_name)

Gets the value of a secret.

The implementation should throw a KeyError exception if the secret doesn't exist.

Parameters:

Name Type Description Default
secret_name str

The name of the secret to get.

required
Source code in zenml/secrets_managers/base_secrets_manager.py
@abstractmethod
def get_secret(self, secret_name: str) -> "BaseSecretSchema":
    """Gets the value of a secret.

    The implementation should throw a `KeyError` exception if the
    secret doesn't exist.

    Args:
        secret_name: The name of the secret to get.
    """
register_secret(self, secret)

Registers a new secret.

The implementation should throw a SecretExistsError exception if the secret already exists.

Parameters:

Name Type Description Default
secret BaseSecretSchema

The secret to register.

required
Source code in zenml/secrets_managers/base_secrets_manager.py
@abstractmethod
def register_secret(self, secret: "BaseSecretSchema") -> None:
    """Registers a new secret.

    The implementation should throw a `SecretExistsError` exception if the
    secret already exists.

    Args:
        secret: The secret to register.
    """
update_secret(self, secret)

Update an existing secret.

The implementation should throw a KeyError exception if the secret doesn't exist.

Parameters:

Name Type Description Default
secret BaseSecretSchema

The secret to update.

required
Source code in zenml/secrets_managers/base_secrets_manager.py
@abstractmethod
def update_secret(self, secret: "BaseSecretSchema") -> None:
    """Update an existing secret.

    The implementation should throw a `KeyError` exception if the
    secret doesn't exist.

    Args:
        secret: The secret to update.
    """

BaseSecretsManagerConfig (StackComponentConfig) pydantic-model

Base configuration for secrets managers.

Attributes:

Name Type Description
scope SecretsManagerScope

The scope of the secrets manager.

namespace Optional[str]

The namespace of the secrets manager.

Source code in zenml/secrets_managers/base_secrets_manager.py
class BaseSecretsManagerConfig(StackComponentConfig):
    """Base configuration for secrets managers.

    Attributes:
        scope: The scope of the secrets manager.
        namespace: The namespace of the secrets manager.
    """

    SUPPORTS_SCOPING: ClassVar[bool] = False
    scope: SecretsManagerScope = SecretsManagerScope.COMPONENT
    namespace: Optional[str] = None

    def __init__(self, **kwargs: Any) -> None:
        """Ensures that no attributes are specified as a secret reference.

        Args:
            **kwargs: Arguments to initialize this secrets manager.

        Raises:
            ValueError: If any of the secrets manager attributes are specified
                as a secret reference.
        """
        for key, value in kwargs.items():
            if secret_utils.is_secret_reference(value):
                raise ValueError(
                    "Using secret references to specify attributes on a "
                    "secrets manager is not allowed. Please specify the "
                    f"real value for the attribute {key}."
                )

        super().__init__(**kwargs)

    @root_validator(pre=True)
    def scope_initializer(cls, values: Dict[str, Any]) -> Dict[str, Any]:
        """Pydantic root_validator for the scope.

        This root validator is used for backwards compatibility purposes. It
        ensures that existing Secrets Managers continue to use no scope for
        secrets while new instances default to using the component scope.

        Args:
            values: Values passed to the object constructor

        Returns:
            Values passed to the object constructor

        Raises:
            ValueError: If the scope value is not valid.
        """
        scope = values.get("scope")

        if scope:
            # fail if the user tries to explicitly use a scope with a
            # Secrets Manager that doesn't support scoping
            if scope != SecretsManagerScope.NONE and not cls.SUPPORTS_SCOPING:
                raise ValueError(
                    "This Secrets Manager does not support "
                    "scoping. You can only use a `none` scope value."
                )
        elif not cls.SUPPORTS_SCOPING:
            # disable scoping by default for Secrets Managers that don't
            # support scoping
            values["scope"] = SecretsManagerScope.NONE

        # warn if the user tries to explicitly disable scoping for a
        # Secrets Manager that does support scoping
        if scope == SecretsManagerScope.NONE and cls.SUPPORTS_SCOPING:
            logger.warning(
                "Unscoped support for this Secrets "
                "Manager is deprecated and will be removed in a future "
                "release. You should use the `global` scope instead."
            )

        return values

    @root_validator
    def namespace_validator(cls, values: Dict[str, Any]) -> Dict[str, Any]:
        """Pydantic root validator for the namespace.

        For a namespace scoped Secret Manager, the namespace is required.

        Args:
            values: Values passed to the object constructor

        Returns:
            Values passed to the object constructor

        Raises:
            ValueError: If a namespace is not configured for a namespace scoped
                Secret Manager.
        """
        scope = cast(SecretsManagerScope, values.get("scope"))
        if scope == SecretsManagerScope.NAMESPACE and not values.get(
            "namespace"
        ):
            raise ValueError(
                "A `namespace` value is required for a namespace scoped "
                "Secrets Manager."
            )
        cls._validate_scope(scope, values.get("namespace"))
        return values

    @classmethod
    def _validate_scope(
        cls,
        scope: SecretsManagerScope,
        namespace: Optional[str],
    ) -> None:
        """Validate the scope and namespace value.

        Subclasses should override this method to implement their own scope
        and namespace validation logic (e.g. raise an exception if a scope is
        not supported or if a namespace has an invalid value).

        Args:
            scope: Scope value.
            namespace: Namespace value.
        """
        ...
__init__(self, **kwargs) special

Ensures that no attributes are specified as a secret reference.

Parameters:

Name Type Description Default
**kwargs Any

Arguments to initialize this secrets manager.

{}

Exceptions:

Type Description
ValueError

If any of the secrets manager attributes are specified as a secret reference.

Source code in zenml/secrets_managers/base_secrets_manager.py
def __init__(self, **kwargs: Any) -> None:
    """Ensures that no attributes are specified as a secret reference.

    Args:
        **kwargs: Arguments to initialize this secrets manager.

    Raises:
        ValueError: If any of the secrets manager attributes are specified
            as a secret reference.
    """
    for key, value in kwargs.items():
        if secret_utils.is_secret_reference(value):
            raise ValueError(
                "Using secret references to specify attributes on a "
                "secrets manager is not allowed. Please specify the "
                f"real value for the attribute {key}."
            )

    super().__init__(**kwargs)
namespace_validator(values) classmethod

Pydantic root validator for the namespace.

For a namespace scoped Secret Manager, the namespace is required.

Parameters:

Name Type Description Default
values Dict[str, Any]

Values passed to the object constructor

required

Returns:

Type Description
Dict[str, Any]

Values passed to the object constructor

Exceptions:

Type Description
ValueError

If a namespace is not configured for a namespace scoped Secret Manager.

Source code in zenml/secrets_managers/base_secrets_manager.py
@root_validator
def namespace_validator(cls, values: Dict[str, Any]) -> Dict[str, Any]:
    """Pydantic root validator for the namespace.

    For a namespace scoped Secret Manager, the namespace is required.

    Args:
        values: Values passed to the object constructor

    Returns:
        Values passed to the object constructor

    Raises:
        ValueError: If a namespace is not configured for a namespace scoped
            Secret Manager.
    """
    scope = cast(SecretsManagerScope, values.get("scope"))
    if scope == SecretsManagerScope.NAMESPACE and not values.get(
        "namespace"
    ):
        raise ValueError(
            "A `namespace` value is required for a namespace scoped "
            "Secrets Manager."
        )
    cls._validate_scope(scope, values.get("namespace"))
    return values
scope_initializer(values) classmethod

Pydantic root_validator for the scope.

This root validator is used for backwards compatibility purposes. It ensures that existing Secrets Managers continue to use no scope for secrets while new instances default to using the component scope.

Parameters:

Name Type Description Default
values Dict[str, Any]

Values passed to the object constructor

required

Returns:

Type Description
Dict[str, Any]

Values passed to the object constructor

Exceptions:

Type Description
ValueError

If the scope value is not valid.

Source code in zenml/secrets_managers/base_secrets_manager.py
@root_validator(pre=True)
def scope_initializer(cls, values: Dict[str, Any]) -> Dict[str, Any]:
    """Pydantic root_validator for the scope.

    This root validator is used for backwards compatibility purposes. It
    ensures that existing Secrets Managers continue to use no scope for
    secrets while new instances default to using the component scope.

    Args:
        values: Values passed to the object constructor

    Returns:
        Values passed to the object constructor

    Raises:
        ValueError: If the scope value is not valid.
    """
    scope = values.get("scope")

    if scope:
        # fail if the user tries to explicitly use a scope with a
        # Secrets Manager that doesn't support scoping
        if scope != SecretsManagerScope.NONE and not cls.SUPPORTS_SCOPING:
            raise ValueError(
                "This Secrets Manager does not support "
                "scoping. You can only use a `none` scope value."
            )
    elif not cls.SUPPORTS_SCOPING:
        # disable scoping by default for Secrets Managers that don't
        # support scoping
        values["scope"] = SecretsManagerScope.NONE

    # warn if the user tries to explicitly disable scoping for a
    # Secrets Manager that does support scoping
    if scope == SecretsManagerScope.NONE and cls.SUPPORTS_SCOPING:
        logger.warning(
            "Unscoped support for this Secrets "
            "Manager is deprecated and will be removed in a future "
            "release. You should use the `global` scope instead."
        )

    return values

BaseSecretsManagerFlavor (Flavor)

Class for the BaseSecretsManagerFlavor.

Source code in zenml/secrets_managers/base_secrets_manager.py
class BaseSecretsManagerFlavor(Flavor):
    """Class for the `BaseSecretsManagerFlavor`."""

    @property
    def type(self) -> StackComponentType:
        """Returns the flavor type.

        Returns:
            The flavor type.
        """
        return StackComponentType.SECRETS_MANAGER

    @property
    def config_class(self) -> Type[BaseSecretsManagerConfig]:
        """Returns the config class.

        Returns:
            The config class.
        """
        return BaseSecretsManagerConfig

    @property
    @abstractmethod
    def implementation_class(self) -> Type["BaseSecretsManager"]:
        """Implementation class for this flavor.

        Returns:
            The implementation class.
        """
config_class: Type[zenml.secrets_managers.base_secrets_manager.BaseSecretsManagerConfig] property readonly

Returns the config class.

Returns:

Type Description
Type[zenml.secrets_managers.base_secrets_manager.BaseSecretsManagerConfig]

The config class.

implementation_class: Type[BaseSecretsManager] property readonly

Implementation class for this flavor.

Returns:

Type Description
Type[BaseSecretsManager]

The implementation class.

type: StackComponentType property readonly

Returns the flavor type.

Returns:

Type Description
StackComponentType

The flavor type.

SecretsManagerScope (StrEnum)

Secrets Manager scope enum.

Source code in zenml/secrets_managers/base_secrets_manager.py
class SecretsManagerScope(StrEnum):
    """Secrets Manager scope enum."""

    NONE = "none"
    GLOBAL = "global"
    COMPONENT = "component"
    NAMESPACE = "namespace"

local special

Initialization of the ZenML local secrets manager.

local_secrets_manager

Implementation of the ZenML local secrets manager.

LocalSecretsManager (BaseSecretsManager)

Class for ZenML local file-based secret manager.

Source code in zenml/secrets_managers/local/local_secrets_manager.py
class LocalSecretsManager(BaseSecretsManager):
    """Class for ZenML local file-based secret manager."""

    @property
    def config(self) -> LocalSecretsManagerConfig:
        """Returns the `LocalSecretsManagerConfig` config.

        Returns:
            The configuration.
        """
        return cast(LocalSecretsManagerConfig, self._config)

    @property
    def secrets_file(self) -> str:
        """Gets the secrets file path.

        If the secrets file was not provided in the config by the user, this
        will return the default secrets file path based on the component ID.

        Returns:
            The secrets file path.
        """
        if self.config.secrets_file:
            return self.config.secrets_file
        return self.get_default_secret_store_path(self.id)

    @staticmethod
    def get_default_secret_store_path(id_: "UUID") -> str:
        """Get the path to the secret store.

        Args:
            id_: The ID of the secret store.

        Returns:
            The path to the secret store.
        """
        return os.path.join(
            GlobalConfiguration().local_stores_path,
            str(id_),
            LOCAL_SECRETS_FILENAME,
        )

    @property
    def local_path(self) -> str:
        """Path to the local directory where the secrets are stored.

        Returns:
            The path to the local directory where the secrets are stored.
        """
        return str(Path(self.secrets_file).parent)

    def _create_secrets_file__if_not_exists(self) -> None:
        """Makes sure the secrets yaml file exists."""
        create_file_if_not_exists(self.secrets_file)

    def _verify_secret_key_exists(self, secret_name: str) -> bool:
        """Checks if a secret key exists.

        Args:
            secret_name: The name of the secret key.

        Returns:
            True if the secret key exists, False otherwise.
        """
        self._create_secrets_file__if_not_exists()
        secrets_store_items = yaml_utils.read_yaml(self.secrets_file)
        try:
            return secret_name in secrets_store_items
        except TypeError:
            return False

    def _get_all_secrets(self) -> Dict[str, Dict[str, str]]:
        """Gets all secrets.

        Returns:
            A dictionary containing all secrets.
        """
        self._create_secrets_file__if_not_exists()
        return yaml_utils.read_yaml(self.secrets_file) or {}

    def register_secret(self, secret: "BaseSecretSchema") -> None:
        """Registers a new secret.

        Args:
            secret: The secret to register.

        Raises:
            SecretExistsError: If the secret already exists.
        """
        self._create_secrets_file__if_not_exists()

        if self._verify_secret_key_exists(secret_name=secret.name):
            raise SecretExistsError(f"Secret `{secret.name}` already exists.")
        encoded_secret = encode_secret(secret)

        secrets_store_items = self._get_all_secrets()
        secrets_store_items[secret.name] = encoded_secret
        yaml_utils.append_yaml(self.secrets_file, secrets_store_items)

    def get_secret(self, secret_name: str) -> "BaseSecretSchema":
        """Gets a specific secret.

        Args:
            secret_name: The name of the secret.

        Returns:
            The secret.

        Raises:
            KeyError: If the secret does not exist.
        """
        self._create_secrets_file__if_not_exists()

        secret_store_items = self._get_all_secrets()
        if not self._verify_secret_key_exists(secret_name=secret_name):
            raise KeyError(f"Secret `{secret_name}` does not exists.")
        secret_dict = secret_store_items[secret_name]

        decoded_secret_dict, zenml_schema_name = decode_secret_dict(
            secret_dict
        )
        decoded_secret_dict["name"] = secret_name

        secret_schema = SecretSchemaClassRegistry.get_class(
            secret_schema=zenml_schema_name
        )
        return secret_schema(**decoded_secret_dict)

    def get_all_secret_keys(self) -> List[str]:
        """Get all secret keys.

        Returns:
            A list of all secret keys.
        """
        self._create_secrets_file__if_not_exists()

        secrets_store_items = self._get_all_secrets()
        return list(secrets_store_items.keys())

    def update_secret(self, secret: "BaseSecretSchema") -> None:
        """Update an existing secret.

        Args:
            secret: The secret to update.

        Raises:
            KeyError: If the secret does not exist.
        """
        self._create_secrets_file__if_not_exists()

        if not self._verify_secret_key_exists(secret_name=secret.name):
            raise KeyError(f"Secret `{secret.name}` did not exist.")
        encoded_secret = encode_secret(secret)

        secrets_store_items = self._get_all_secrets()
        secrets_store_items[secret.name] = encoded_secret
        yaml_utils.append_yaml(self.secrets_file, secrets_store_items)

    def delete_secret(self, secret_name: str) -> None:
        """Delete an existing secret.

        Args:
            secret_name: The name of the secret to delete.

        Raises:
            KeyError: If the secret does not exist.
        """
        self._create_secrets_file__if_not_exists()

        if not self._verify_secret_key_exists(secret_name=secret_name):
            raise KeyError(f"Secret `{secret_name}` does not exists.")
        secrets_store_items = self._get_all_secrets()

        try:
            secrets_store_items.pop(secret_name)
            yaml_utils.write_yaml(self.secrets_file, secrets_store_items)
        except KeyError as e:
            raise KeyError(f"Secret {secret_name} does not exist.") from e

    def delete_all_secrets(self) -> None:
        """Delete all existing secrets."""
        self._create_secrets_file__if_not_exists()
        remove(self.secrets_file)
config: LocalSecretsManagerConfig property readonly

Returns the LocalSecretsManagerConfig config.

Returns:

Type Description
LocalSecretsManagerConfig

The configuration.

local_path: str property readonly

Path to the local directory where the secrets are stored.

Returns:

Type Description
str

The path to the local directory where the secrets are stored.

secrets_file: str property readonly

Gets the secrets file path.

If the secrets file was not provided in the config by the user, this will return the default secrets file path based on the component ID.

Returns:

Type Description
str

The secrets file path.

delete_all_secrets(self)

Delete all existing secrets.

Source code in zenml/secrets_managers/local/local_secrets_manager.py
def delete_all_secrets(self) -> None:
    """Delete all existing secrets."""
    self._create_secrets_file__if_not_exists()
    remove(self.secrets_file)
delete_secret(self, secret_name)

Delete an existing secret.

Parameters:

Name Type Description Default
secret_name str

The name of the secret to delete.

required

Exceptions:

Type Description
KeyError

If the secret does not exist.

Source code in zenml/secrets_managers/local/local_secrets_manager.py
def delete_secret(self, secret_name: str) -> None:
    """Delete an existing secret.

    Args:
        secret_name: The name of the secret to delete.

    Raises:
        KeyError: If the secret does not exist.
    """
    self._create_secrets_file__if_not_exists()

    if not self._verify_secret_key_exists(secret_name=secret_name):
        raise KeyError(f"Secret `{secret_name}` does not exists.")
    secrets_store_items = self._get_all_secrets()

    try:
        secrets_store_items.pop(secret_name)
        yaml_utils.write_yaml(self.secrets_file, secrets_store_items)
    except KeyError as e:
        raise KeyError(f"Secret {secret_name} does not exist.") from e
get_all_secret_keys(self)

Get all secret keys.

Returns:

Type Description
List[str]

A list of all secret keys.

Source code in zenml/secrets_managers/local/local_secrets_manager.py
def get_all_secret_keys(self) -> List[str]:
    """Get all secret keys.

    Returns:
        A list of all secret keys.
    """
    self._create_secrets_file__if_not_exists()

    secrets_store_items = self._get_all_secrets()
    return list(secrets_store_items.keys())
get_default_secret_store_path(id_) staticmethod

Get the path to the secret store.

Parameters:

Name Type Description Default
id_ UUID

The ID of the secret store.

required

Returns:

Type Description
str

The path to the secret store.

Source code in zenml/secrets_managers/local/local_secrets_manager.py
@staticmethod
def get_default_secret_store_path(id_: "UUID") -> str:
    """Get the path to the secret store.

    Args:
        id_: The ID of the secret store.

    Returns:
        The path to the secret store.
    """
    return os.path.join(
        GlobalConfiguration().local_stores_path,
        str(id_),
        LOCAL_SECRETS_FILENAME,
    )
get_secret(self, secret_name)

Gets a specific secret.

Parameters:

Name Type Description Default
secret_name str

The name of the secret.

required

Returns:

Type Description
BaseSecretSchema

The secret.

Exceptions:

Type Description
KeyError

If the secret does not exist.

Source code in zenml/secrets_managers/local/local_secrets_manager.py
def get_secret(self, secret_name: str) -> "BaseSecretSchema":
    """Gets a specific secret.

    Args:
        secret_name: The name of the secret.

    Returns:
        The secret.

    Raises:
        KeyError: If the secret does not exist.
    """
    self._create_secrets_file__if_not_exists()

    secret_store_items = self._get_all_secrets()
    if not self._verify_secret_key_exists(secret_name=secret_name):
        raise KeyError(f"Secret `{secret_name}` does not exists.")
    secret_dict = secret_store_items[secret_name]

    decoded_secret_dict, zenml_schema_name = decode_secret_dict(
        secret_dict
    )
    decoded_secret_dict["name"] = secret_name

    secret_schema = SecretSchemaClassRegistry.get_class(
        secret_schema=zenml_schema_name
    )
    return secret_schema(**decoded_secret_dict)
register_secret(self, secret)

Registers a new secret.

Parameters:

Name Type Description Default
secret BaseSecretSchema

The secret to register.

required

Exceptions:

Type Description
SecretExistsError

If the secret already exists.

Source code in zenml/secrets_managers/local/local_secrets_manager.py
def register_secret(self, secret: "BaseSecretSchema") -> None:
    """Registers a new secret.

    Args:
        secret: The secret to register.

    Raises:
        SecretExistsError: If the secret already exists.
    """
    self._create_secrets_file__if_not_exists()

    if self._verify_secret_key_exists(secret_name=secret.name):
        raise SecretExistsError(f"Secret `{secret.name}` already exists.")
    encoded_secret = encode_secret(secret)

    secrets_store_items = self._get_all_secrets()
    secrets_store_items[secret.name] = encoded_secret
    yaml_utils.append_yaml(self.secrets_file, secrets_store_items)
update_secret(self, secret)

Update an existing secret.

Parameters:

Name Type Description Default
secret BaseSecretSchema

The secret to update.

required

Exceptions:

Type Description
KeyError

If the secret does not exist.

Source code in zenml/secrets_managers/local/local_secrets_manager.py
def update_secret(self, secret: "BaseSecretSchema") -> None:
    """Update an existing secret.

    Args:
        secret: The secret to update.

    Raises:
        KeyError: If the secret does not exist.
    """
    self._create_secrets_file__if_not_exists()

    if not self._verify_secret_key_exists(secret_name=secret.name):
        raise KeyError(f"Secret `{secret.name}` did not exist.")
    encoded_secret = encode_secret(secret)

    secrets_store_items = self._get_all_secrets()
    secrets_store_items[secret.name] = encoded_secret
    yaml_utils.append_yaml(self.secrets_file, secrets_store_items)
LocalSecretsManagerConfig (BaseSecretsManagerConfig) pydantic-model

Configuration for the local secrets manager.

Attributes:

Name Type Description
secrets_file str

The path to the secrets file.

Source code in zenml/secrets_managers/local/local_secrets_manager.py
class LocalSecretsManagerConfig(BaseSecretsManagerConfig):
    """Configuration for the local secrets manager.

    Attributes:
        secrets_file: The path to the secrets file.
    """

    secrets_file: str = ""

    @property
    def is_local(self) -> bool:
        """Checks if this stack component is running locally.

        This designation is used to determine if the stack component can be
        shared with other users or if it is only usable on the local host.

        Returns:
            True if this config is for a local component, False otherwise.
        """
        return True
is_local: bool property readonly

Checks if this stack component is running locally.

This designation is used to determine if the stack component can be shared with other users or if it is only usable on the local host.

Returns:

Type Description
bool

True if this config is for a local component, False otherwise.

LocalSecretsManagerFlavor (BaseSecretsManagerFlavor)

Class for the LocalSecretsManagerFlavor.

Source code in zenml/secrets_managers/local/local_secrets_manager.py
class LocalSecretsManagerFlavor(BaseSecretsManagerFlavor):
    """Class for the `LocalSecretsManagerFlavor`."""

    @property
    def name(self) -> str:
        """Name of the flavor.

        Returns:
            The name of the flavor.
        """
        return "local"

    @property
    def docs_url(self) -> Optional[str]:
        """A url to point at docs explaining this flavor.

        Returns:
            A flavor docs url.
        """
        return self.generate_default_docs_url()

    @property
    def sdk_docs_url(self) -> Optional[str]:
        """A url to point at SDK docs explaining this flavor.

        Returns:
            A flavor SDK docs url.
        """
        return self.generate_default_sdk_docs_url()

    @property
    def logo_url(self) -> str:
        """A url to represent the flavor in the dashboard.

        Returns:
            The flavor logo.
        """
        return "https://public-flavor-logos.s3.eu-central-1.amazonaws.com/secrets_managers/local.svg"

    @property
    def config_class(self) -> Type[LocalSecretsManagerConfig]:
        """The config class for this flavor.

        Returns:
            The config class for this flavor.
        """
        return LocalSecretsManagerConfig

    @property
    def implementation_class(self) -> Type["LocalSecretsManager"]:
        """Implementation class for this flavor.

        Returns:
            The implementation class for this flavor.
        """
        return LocalSecretsManager
config_class: Type[zenml.secrets_managers.local.local_secrets_manager.LocalSecretsManagerConfig] property readonly

The config class for this flavor.

Returns:

Type Description
Type[zenml.secrets_managers.local.local_secrets_manager.LocalSecretsManagerConfig]

The config class for this flavor.

docs_url: Optional[str] property readonly

A url to point at docs explaining this flavor.

Returns:

Type Description
Optional[str]

A flavor docs url.

implementation_class: Type[LocalSecretsManager] property readonly

Implementation class for this flavor.

Returns:

Type Description
Type[LocalSecretsManager]

The implementation class for this flavor.

logo_url: str property readonly

A url to represent the flavor in the dashboard.

Returns:

Type Description
str

The flavor logo.

name: str property readonly

Name of the flavor.

Returns:

Type Description
str

The name of the flavor.

sdk_docs_url: Optional[str] property readonly

A url to point at SDK docs explaining this flavor.

Returns:

Type Description
Optional[str]

A flavor SDK docs url.

utils

Utility functions for the ZenML secrets manager module.

decode_secret_dict(secret_dict)

Base64 decode a Secret.

Parameters:

Name Type Description Default
secret_dict Dict[str, str]

dict containing key-value pairs to decode

required

Returns:

Type Description
Tuple[Dict[str, str], str]

Decoded secret Dict containing key-value pairs

Source code in zenml/secrets_managers/utils.py
def decode_secret_dict(
    secret_dict: Dict[str, str]
) -> Tuple[Dict[str, str], str]:
    """Base64 decode a Secret.

    Args:
        secret_dict: dict containing key-value pairs to decode

    Returns:
        Decoded secret Dict containing key-value pairs
    """
    zenml_schema_name = secret_dict.pop(ZENML_SCHEMA_NAME)

    decoded_secret = {k: decode_string(v) for k, v in secret_dict.items()}
    return decoded_secret, zenml_schema_name

decode_string(string)

Base64 decode a string.

Parameters:

Name Type Description Default
string str

String to decode

required

Returns:

Type Description
str

Decoded string

Source code in zenml/secrets_managers/utils.py
def decode_string(string: str) -> str:
    """Base64 decode a string.

    Args:
        string: String to decode

    Returns:
        Decoded string
    """
    decoded_bytes = base64.b64decode(string)
    return str(decoded_bytes, "utf-8")

encode_secret(secret)

Base64 encode all values within a secret.

Parameters:

Name Type Description Default
secret BaseSecretSchema

Secret containing key-value pairs

required

Returns:

Type Description
Dict[str, str]

Encoded secret Dict containing key-value pairs

Source code in zenml/secrets_managers/utils.py
def encode_secret(secret: BaseSecretSchema) -> Dict[str, str]:
    """Base64 encode all values within a secret.

    Args:
        secret: Secret containing key-value pairs

    Returns:
        Encoded secret Dict containing key-value pairs
    """
    encoded_secret = {
        k: encode_string(str(v))
        for k, v in secret.content.items()
        if v is not None
    }
    encoded_secret[ZENML_SCHEMA_NAME] = secret.TYPE
    return encoded_secret

encode_string(string)

Base64 encode a string.

Parameters:

Name Type Description Default
string str

String to encode

required

Returns:

Type Description
str

Encoded string

Source code in zenml/secrets_managers/utils.py
def encode_string(string: str) -> str:
    """Base64 encode a string.

    Args:
        string: String to encode

    Returns:
        Encoded string
    """
    encoded_bytes = base64.b64encode(string.encode("utf-8"))
    return str(encoded_bytes, "utf-8")

secret_from_dict(secret_dict, secret_name='', decode=False)

Converts a dictionary secret representation into a secret.

Parameters:

Name Type Description Default
secret_dict Dict[str, Any]

a dictionary representation of a secret

required
secret_name str

optional name for the secret, defaults to empty string

''
decode bool

if true, decodes the secret values using base64

False

Returns:

Type Description
BaseSecretSchema

A secret instance containing all key-value pairs loaded from the JSON representation and of the ZenML schema type indicated in the JSON.

Source code in zenml/secrets_managers/utils.py
def secret_from_dict(
    secret_dict: Dict[str, Any], secret_name: str = "", decode: bool = False
) -> BaseSecretSchema:
    """Converts a dictionary secret representation into a secret.

    Args:
        secret_dict: a dictionary representation of a secret
        secret_name: optional name for the secret, defaults to empty string
        decode: if true, decodes the secret values using base64

    Returns:
        A secret instance containing all key-value pairs loaded from the JSON
        representation and of the ZenML schema type indicated in the JSON.
    """
    from zenml.secret.secret_schema_class_registry import (
        SecretSchemaClassRegistry,
    )

    secret_contents = secret_dict.copy()

    if decode:
        secret_contents, zenml_schema_name = decode_secret_dict(
            secret_contents
        )
    else:
        zenml_schema_name = secret_contents.pop(ZENML_SCHEMA_NAME)

    secret_contents["name"] = secret_name

    secret_schema = SecretSchemaClassRegistry.get_class(
        secret_schema=zenml_schema_name
    )
    return secret_schema(**secret_contents)

secret_to_dict(secret, encode=False)

Converts a secret to a dict representation with the schema.

This includes the schema type in the secret's JSON representation, so that the correct SecretSchema can be retrieved when the secret is loaded.

Parameters:

Name Type Description Default
secret BaseSecretSchema

a subclass of the BaseSecretSchema class

required
encode bool

if true, encodes the secret values using base64 encoding

False

Returns:

Type Description
Dict[str, Any]

A dict representation containing all key-value pairs and the ZenML schema type.

Source code in zenml/secrets_managers/utils.py
def secret_to_dict(
    secret: BaseSecretSchema, encode: bool = False
) -> Dict[str, Any]:
    """Converts a secret to a dict representation with the schema.

    This includes the schema type in the secret's JSON representation, so that
    the correct SecretSchema can be retrieved when the secret is loaded.

    Args:
        secret: a subclass of the BaseSecretSchema class
        encode: if true, encodes the secret values using base64 encoding

    Returns:
        A dict representation containing all key-value pairs and the ZenML
        schema type.
    """
    if encode:
        secret_contents = encode_secret(secret)
    else:
        secret_contents = secret.content
        secret_contents[ZENML_SCHEMA_NAME] = secret.TYPE

    return secret_contents