Taragolis commented on code in PR #36449: URL: https://github.com/apache/airflow/pull/36449#discussion_r1459066788
########## airflow/providers/yandex/secrets/secrets_manager.py: ########## @@ -0,0 +1,209 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +"""Objects relating to sourcing secrets from Yandex Cloud Lockbox.""" +from __future__ import annotations + +from functools import cached_property + +import yandex.cloud.lockbox.v1.payload_pb2 as payload_pb +import yandex.cloud.lockbox.v1.payload_service_pb2 as payload_service_pb +import yandex.cloud.lockbox.v1.payload_service_pb2_grpc as payload_service_pb_grpc +import yandex.cloud.lockbox.v1.secret_pb2 as secret_pb +import yandex.cloud.lockbox.v1.secret_service_pb2 as secret_service_pb +import yandex.cloud.lockbox.v1.secret_service_pb2_grpc as secret_service_pb_grpc + +from airflow.providers.yandex.hooks.yandex import YandexCloudBaseHook +from airflow.secrets import BaseSecretsBackend + + +class SecretsManagerBackend(BaseSecretsBackend): + """ + Retrieves Connection or Variables from Yandex Lockbox. + + Configurable via ``airflow.cfg`` like so: + + .. code-block:: ini + + [secrets] + backend = airflow.providers.yandex.secrets.secrets_manager.SecretsManagerBackend + backend_kwargs = {"connections_prefix": "airflow/connections"} + + For example, when ``{"connections_prefix": "airflow/connections"}`` is set, if a secret is defined with + the path ``airflow/connections/smtp_default``, the connection with conn_id ``smtp_default`` would be + accessible. + + When ``{"variables_prefix": "airflow/variables"}`` is set, if a secret is defined with + the path ``airflow/variables/hello``, the variable with the name ``hello`` would be accessible. + + When ``{"config_prefix": "airflow/config"}`` is set, if a secret is defined with + the path ``airflow/config/sql_alchemy_conn``, the config with key ``sql_alchemy_conn`` would be + accessible. + + When the prefix is empty, keys will use the Lockbox Secrets without any prefix. + + .. code-block:: ini + + [secrets] + backend = airflow.providers.yandex.secrets.secrets_manager.SecretsManagerBackend + backend_kwargs = {"connection_id": "<connection_ID>", "folder_id": "<folder_ID>"} + + You need to specify id of yandexcloud connection to connect to Yandex Lockbox with. + Also, you need to specify the Yandex Cloud folder ID to search for Yandex Lockbox secrets in. + + :param connection_id: Specifies the connection ID to connect to Yandex Lockbox with. + If set to None (null), requests will use default connection_id from YandexCloudBaseHook. + Default: "yandexcloud_default" + :param folder_id: Specifies the folder ID to search for Yandex Lockbox secrets in. + If set to None (null), requests will use the connection folder_id. + :param connections_prefix: Specifies the prefix of the secret to read to get Connections. + If set to None (null), requests for connections will not be sent to Yandex Lockbox. + Default: "airflow/connections" + :param variables_prefix: Specifies the prefix of the secret to read to get Variables. + If set to None (null), requests for variables will not be sent to Yandex Lockbox. + Default: "airflow/variables" + :param config_prefix: Specifies the prefix of the secret to read to get Configurations. + If set to None (null), requests for variables will not be sent to Yandex Lockbox. + Default: "airflow/config" + :param sep: Specifies the separator used to concatenate secret_prefix and secret_id. + Default: "/" + """ + + def __init__( + self, + connection_id: str | None = None, + folder_id: str | None = None, + connections_prefix: str | None = "airflow/connections", + variables_prefix: str | None = "airflow/variables", + config_prefix: str | None = "airflow/config", + sep: str = "/", + ): + super().__init__() + + self.connection_id = connection_id + self.folder_id = folder_id + self.connections_prefix = connections_prefix.rstrip(sep) if connections_prefix is not None else None + self.variables_prefix = variables_prefix.rstrip(sep) if variables_prefix is not None else None + self.config_prefix = config_prefix.rstrip(sep) if config_prefix is not None else None + self.sep = sep + + @property + def _client(self): + """Create a Yandex Cloud SDK client.""" + return self._base_hook.client + + @cached_property + def _base_hook(self) -> YandexCloudBaseHook: + return YandexCloudBaseHook( + yandex_conn_id=self.connection_id, + default_folder_id=self.folder_id, + ) + + def get_conn_value(self, conn_id: str) -> str | None: + """ + Retrieve from Secrets Backend a string value representing the Connection object. + + :param conn_id: connection id + :return: Connection Value + """ + if self.connections_prefix is None: + return None + + if conn_id == self.connection_id: + return None + + if not self.connection_id and conn_id == YandexCloudBaseHook.default_conn_name: Review Comment: Resolve in favor of https://github.com/apache/airflow/pull/36449#discussion_r1456111043 -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
