[GitHub] [airflow] ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support for HashiCorp Vault as Secrets Backend

2020-03-19 Thread GitBox
ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support 
for HashiCorp Vault as Secrets Backend
URL: https://github.com/apache/airflow/pull/7741#discussion_r395299575
 
 

 ##
 File path: airflow/providers/hashicorp/secrets/vault.py
 ##
 @@ -0,0 +1,214 @@
+#
+# 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 connections from Hashicorp Vault
+"""
+from typing import List, Optional
+
+import hvac
+from cached_property import cached_property
+from hvac.exceptions import InvalidPath, VaultError
+
+from airflow import AirflowException
+from airflow.models import Connection
+from airflow.secrets import BaseSecretsBackend
+from airflow.utils.log.logging_mixin import LoggingMixin
+
+
+class VaultSecrets(BaseSecretsBackend, LoggingMixin):
+"""
+Retrieves Connection object from Hashicorp Vault
+
+Configurable via ``airflow.cfg`` as follows:
+
+.. code-block:: ini
+
+[secrets]
+backend = airflow.providers.hashicorp.secrets.vault.VaultSecrets
+backend_kwargs = 
{"path":"connections","url":"http://127.0.0.1:8200","mount_point":"airflow"}
+
+For example, if your keys are under ``connections`` path in ``airflow`` 
mount_point, this
+would be accessible if you provide ``{"path": "connections"}`` and request
+conn_id ``smtp_default``.
+
+:param connections_path: Specifies the path of the secret to read to get 
Connections.
+:type connections_path: str
+:param url: Base URL for the Vault instance being addressed.
+:type url: str
+:param auth_type: Authentication Type for Vault (one of 'token', 'ldap', 
'userpass', 'approle',
+'github', 'gcp). Default is ``token``.
+:type auth_type: str
+:param mount_point: The "path" the secret engine was mounted on. (Default: 
``secret``)
+:type mount_point: str
+:param token: Authentication token to include in requests sent to Vault.
+(for ``token`` and ``github`` auth_type)
+:type token: str
+:param kv_engine_version: Select the version of the engine to run (``1`` 
or ``2``, default: ``2``)
+:type kv_engine_version: int
+:param username: Username for Authentication (for ``ldap`` and 
``userpass`` auth_type)
+:type username: str
+:param password: Password for Authentication (for ``ldap`` and 
``userpass`` auth_type)
+:type password: str
+:param role_id: Role ID for Authentication (for ``approle`` auth_type)
+:type role_id: str
+:param secret_id: Secret ID for Authentication (for ``approle`` auth_type)
+:type secret_id: str
+:param gcp_key_path: Path to GCP Credential JSON file (for ``gcp`` 
auth_type)
+:type gcp_key_path: str
+:param gcp_scopes: Comma-separated string containing GCP scopes (for 
``gcp`` auth_type)
+:type gcp_scopes: str
+"""
+def __init__(  # pylint: disable=too-many-arguments
+self,
+connections_path: str,
+url: Optional[str] = None,
+auth_type: str = 'token',
+mount_point: str = 'secret',
+kv_engine_version: int = 2,
+token: Optional[str] = None,
+username: Optional[str] = None,
+password: Optional[str] = None,
+role_id: Optional[str] = None,
+secret_id: Optional[str] = None,
+gcp_key_path: Optional[str] = None,
+gcp_scopes: Optional[str] = None,
+**kwargs
+):
+super().__init__(**kwargs)
+self.connections_path = connections_path.rstrip('/')
+self.url = url
+self.auth_type = auth_type
+self.kwargs = kwargs
+self.token = token
+self.username = username
+self.password = password
+self.role_id = role_id
+self.secret_id = secret_id
+self.mount_point = mount_point
+self.kv_engine_version = kv_engine_version
+self.gcp_key_path = gcp_key_path
+self.gcp_scopes = gcp_scopes
+
+@cached_property
+def client(self) -> hvac.Client:
+"""
+Return an authenticated Hashicorp Vault client
+"""
+
+_client = hvac.Client(url=self.url, **self.kwargs)
+if self.auth_type == "token":
+_client.token = self.token
+elif 

[GitHub] [airflow] ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support for HashiCorp Vault as Secrets Backend

2020-03-19 Thread GitBox
ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support 
for HashiCorp Vault as Secrets Backend
URL: https://github.com/apache/airflow/pull/7741#discussion_r395299828
 
 

 ##
 File path: airflow/providers/hashicorp/secrets/vault.py
 ##
 @@ -0,0 +1,214 @@
+#
+# 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 connections from Hashicorp Vault
+"""
+from typing import List, Optional
+
+import hvac
+from cached_property import cached_property
+from hvac.exceptions import InvalidPath, VaultError
+
+from airflow import AirflowException
+from airflow.models import Connection
+from airflow.secrets import BaseSecretsBackend
+from airflow.utils.log.logging_mixin import LoggingMixin
+
+
+class VaultSecrets(BaseSecretsBackend, LoggingMixin):
+"""
+Retrieves Connection object from Hashicorp Vault
+
+Configurable via ``airflow.cfg`` as follows:
+
+.. code-block:: ini
+
+[secrets]
+backend = airflow.providers.hashicorp.secrets.vault.VaultSecrets
+backend_kwargs = 
{"path":"connections","url":"http://127.0.0.1:8200","mount_point":"airflow"}
+
+For example, if your keys are under ``connections`` path in ``airflow`` 
mount_point, this
+would be accessible if you provide ``{"path": "connections"}`` and request
+conn_id ``smtp_default``.
+
+:param connections_path: Specifies the path of the secret to read to get 
Connections.
+:type connections_path: str
+:param url: Base URL for the Vault instance being addressed.
+:type url: str
+:param auth_type: Authentication Type for Vault (one of 'token', 'ldap', 
'userpass', 'approle',
+'github', 'gcp). Default is ``token``.
+:type auth_type: str
+:param mount_point: The "path" the secret engine was mounted on. (Default: 
``secret``)
+:type mount_point: str
+:param token: Authentication token to include in requests sent to Vault.
+(for ``token`` and ``github`` auth_type)
+:type token: str
+:param kv_engine_version: Select the version of the engine to run (``1`` 
or ``2``, default: ``2``)
+:type kv_engine_version: int
+:param username: Username for Authentication (for ``ldap`` and 
``userpass`` auth_type)
+:type username: str
+:param password: Password for Authentication (for ``ldap`` and 
``userpass`` auth_type)
+:type password: str
+:param role_id: Role ID for Authentication (for ``approle`` auth_type)
+:type role_id: str
+:param secret_id: Secret ID for Authentication (for ``approle`` auth_type)
+:type secret_id: str
+:param gcp_key_path: Path to GCP Credential JSON file (for ``gcp`` 
auth_type)
+:type gcp_key_path: str
+:param gcp_scopes: Comma-separated string containing GCP scopes (for 
``gcp`` auth_type)
+:type gcp_scopes: str
+"""
+def __init__(  # pylint: disable=too-many-arguments
+self,
+connections_path: str,
+url: Optional[str] = None,
+auth_type: str = 'token',
+mount_point: str = 'secret',
+kv_engine_version: int = 2,
+token: Optional[str] = None,
+username: Optional[str] = None,
+password: Optional[str] = None,
+role_id: Optional[str] = None,
+secret_id: Optional[str] = None,
+gcp_key_path: Optional[str] = None,
+gcp_scopes: Optional[str] = None,
+**kwargs
+):
+super().__init__(**kwargs)
+self.connections_path = connections_path.rstrip('/')
+self.url = url
+self.auth_type = auth_type
+self.kwargs = kwargs
+self.token = token
+self.username = username
+self.password = password
+self.role_id = role_id
+self.secret_id = secret_id
+self.mount_point = mount_point
+self.kv_engine_version = kv_engine_version
+self.gcp_key_path = gcp_key_path
+self.gcp_scopes = gcp_scopes
+
+@cached_property
+def client(self) -> hvac.Client:
+"""
+Return an authenticated Hashicorp Vault client
+"""
+
+_client = hvac.Client(url=self.url, **self.kwargs)
+if self.auth_type == "token":
+_client.token = self.token
+elif 

[GitHub] [airflow] ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support for HashiCorp Vault as Secrets Backend

2020-03-19 Thread GitBox
ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support 
for HashiCorp Vault as Secrets Backend
URL: https://github.com/apache/airflow/pull/7741#discussion_r395298801
 
 

 ##
 File path: airflow/providers/hashicorp/secrets/vault.py
 ##
 @@ -0,0 +1,214 @@
+#
+# 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 connections from Hashicorp Vault
+"""
+from typing import List, Optional
+
+import hvac
+from cached_property import cached_property
+from hvac.exceptions import InvalidPath, VaultError
+
+from airflow import AirflowException
+from airflow.models import Connection
+from airflow.secrets import BaseSecretsBackend
+from airflow.utils.log.logging_mixin import LoggingMixin
+
+
+class VaultSecrets(BaseSecretsBackend, LoggingMixin):
+"""
+Retrieves Connection object from Hashicorp Vault
+
+Configurable via ``airflow.cfg`` as follows:
+
+.. code-block:: ini
+
+[secrets]
+backend = airflow.providers.hashicorp.secrets.vault.VaultSecrets
+backend_kwargs = 
{"path":"connections","url":"http://127.0.0.1:8200","mount_point":"airflow"}
+
+For example, if your keys are under ``connections`` path in ``airflow`` 
mount_point, this
+would be accessible if you provide ``{"path": "connections"}`` and request
+conn_id ``smtp_default``.
+
+:param connections_path: Specifies the path of the secret to read to get 
Connections.
+:type connections_path: str
+:param url: Base URL for the Vault instance being addressed.
+:type url: str
+:param auth_type: Authentication Type for Vault (one of 'token', 'ldap', 
'userpass', 'approle',
+'github', 'gcp). Default is ``token``.
+:type auth_type: str
+:param mount_point: The "path" the secret engine was mounted on. (Default: 
``secret``)
+:type mount_point: str
+:param token: Authentication token to include in requests sent to Vault.
+(for ``token`` and ``github`` auth_type)
+:type token: str
+:param kv_engine_version: Select the version of the engine to run (``1`` 
or ``2``, default: ``2``)
+:type kv_engine_version: int
+:param username: Username for Authentication (for ``ldap`` and 
``userpass`` auth_type)
+:type username: str
+:param password: Password for Authentication (for ``ldap`` and 
``userpass`` auth_type)
+:type password: str
+:param role_id: Role ID for Authentication (for ``approle`` auth_type)
+:type role_id: str
+:param secret_id: Secret ID for Authentication (for ``approle`` auth_type)
+:type secret_id: str
+:param gcp_key_path: Path to GCP Credential JSON file (for ``gcp`` 
auth_type)
+:type gcp_key_path: str
+:param gcp_scopes: Comma-separated string containing GCP scopes (for 
``gcp`` auth_type)
+:type gcp_scopes: str
+"""
+def __init__(  # pylint: disable=too-many-arguments
+self,
+connections_path: str,
+url: Optional[str] = None,
+auth_type: str = 'token',
+mount_point: str = 'secret',
+kv_engine_version: int = 2,
+token: Optional[str] = None,
+username: Optional[str] = None,
+password: Optional[str] = None,
+role_id: Optional[str] = None,
+secret_id: Optional[str] = None,
+gcp_key_path: Optional[str] = None,
+gcp_scopes: Optional[str] = None,
+**kwargs
+):
+super().__init__(**kwargs)
+self.connections_path = connections_path.rstrip('/')
+self.url = url
+self.auth_type = auth_type
+self.kwargs = kwargs
+self.token = token
+self.username = username
+self.password = password
+self.role_id = role_id
+self.secret_id = secret_id
+self.mount_point = mount_point
+self.kv_engine_version = kv_engine_version
+self.gcp_key_path = gcp_key_path
+self.gcp_scopes = gcp_scopes
+
+@cached_property
+def client(self) -> hvac.Client:
+"""
+Return an authenticated Hashicorp Vault client
+"""
+
+_client = hvac.Client(url=self.url, **self.kwargs)
+if self.auth_type == "token":
+_client.token = self.token
 
 Review comment:
   We 

[GitHub] [airflow] ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support for HashiCorp Vault as Secrets Backend

2020-03-19 Thread GitBox
ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support 
for HashiCorp Vault as Secrets Backend
URL: https://github.com/apache/airflow/pull/7741#discussion_r395209173
 
 

 ##
 File path: tests/providers/hashicorp/secrets/test_vault.py
 ##
 @@ -0,0 +1,137 @@
+# 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.
+
+from unittest import TestCase, mock
+
+from hvac.exceptions import VaultError
+
+from airflow.providers.hashicorp.secrets.vault import VaultSecrets
+
+
+class TestVaultSecrets(TestCase):
+
+@mock.patch("airflow.providers.hashicorp.secrets.vault.hvac")
+def test_get_conn_uri(self, mock_hvac):
+mock_client = mock.MagicMock()
+mock_hvac.Client.return_value = mock_client
+mock_client.secrets.kv.v2.read_secret_version.return_value = {
+'request_id': '94011e25-f8dc-ec29-221b-1f9c1d9ad2ae',
+'lease_id': '',
+'renewable': False,
+'lease_duration': 0,
+'data': {
+'data': {'test_postgres': 
'postgresql://airflow:airflow@host:5432/airflow'},
 
 Review comment:
   Does G kms just have a single key at each path, or does it also have keys 
like valut does?


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.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [airflow] ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support for HashiCorp Vault as Secrets Backend

2020-03-19 Thread GitBox
ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support 
for HashiCorp Vault as Secrets Backend
URL: https://github.com/apache/airflow/pull/7741#discussion_r394929982
 
 

 ##
 File path: tests/providers/hashicorp/secrets/test_vault.py
 ##
 @@ -0,0 +1,137 @@
+# 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.
+
+from unittest import TestCase, mock
+
+from hvac.exceptions import VaultError
+
+from airflow.providers.hashicorp.secrets.vault import VaultSecrets
+
+
+class TestVaultSecrets(TestCase):
+
+@mock.patch("airflow.providers.hashicorp.secrets.vault.hvac")
+def test_get_conn_uri(self, mock_hvac):
+mock_client = mock.MagicMock()
+mock_hvac.Client.return_value = mock_client
+mock_client.secrets.kv.v2.read_secret_version.return_value = {
+'request_id': '94011e25-f8dc-ec29-221b-1f9c1d9ad2ae',
+'lease_id': '',
+'renewable': False,
+'lease_duration': 0,
+'data': {
+'data': {'test_postgres': 
'postgresql://airflow:airflow@host:5432/airflow'},
 
 Review comment:
   By having them all in a single path does it restrict the ability to apply 
different policies to each key?


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.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [airflow] ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support for HashiCorp Vault as Secrets Backend

2020-03-18 Thread GitBox
ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support 
for HashiCorp Vault as Secrets Backend
URL: https://github.com/apache/airflow/pull/7741#discussion_r394660515
 
 

 ##
 File path: tests/providers/hashicorp/secrets/test_vault.py
 ##
 @@ -0,0 +1,137 @@
+# 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.
+
+from unittest import TestCase, mock
+
+from hvac.exceptions import VaultError
+
+from airflow.providers.hashicorp.secrets.vault import VaultSecrets
+
+
+class TestVaultSecrets(TestCase):
+
+@mock.patch("airflow.providers.hashicorp.secrets.vault.hvac")
+def test_get_conn_uri(self, mock_hvac):
+mock_client = mock.MagicMock()
+mock_hvac.Client.return_value = mock_client
+mock_client.secrets.kv.v2.read_secret_version.return_value = {
+'request_id': '94011e25-f8dc-ec29-221b-1f9c1d9ad2ae',
+'lease_id': '',
+'renewable': False,
+'lease_duration': 0,
+'data': {
+'data': {'test_postgres': 
'postgresql://airflow:airflow@host:5432/airflow'},
 
 Review comment:
   Remember: I'm not familiar with Vault so may be making stupid assumptions.


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.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [airflow] ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support for HashiCorp Vault as Secrets Backend

2020-03-18 Thread GitBox
ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support 
for HashiCorp Vault as Secrets Backend
URL: https://github.com/apache/airflow/pull/7741#discussion_r394659919
 
 

 ##
 File path: tests/providers/hashicorp/secrets/test_vault.py
 ##
 @@ -0,0 +1,137 @@
+# 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.
+
+from unittest import TestCase, mock
+
+from hvac.exceptions import VaultError
+
+from airflow.providers.hashicorp.secrets.vault import VaultSecrets
+
+
+class TestVaultSecrets(TestCase):
+
+@mock.patch("airflow.providers.hashicorp.secrets.vault.hvac")
+def test_get_conn_uri(self, mock_hvac):
+mock_client = mock.MagicMock()
+mock_hvac.Client.return_value = mock_client
+mock_client.secrets.kv.v2.read_secret_version.return_value = {
+'request_id': '94011e25-f8dc-ec29-221b-1f9c1d9ad2ae',
+'lease_id': '',
+'renewable': False,
+'lease_duration': 0,
+'data': {
+'data': {'test_postgres': 
'postgresql://airflow:airflow@host:5432/airflow'},
 
 Review comment:
   Current method:
   
   ```
   vault kv put airflow/connections 
smtp_default=smtps://user:h...@relay.example.com:465
   vault kv put airflow/connections 
postgres_default=postgresql://airflow:airflow@host:5432/airflow
   ```
   
   My proposal:
   
   ```
   vault kv put airflow/connections/smtp_default 
conn_uri=smtps://user:h...@relay.example.com:465
   vault kv put airflow/connections 
conn_uri=postgresql://airflow:airflow@host:5432/airflow
   ```
   
   And conn_uri is there so we could do this in the future:
   
   ```
   vault kv put airflow/connections conn_type=postgresql user=airflow 
password=airflow host=host port=5432 schema=airflow
   ```


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.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [airflow] ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support for HashiCorp Vault as Secrets Backend

2020-03-18 Thread GitBox
ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support 
for HashiCorp Vault as Secrets Backend
URL: https://github.com/apache/airflow/pull/7741#discussion_r394658839
 
 

 ##
 File path: tests/providers/hashicorp/secrets/test_vault.py
 ##
 @@ -0,0 +1,137 @@
+# 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.
+
+from unittest import TestCase, mock
+
+from hvac.exceptions import VaultError
+
+from airflow.providers.hashicorp.secrets.vault import VaultSecrets
+
+
+class TestVaultSecrets(TestCase):
+
+@mock.patch("airflow.providers.hashicorp.secrets.vault.hvac")
+def test_get_conn_uri(self, mock_hvac):
+mock_client = mock.MagicMock()
+mock_hvac.Client.return_value = mock_client
+mock_client.secrets.kv.v2.read_secret_version.return_value = {
+'request_id': '94011e25-f8dc-ec29-221b-1f9c1d9ad2ae',
+'lease_id': '',
+'renewable': False,
+'lease_duration': 0,
+'data': {
+'data': {'test_postgres': 
'postgresql://airflow:airflow@host:5432/airflow'},
 
 Review comment:
   `conn_uri` is there because you need _something_ as the key, don't you?


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.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [airflow] ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support for HashiCorp Vault as Secrets Backend

2020-03-18 Thread GitBox
ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support 
for HashiCorp Vault as Secrets Backend
URL: https://github.com/apache/airflow/pull/7741#discussion_r394658547
 
 

 ##
 File path: tests/providers/hashicorp/secrets/test_vault.py
 ##
 @@ -0,0 +1,137 @@
+# 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.
+
+from unittest import TestCase, mock
+
+from hvac.exceptions import VaultError
+
+from airflow.providers.hashicorp.secrets.vault import VaultSecrets
+
+
+class TestVaultSecrets(TestCase):
+
+@mock.patch("airflow.providers.hashicorp.secrets.vault.hvac")
+def test_get_conn_uri(self, mock_hvac):
+mock_client = mock.MagicMock()
+mock_hvac.Client.return_value = mock_client
+mock_client.secrets.kv.v2.read_secret_version.return_value = {
+'request_id': '94011e25-f8dc-ec29-221b-1f9c1d9ad2ae',
+'lease_id': '',
+'renewable': False,
+'lease_duration': 0,
+'data': {
+'data': {'test_postgres': 
'postgresql://airflow:airflow@host:5432/airflow'},
 
 Review comment:
   Yes, that seems to be the level Vault polices operate at: 
https://www.vaultproject.io/docs/concepts/policies/#policy-syntax


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.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [airflow] ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support for HashiCorp Vault as Secrets Backend

2020-03-18 Thread GitBox
ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support 
for HashiCorp Vault as Secrets Backend
URL: https://github.com/apache/airflow/pull/7741#discussion_r394657719
 
 

 ##
 File path: tests/providers/hashicorp/secrets/test_vault.py
 ##
 @@ -0,0 +1,137 @@
+# 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.
+
+from unittest import TestCase, mock
+
+from hvac.exceptions import VaultError
+
+from airflow.providers.hashicorp.secrets.vault import VaultSecrets
+
+
+class TestVaultSecrets(TestCase):
+
+@mock.patch("airflow.providers.hashicorp.secrets.vault.hvac")
+def test_get_conn_uri(self, mock_hvac):
+mock_client = mock.MagicMock()
+mock_hvac.Client.return_value = mock_client
+mock_client.secrets.kv.v2.read_secret_version.return_value = {
+'request_id': '94011e25-f8dc-ec29-221b-1f9c1d9ad2ae',
+'lease_id': '',
+'renewable': False,
+'lease_duration': 0,
+'data': {
+'data': {'test_postgres': 
'postgresql://airflow:airflow@host:5432/airflow'},
 
 Review comment:
   I.e. instead of this
   
   ```
   vault kv put airflow/connections 
smtp_default=postgresql://airflow:airflow@host:5432/airflow
   ```
   
   I'm proposing we do
   
   ```
   vault kv put airflow/connections/smtp_default
   conn_uri=postgresql://airflow:airflow@host:5432/airflow
   ```


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.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [airflow] ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support for HashiCorp Vault as Secrets Backend

2020-03-18 Thread GitBox
ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support 
for HashiCorp Vault as Secrets Backend
URL: https://github.com/apache/airflow/pull/7741#discussion_r394657351
 
 

 ##
 File path: tests/providers/hashicorp/secrets/test_vault.py
 ##
 @@ -0,0 +1,137 @@
+# 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.
+
+from unittest import TestCase, mock
+
+from hvac.exceptions import VaultError
+
+from airflow.providers.hashicorp.secrets.vault import VaultSecrets
+
+
+class TestVaultSecrets(TestCase):
+
+@mock.patch("airflow.providers.hashicorp.secrets.vault.hvac")
+def test_get_conn_uri(self, mock_hvac):
+mock_client = mock.MagicMock()
+mock_hvac.Client.return_value = mock_client
+mock_client.secrets.kv.v2.read_secret_version.return_value = {
+'request_id': '94011e25-f8dc-ec29-221b-1f9c1d9ad2ae',
+'lease_id': '',
+'renewable': False,
+'lease_duration': 0,
+'data': {
+'data': {'test_postgres': 
'postgresql://airflow:airflow@host:5432/airflow'},
 
 Review comment:
   Right now this seems to be _all_ connections in a single path, with 
different values for each of them. I would have expected that each connection 
is it's own secret instead.
   
   (I'm guessing Vault lets you limit access based on path, but not on key?)


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.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [airflow] ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support for HashiCorp Vault as Secrets Backend

2020-03-18 Thread GitBox
ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support 
for HashiCorp Vault as Secrets Backend
URL: https://github.com/apache/airflow/pull/7741#discussion_r394656677
 
 

 ##
 File path: tests/providers/hashicorp/secrets/test_vault.py
 ##
 @@ -0,0 +1,137 @@
+# 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.
+
+from unittest import TestCase, mock
+
+from hvac.exceptions import VaultError
+
+from airflow.providers.hashicorp.secrets.vault import VaultSecrets
+
+
+class TestVaultSecrets(TestCase):
+
+@mock.patch("airflow.providers.hashicorp.secrets.vault.hvac")
+def test_get_conn_uri(self, mock_hvac):
+mock_client = mock.MagicMock()
+mock_hvac.Client.return_value = mock_client
+mock_client.secrets.kv.v2.read_secret_version.return_value = {
+'request_id': '94011e25-f8dc-ec29-221b-1f9c1d9ad2ae',
+'lease_id': '',
+'renewable': False,
+'lease_duration': 0,
+'data': {
+'data': {'test_postgres': 
'postgresql://airflow:airflow@host:5432/airflow'},
 
 Review comment:
   `test_postgres` here is in the duplicated in the key name isn't it? To make 
it easy to support storing in other forms (such as a k/v per attribute, i.e. 
not needing to URI parse) we could store that as 
   ```suggestion
   'data': {'conn_uri': 
'postgresql://airflow:airflow@host:5432/airflow'},
   ```
   
   WDYT?


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.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [airflow] ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support for HashiCorp Vault as Secrets Backend

2020-03-18 Thread GitBox
ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support 
for HashiCorp Vault as Secrets Backend
URL: https://github.com/apache/airflow/pull/7741#discussion_r394655248
 
 

 ##
 File path: tests/providers/hashicorp/secrets/test_vault.py
 ##
 @@ -0,0 +1,137 @@
+# 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.
+
+from unittest import TestCase, mock
+
+from hvac.exceptions import VaultError
+
+from airflow.providers.hashicorp.secrets.vault import VaultSecrets
+
+
+class TestVaultSecrets(TestCase):
+
+@mock.patch("airflow.providers.hashicorp.secrets.vault.hvac")
+def test_get_conn_uri(self, mock_hvac):
+mock_client = mock.MagicMock()
+mock_hvac.Client.return_value = mock_client
+mock_client.secrets.kv.v2.read_secret_version.return_value = {
+'request_id': '94011e25-f8dc-ec29-221b-1f9c1d9ad2ae',
+'lease_id': '',
+'renewable': False,
+'lease_duration': 0,
+'data': {
+'data': {'test_postgres': 
'postgresql://airflow:airflow@host:5432/airflow'},
+'metadata': {'created_time': '2020-03-16T21:01:43.331126Z',
+ 'deletion_time': '',
+ 'destroyed': False,
+ 'version': 1}},
+'wrap_info': None,
+'warnings': None,
+'auth': None
+}
+
+kwargs = {
+"connections_path": "airflow/connections",
+"auth_type": "token",
+"url": "http://127.0.0.1:8200;,
+"token": "s.7AU0I51yv1Q1lxOIg1F3ZRAS"
+}
+
+test_client = VaultSecrets(**kwargs)
+returned_uri = test_client.get_conn_uri(conn_id="test_postgres")
 
 Review comment:
   Is it worth adding an assertion to check that 
`mock_client.secrets.kv.v2.read_secret_version` is called with args we expect 
(path, secret name etc.)


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.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [airflow] ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support for HashiCorp Vault as Secrets Backend

2020-03-18 Thread GitBox
ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support 
for HashiCorp Vault as Secrets Backend
URL: https://github.com/apache/airflow/pull/7741#discussion_r394654715
 
 

 ##
 File path: tests/providers/hashicorp/secrets/test_vault.py
 ##
 @@ -0,0 +1,137 @@
+# 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.
+
+from unittest import TestCase, mock
+
+from hvac.exceptions import VaultError
+
+from airflow.providers.hashicorp.secrets.vault import VaultSecrets
+
+
+class TestVaultSecrets(TestCase):
+
+@mock.patch("airflow.providers.hashicorp.secrets.vault.hvac")
+def test_get_conn_uri(self, mock_hvac):
+mock_client = mock.MagicMock()
+mock_hvac.Client.return_value = mock_client
+mock_client.secrets.kv.v2.read_secret_version.return_value = {
+'request_id': '94011e25-f8dc-ec29-221b-1f9c1d9ad2ae',
+'lease_id': '',
+'renewable': False,
+'lease_duration': 0,
+'data': {
+'data': {'test_postgres': 
'postgresql://airflow:airflow@host:5432/airflow'},
+'metadata': {'created_time': '2020-03-16T21:01:43.331126Z',
+ 'deletion_time': '',
+ 'destroyed': False,
+ 'version': 1}},
+'wrap_info': None,
+'warnings': None,
+'auth': None
+}
+
+kwargs = {
+"connections_path": "airflow/connections",
 
 Review comment:
   Not _super_ important, but this doesn't line up with the example in the docs.


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.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [airflow] ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support for HashiCorp Vault as Secrets Backend

2020-03-18 Thread GitBox
ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support 
for HashiCorp Vault as Secrets Backend
URL: https://github.com/apache/airflow/pull/7741#discussion_r394197368
 
 

 ##
 File path: airflow/providers/hashicorp/secrets/vault.py
 ##
 @@ -0,0 +1,196 @@
+#
+# 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 connections from Hashicorp Vault
+"""
+from typing import List, Optional
+
+import hvac
+from hvac.exceptions import VaultError
+
+from airflow import AirflowException
+from airflow.models import Connection
+from airflow.secrets import CONN_ENV_PREFIX, BaseSecretsBackend
+from airflow.utils.log.logging_mixin import LoggingMixin
+
+
+class VaultSecrets(BaseSecretsBackend, LoggingMixin):
+"""
+Retrieves Connection object from Hashicorp Vault Secrets
+
+Configurable via ``airflow.cfg`` as follows:
+
+.. code-block:: ini
+
+[secrets]
+backend = airflow.providers.hashicorp.secrets.vault.VaultSecrets
+backend_kwargs = {"path": "airflow", "url": "http://127.0.0.1:8200"}
+
+For example, if your keys are under ``airflow/AIRFLOW_CONN_SMTP_DEFAULT``, 
this would be accessible if you
+provide ``{"path": "airflow"}`` and request conn_id ``smtp_default``.
+
+:param path: Specifies the path of the secret to read.
+:type path: str
+:param url: Base URL for the Vault instance being addressed.
+:type url: str
+:param auth_type: Authentication Type for Vault (one of 'token', 'ldap', 
'userpass', 'approle',
+'github', 'gcp). Default is ``token``.
+:type auth_type: str
+:param mount_point: The "path" the secret engine was mounted on. (Default: 
``secret``)
+:type mount_point: str
+:param token: Authentication token to include in requests sent to Vault.
+(for ``token`` and ``github`` auth_type)
+:type token: str
+:param username: Username for Authentication (for ``ldap`` and 
``userpass`` auth_type)
+:type username: str
+:param password: Password for Authentication (for ``ldap`` and 
``userpass`` auth_type)
+:type password: str
+:param role_id: Role ID for Authentication (for ``approle`` auth_type)
+:type role_id: str
+:param secret_id: Secret ID for Authentication (for ``approle`` auth_type)
+:type secret_id: str
+:param gcp_key_path: Path to GCP Credential JSON file (for ``gcp`` 
auth_type)
+:type gcp_key_path: str
+:param gcp_scopes: Comma-separated string containing GCP scopes (for 
``gcp`` auth_type)
+:type gcp_scopes: str
+"""
+def __init__(  # pylint: disable=too-many-arguments
+self,
+path: str,
+url: Optional[str] = None,
+auth_type: str = 'token',
+mount_point: str = 'secret',
+token: Optional[str] = None,
+username: Optional[str] = None,
+password: Optional[str] = None,
+role_id: Optional[str] = None,
+secret_id: Optional[str] = None,
+gcp_key_path: Optional[str] = None,
+gcp_scopes: Optional[str] = None,
+**kwargs
+):
+super().__init__()
+self.path = path.rstrip('/')
+self.url = url
+self.auth_type = auth_type
+self.kwargs = kwargs
+self.token = token
+self.username = username
+self.password = password
+self.role_id = role_id
+self.secret_id = secret_id
+self.mount_point = mount_point
+self.gcp_key_path = gcp_key_path
+self.gcp_scopes = gcp_scopes
+self._client: Optional[hvac.Client] = None
+
+def get_client(self) -> hvac.Client:
+"""
+Return an authenticated Hashicorp Vault client
+"""
+if not self._client:
+self._client = hvac.Client(url=self.url, **self.kwargs)
+if self.auth_type == "token":
+self._client.token = self.token
+elif self.auth_type == "ldap":
+self._client.auth.ldap.login(
+username=self.username, password=self.password)
+elif self.auth_type == "userpass":
+self._client.auth_userpass(username=self.username, 
password=self.password)
+elif self.auth_type == 

[GitHub] [airflow] ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support for HashiCorp Vault as Secrets Backend

2020-03-18 Thread GitBox
ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support 
for HashiCorp Vault as Secrets Backend
URL: https://github.com/apache/airflow/pull/7741#discussion_r394194861
 
 

 ##
 File path: airflow/providers/hashicorp/secrets/vault.py
 ##
 @@ -0,0 +1,196 @@
+#
+# 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 connections from Hashicorp Vault
+"""
+from typing import List, Optional
+
+import hvac
+from hvac.exceptions import VaultError
+
+from airflow import AirflowException
+from airflow.models import Connection
+from airflow.secrets import CONN_ENV_PREFIX, BaseSecretsBackend
+from airflow.utils.log.logging_mixin import LoggingMixin
+
+
+class VaultSecrets(BaseSecretsBackend, LoggingMixin):
+"""
+Retrieves Connection object from Hashicorp Vault Secrets
+
+Configurable via ``airflow.cfg`` as follows:
+
+.. code-block:: ini
+
+[secrets]
+backend = airflow.providers.hashicorp.secrets.vault.VaultSecrets
+backend_kwargs = {"path": "airflow", "url": "http://127.0.0.1:8200"}
+
+For example, if your keys are under ``airflow/AIRFLOW_CONN_SMTP_DEFAULT``, 
this would be accessible if you
+provide ``{"path": "airflow"}`` and request conn_id ``smtp_default``.
+
+:param path: Specifies the path of the secret to read.
+:type path: str
+:param url: Base URL for the Vault instance being addressed.
+:type url: str
+:param auth_type: Authentication Type for Vault (one of 'token', 'ldap', 
'userpass', 'approle',
+'github', 'gcp). Default is ``token``.
+:type auth_type: str
+:param mount_point: The "path" the secret engine was mounted on. (Default: 
``secret``)
+:type mount_point: str
+:param token: Authentication token to include in requests sent to Vault.
+(for ``token`` and ``github`` auth_type)
+:type token: str
+:param username: Username for Authentication (for ``ldap`` and 
``userpass`` auth_type)
+:type username: str
+:param password: Password for Authentication (for ``ldap`` and 
``userpass`` auth_type)
+:type password: str
+:param role_id: Role ID for Authentication (for ``approle`` auth_type)
+:type role_id: str
+:param secret_id: Secret ID for Authentication (for ``approle`` auth_type)
+:type secret_id: str
+:param gcp_key_path: Path to GCP Credential JSON file (for ``gcp`` 
auth_type)
+:type gcp_key_path: str
+:param gcp_scopes: Comma-separated string containing GCP scopes (for 
``gcp`` auth_type)
+:type gcp_scopes: str
+"""
+def __init__(  # pylint: disable=too-many-arguments
+self,
+path: str,
+url: Optional[str] = None,
+auth_type: str = 'token',
+mount_point: str = 'secret',
+token: Optional[str] = None,
+username: Optional[str] = None,
+password: Optional[str] = None,
+role_id: Optional[str] = None,
+secret_id: Optional[str] = None,
+gcp_key_path: Optional[str] = None,
+gcp_scopes: Optional[str] = None,
+**kwargs
+):
+super().__init__()
+self.path = path.rstrip('/')
+self.url = url
+self.auth_type = auth_type
+self.kwargs = kwargs
+self.token = token
+self.username = username
+self.password = password
+self.role_id = role_id
+self.secret_id = secret_id
+self.mount_point = mount_point
+self.gcp_key_path = gcp_key_path
+self.gcp_scopes = gcp_scopes
+self._client: Optional[hvac.Client] = None
+
+def get_client(self) -> hvac.Client:
+"""
+Return an authenticated Hashicorp Vault client
+"""
+if not self._client:
+self._client = hvac.Client(url=self.url, **self.kwargs)
+if self.auth_type == "token":
+self._client.token = self.token
+elif self.auth_type == "ldap":
+self._client.auth.ldap.login(
+username=self.username, password=self.password)
+elif self.auth_type == "userpass":
+self._client.auth_userpass(username=self.username, 
password=self.password)
+elif self.auth_type == 

[GitHub] [airflow] ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support for HashiCorp Vault as Secrets Backend

2020-03-17 Thread GitBox
ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support 
for HashiCorp Vault as Secrets Backend
URL: https://github.com/apache/airflow/pull/7741#discussion_r393993686
 
 

 ##
 File path: airflow/providers/hashicorp/secrets/vault.py
 ##
 @@ -0,0 +1,196 @@
+#
+# 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 connections from Hashicorp Vault
+"""
+from typing import List, Optional
+
+import hvac
+from hvac.exceptions import VaultError
+
+from airflow import AirflowException
+from airflow.models import Connection
+from airflow.secrets import CONN_ENV_PREFIX, BaseSecretsBackend
+from airflow.utils.log.logging_mixin import LoggingMixin
+
+
+class VaultSecrets(BaseSecretsBackend, LoggingMixin):
+"""
+Retrieves Connection object from Hashicorp Vault Secrets
+
+Configurable via ``airflow.cfg`` as follows:
+
+.. code-block:: ini
+
+[secrets]
+backend = airflow.providers.hashicorp.secrets.vault.VaultSecrets
+backend_kwargs = {"path": "airflow", "url": "http://127.0.0.1:8200"}
+
+For example, if your keys are under ``airflow/AIRFLOW_CONN_SMTP_DEFAULT``, 
this would be accessible if you
+provide ``{"path": "airflow"}`` and request conn_id ``smtp_default``.
+
+:param path: Specifies the path of the secret to read.
+:type path: str
+:param url: Base URL for the Vault instance being addressed.
+:type url: str
+:param auth_type: Authentication Type for Vault (one of 'token', 'ldap', 
'userpass', 'approle',
+'github', 'gcp). Default is ``token``.
+:type auth_type: str
+:param mount_point: The "path" the secret engine was mounted on. (Default: 
``secret``)
+:type mount_point: str
+:param token: Authentication token to include in requests sent to Vault.
+(for ``token`` and ``github`` auth_type)
+:type token: str
+:param username: Username for Authentication (for ``ldap`` and 
``userpass`` auth_type)
+:type username: str
+:param password: Password for Authentication (for ``ldap`` and 
``userpass`` auth_type)
+:type password: str
+:param role_id: Role ID for Authentication (for ``approle`` auth_type)
+:type role_id: str
+:param secret_id: Secret ID for Authentication (for ``approle`` auth_type)
+:type secret_id: str
+:param gcp_key_path: Path to GCP Credential JSON file (for ``gcp`` 
auth_type)
+:type gcp_key_path: str
+:param gcp_scopes: Comma-separated string containing GCP scopes (for 
``gcp`` auth_type)
+:type gcp_scopes: str
+"""
+def __init__(  # pylint: disable=too-many-arguments
+self,
+path: str,
+url: Optional[str] = None,
+auth_type: str = 'token',
+mount_point: str = 'secret',
+token: Optional[str] = None,
+username: Optional[str] = None,
+password: Optional[str] = None,
+role_id: Optional[str] = None,
+secret_id: Optional[str] = None,
+gcp_key_path: Optional[str] = None,
+gcp_scopes: Optional[str] = None,
+**kwargs
+):
+super().__init__()
+self.path = path.rstrip('/')
+self.url = url
+self.auth_type = auth_type
+self.kwargs = kwargs
+self.token = token
+self.username = username
+self.password = password
+self.role_id = role_id
+self.secret_id = secret_id
+self.mount_point = mount_point
+self.gcp_key_path = gcp_key_path
+self.gcp_scopes = gcp_scopes
+self._client: Optional[hvac.Client] = None
+
+def get_client(self) -> hvac.Client:
+"""
+Return an authenticated Hashicorp Vault client
+"""
+if not self._client:
+self._client = hvac.Client(url=self.url, **self.kwargs)
+if self.auth_type == "token":
+self._client.token = self.token
+elif self.auth_type == "ldap":
+self._client.auth.ldap.login(
+username=self.username, password=self.password)
+elif self.auth_type == "userpass":
+self._client.auth_userpass(username=self.username, 
password=self.password)
+elif self.auth_type == 

[GitHub] [airflow] ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support for HashiCorp Vault as Secrets Backend

2020-03-17 Thread GitBox
ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support 
for HashiCorp Vault as Secrets Backend
URL: https://github.com/apache/airflow/pull/7741#discussion_r393976739
 
 

 ##
 File path: airflow/providers/hashicorp/secrets/vault.py
 ##
 @@ -0,0 +1,196 @@
+#
+# 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 connections from Hashicorp Vault
+"""
+from typing import List, Optional
+
+import hvac
+from hvac.exceptions import VaultError
+
+from airflow import AirflowException
+from airflow.models import Connection
+from airflow.secrets import CONN_ENV_PREFIX, BaseSecretsBackend
+from airflow.utils.log.logging_mixin import LoggingMixin
+
+
+class VaultSecrets(BaseSecretsBackend, LoggingMixin):
+"""
+Retrieves Connection object from Hashicorp Vault Secrets
+
+Configurable via ``airflow.cfg`` as follows:
+
+.. code-block:: ini
+
+[secrets]
+backend = airflow.providers.hashicorp.secrets.vault.VaultSecrets
+backend_kwargs = {"path": "airflow", "url": "http://127.0.0.1:8200"}
+
+For example, if your keys are under ``airflow/AIRFLOW_CONN_SMTP_DEFAULT``, 
this would be accessible if you
+provide ``{"path": "airflow"}`` and request conn_id ``smtp_default``.
+
+:param path: Specifies the path of the secret to read.
+:type path: str
+:param url: Base URL for the Vault instance being addressed.
+:type url: str
+:param auth_type: Authentication Type for Vault (one of 'token', 'ldap', 
'userpass', 'approle',
+'github', 'gcp). Default is ``token``.
+:type auth_type: str
+:param mount_point: The "path" the secret engine was mounted on. (Default: 
``secret``)
+:type mount_point: str
+:param token: Authentication token to include in requests sent to Vault.
+(for ``token`` and ``github`` auth_type)
+:type token: str
+:param username: Username for Authentication (for ``ldap`` and 
``userpass`` auth_type)
+:type username: str
+:param password: Password for Authentication (for ``ldap`` and 
``userpass`` auth_type)
+:type password: str
+:param role_id: Role ID for Authentication (for ``approle`` auth_type)
+:type role_id: str
+:param secret_id: Secret ID for Authentication (for ``approle`` auth_type)
+:type secret_id: str
+:param gcp_key_path: Path to GCP Credential JSON file (for ``gcp`` 
auth_type)
+:type gcp_key_path: str
+:param gcp_scopes: Comma-separated string containing GCP scopes (for 
``gcp`` auth_type)
+:type gcp_scopes: str
+"""
+def __init__(  # pylint: disable=too-many-arguments
+self,
+path: str,
+url: Optional[str] = None,
+auth_type: str = 'token',
+mount_point: str = 'secret',
+token: Optional[str] = None,
+username: Optional[str] = None,
+password: Optional[str] = None,
+role_id: Optional[str] = None,
+secret_id: Optional[str] = None,
+gcp_key_path: Optional[str] = None,
+gcp_scopes: Optional[str] = None,
+**kwargs
+):
+super().__init__()
+self.path = path.rstrip('/')
+self.url = url
+self.auth_type = auth_type
+self.kwargs = kwargs
+self.token = token
+self.username = username
+self.password = password
+self.role_id = role_id
+self.secret_id = secret_id
+self.mount_point = mount_point
+self.gcp_key_path = gcp_key_path
+self.gcp_scopes = gcp_scopes
+self._client: Optional[hvac.Client] = None
+
+def get_client(self) -> hvac.Client:
+"""
+Return an authenticated Hashicorp Vault client
+"""
+if not self._client:
+self._client = hvac.Client(url=self.url, **self.kwargs)
+if self.auth_type == "token":
+self._client.token = self.token
+elif self.auth_type == "ldap":
+self._client.auth.ldap.login(
+username=self.username, password=self.password)
+elif self.auth_type == "userpass":
+self._client.auth_userpass(username=self.username, 
password=self.password)
+elif self.auth_type == 

[GitHub] [airflow] ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support for HashiCorp Vault as Secrets Backend

2020-03-17 Thread GitBox
ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support 
for HashiCorp Vault as Secrets Backend
URL: https://github.com/apache/airflow/pull/7741#discussion_r393974473
 
 

 ##
 File path: docs/howto/use-alternative-secrets-backend.rst
 ##
 @@ -0,0 +1,130 @@
+ .. 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.
+
+
+Alternative secrets backend
+---
+
+In addition to retrieving connections from environment variables or the 
metastore database, you can enable
+an alternative secrets backend to retrieve connections,
+such as :ref:`AWS SSM Parameter Store `,
+:ref:`Hashicorp Vault Secrets` or you can :ref:`roll 
your own `.
+
+Search path
+^^^
+When looking up a connection, by default Airflow will search environment 
variables first and metastore
+database second.
+
+If you enable an alternative secrets backend, it will be searched first, 
followed by environment variables,
+then metastore.  This search ordering is not configurable.
+
+.. _secrets_backend_configuration:
+
+Configuration
+^
+
+The ``[secrets]`` section has the following options:
+
+.. code-block:: ini
+
+[secrets]
+backend =
+backend_kwargs =
+
+Set ``backend`` to the fully qualified class name of the backend you want to 
enable.
+
+You can provide ``backend_kwargs`` with json and it will be passed as kwargs 
to the ``__init__`` method of
+your secrets backend.
+
+See :ref:`AWS SSM Parameter Store ` for an 
example configuration.
+
+.. _ssm_parameter_store_secrets:
+
+AWS SSM Parameter Store Secrets Backend
+^^^
+
+To enable SSM parameter store, specify 
:py:class:`~airflow.providers.amazon.aws.secrets.ssm.AwsSsmSecretsBackend`
+as the ``backend`` in  ``[secrets]`` section of ``airflow.cfg``.
+
+Here is a sample configuration:
+
+.. code-block:: ini
+
+[secrets]
+backend = airflow.providers.amazon.aws.secrets.ssm.AwsSsmSecretsBackend
+backend_kwargs = {"prefix": "/airflow", "profile_name": "default"}
+
+If you have set your prefix as ``/airflow``, then for a connection id of 
``smtp_default``, you would want to
+store your connection at ``/airflow/AIRFLOW_CONN_SMTP_DEFAULT``.
+
+Optionally you can supply a profile name to reference aws profile, e.g. 
defined in ``~/.aws/config``.
+
+The value of the SSM parameter must be the :ref:`airflow connection URI 
representation ` of the connection object.
+
+.. _hashicorp_vault_secrets:
+
+Hashicorp Vault Secrets Backend
+^^^
+
+To enable Hashicorp vault to retrieve connection, specify 
:py:class:`~airflow.providers.hashicorp.secrets.vault.VaultSecrets`
+as the ``backend`` in  ``[secrets]`` section of ``airflow.cfg``.
+
+Here is a sample configuration:
+
+.. code-block:: ini
+
+[secrets]
+backend = airflow.providers.hashicorp.secrets.vault.VaultSecrets
+backend_kwargs = {"path": "airflow/connections", "url": 
"http://127.0.0.1:8200"}
+
+You can also set and pass values to Vault client by setting environment 
variables. All the
+environment variables listed at 
https://www.vaultproject.io/docs/commands/#environment-variables are supported.
+
+Hence, if you set ``VAULT_ADDR`` environment variable like below, you do not 
need to pass ``url``
+key to ``backend_kwargs``:
+
+.. code-block:: bash
+
+export VAULT_ADDR="http://127.0.0.1:8200;
+
+If you have set your path as ``airflow/connections``, then for a connection id 
of ``smtp_default``, you would want to
+store your secret as:
+
+.. code-block:: bash
+
+vault kv put secret/airflow/connections 
smtp_default=postgresql://airflow:airflow@host:5432/airflow
+
+The value of the Vault key must be the :ref:`airflow connection URI 
representation `
 
 Review comment:
   ```suggestion
   The value of the Vault key must be the :ref:`connection URI representation 
`
   ```


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.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [airflow] ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support for HashiCorp Vault as Secrets Backend

2020-03-17 Thread GitBox
ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support 
for HashiCorp Vault as Secrets Backend
URL: https://github.com/apache/airflow/pull/7741#discussion_r393972573
 
 

 ##
 File path: airflow/providers/hashicorp/secrets/vault.py
 ##
 @@ -0,0 +1,192 @@
+#
+# 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 connections from Hashicorp Vault
+"""
+from typing import List, Optional
+
+import hvac
+from cached_property import cached_property
+from hvac.exceptions import VaultError
+
+from airflow import AirflowException
+from airflow.models import Connection
+from airflow.secrets import BaseSecretsBackend
+from airflow.utils.log.logging_mixin import LoggingMixin
+
+
+class VaultSecrets(BaseSecretsBackend, LoggingMixin):
+"""
+Retrieves Connection object from Hashicorp Vault
+
+Configurable via ``airflow.cfg`` as follows:
+
+.. code-block:: ini
+
+[secrets]
+backend = airflow.providers.hashicorp.secrets.vault.VaultSecrets
+backend_kwargs = {"path": "airflow/connections", "url": 
"http://127.0.0.1:8200"}
+
+For example, if your keys are under ``airflow/connections``, this would be 
accessible if you
+provide ``{"path": "airflow/connections"}`` and request conn_id 
``smtp_default``.
+
+:param path: Specifies the path of the secret to read.
+:type path: str
+:param url: Base URL for the Vault instance being addressed.
+:type url: str
+:param auth_type: Authentication Type for Vault (one of 'token', 'ldap', 
'userpass', 'approle',
+'github', 'gcp). Default is ``token``.
+:type auth_type: str
+:param mount_point: The "path" the secret engine was mounted on. (Default: 
``secret``)
+:type mount_point: str
+:param token: Authentication token to include in requests sent to Vault.
+(for ``token`` and ``github`` auth_type)
+:type token: str
+:param username: Username for Authentication (for ``ldap`` and 
``userpass`` auth_type)
+:type username: str
+:param password: Password for Authentication (for ``ldap`` and 
``userpass`` auth_type)
+:type password: str
+:param role_id: Role ID for Authentication (for ``approle`` auth_type)
+:type role_id: str
+:param secret_id: Secret ID for Authentication (for ``approle`` auth_type)
+:type secret_id: str
+:param gcp_key_path: Path to GCP Credential JSON file (for ``gcp`` 
auth_type)
+:type gcp_key_path: str
+:param gcp_scopes: Comma-separated string containing GCP scopes (for 
``gcp`` auth_type)
+:type gcp_scopes: str
+"""
+def __init__(  # pylint: disable=too-many-arguments
+self,
+path: str,
+url: Optional[str] = None,
+auth_type: str = 'token',
+mount_point: str = 'secret',
+token: Optional[str] = None,
+username: Optional[str] = None,
+password: Optional[str] = None,
+role_id: Optional[str] = None,
+secret_id: Optional[str] = None,
+gcp_key_path: Optional[str] = None,
+gcp_scopes: Optional[str] = None,
+**kwargs
+):
+super().__init__()
 
 Review comment:
   ```suggestion
   super().__init__(**kwrgs)
   ```


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.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [airflow] ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support for HashiCorp Vault as Secrets Backend

2020-03-17 Thread GitBox
ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support 
for HashiCorp Vault as Secrets Backend
URL: https://github.com/apache/airflow/pull/7741#discussion_r393956556
 
 

 ##
 File path: airflow/providers/hashicorp/secrets/vault.py
 ##
 @@ -0,0 +1,192 @@
+#
+# 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 connections from Hashicorp Vault
+"""
+from typing import List, Optional
+
+import hvac
+from cached_property import cached_property
+from hvac.exceptions import VaultError
+
+from airflow import AirflowException
+from airflow.models import Connection
+from airflow.secrets import BaseSecretsBackend
+from airflow.utils.log.logging_mixin import LoggingMixin
+
+
+class VaultSecrets(BaseSecretsBackend, LoggingMixin):
+"""
+Retrieves Connection object from Hashicorp Vault
+
+Configurable via ``airflow.cfg`` as follows:
+
+.. code-block:: ini
+
+[secrets]
+backend = airflow.providers.hashicorp.secrets.vault.VaultSecrets
+backend_kwargs = {"path": "airflow/connections", "url": 
"http://127.0.0.1:8200"}
+
+For example, if your keys are under ``airflow/AIRFLOW_CONN_SMTP_DEFAULT``, 
this would be accessible if you
 
 Review comment:
   This is out of date now I think.


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.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [airflow] ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support for HashiCorp Vault as Secrets Backend

2020-03-17 Thread GitBox
ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support 
for HashiCorp Vault as Secrets Backend
URL: https://github.com/apache/airflow/pull/7741#discussion_r393954612
 
 

 ##
 File path: airflow/providers/hashicorp/secrets/vault.py
 ##
 @@ -0,0 +1,196 @@
+#
+# 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 connections from Hashicorp Vault
+"""
+from typing import List, Optional
+
+import hvac
+from hvac.exceptions import VaultError
+
+from airflow import AirflowException
+from airflow.models import Connection
+from airflow.secrets import CONN_ENV_PREFIX, BaseSecretsBackend
+from airflow.utils.log.logging_mixin import LoggingMixin
+
+
+class VaultSecrets(BaseSecretsBackend, LoggingMixin):
+"""
+Retrieves Connection object from Hashicorp Vault Secrets
+
+Configurable via ``airflow.cfg`` as follows:
+
+.. code-block:: ini
+
+[secrets]
+backend = airflow.providers.hashicorp.secrets.vault.VaultSecrets
+backend_kwargs = {"path": "airflow", "url": "http://127.0.0.1:8200"}
+
+For example, if your keys are under ``airflow/AIRFLOW_CONN_SMTP_DEFAULT``, 
this would be accessible if you
+provide ``{"path": "airflow"}`` and request conn_id ``smtp_default``.
+
+:param path: Specifies the path of the secret to read.
+:type path: str
+:param url: Base URL for the Vault instance being addressed.
+:type url: str
+:param auth_type: Authentication Type for Vault (one of 'token', 'ldap', 
'userpass', 'approle',
+'github', 'gcp). Default is ``token``.
+:type auth_type: str
+:param mount_point: The "path" the secret engine was mounted on. (Default: 
``secret``)
+:type mount_point: str
+:param token: Authentication token to include in requests sent to Vault.
+(for ``token`` and ``github`` auth_type)
+:type token: str
+:param username: Username for Authentication (for ``ldap`` and 
``userpass`` auth_type)
+:type username: str
+:param password: Password for Authentication (for ``ldap`` and 
``userpass`` auth_type)
+:type password: str
+:param role_id: Role ID for Authentication (for ``approle`` auth_type)
+:type role_id: str
+:param secret_id: Secret ID for Authentication (for ``approle`` auth_type)
+:type secret_id: str
+:param gcp_key_path: Path to GCP Credential JSON file (for ``gcp`` 
auth_type)
+:type gcp_key_path: str
+:param gcp_scopes: Comma-separated string containing GCP scopes (for 
``gcp`` auth_type)
+:type gcp_scopes: str
+"""
+def __init__(  # pylint: disable=too-many-arguments
+self,
+path: str,
+url: Optional[str] = None,
+auth_type: str = 'token',
+mount_point: str = 'secret',
+token: Optional[str] = None,
+username: Optional[str] = None,
+password: Optional[str] = None,
+role_id: Optional[str] = None,
+secret_id: Optional[str] = None,
+gcp_key_path: Optional[str] = None,
+gcp_scopes: Optional[str] = None,
+**kwargs
+):
+super().__init__()
+self.path = path.rstrip('/')
+self.url = url
+self.auth_type = auth_type
+self.kwargs = kwargs
+self.token = token
+self.username = username
+self.password = password
+self.role_id = role_id
+self.secret_id = secret_id
+self.mount_point = mount_point
+self.gcp_key_path = gcp_key_path
+self.gcp_scopes = gcp_scopes
+self._client: Optional[hvac.Client] = None
+
+def get_client(self) -> hvac.Client:
+"""
+Return an authenticated Hashicorp Vault client
+"""
+if not self._client:
+self._client = hvac.Client(url=self.url, **self.kwargs)
+if self.auth_type == "token":
+self._client.token = self.token
+elif self.auth_type == "ldap":
+self._client.auth.ldap.login(
+username=self.username, password=self.password)
+elif self.auth_type == "userpass":
+self._client.auth_userpass(username=self.username, 
password=self.password)
+elif self.auth_type == 

[GitHub] [airflow] ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support for HashiCorp Vault as Secrets Backend

2020-03-17 Thread GitBox
ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support 
for HashiCorp Vault as Secrets Backend
URL: https://github.com/apache/airflow/pull/7741#discussion_r393604138
 
 

 ##
 File path: airflow/providers/hashicorp/secrets/vault.py
 ##
 @@ -0,0 +1,196 @@
+#
+# 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 connections from Hashicorp Vault
+"""
+from typing import List, Optional
+
+import hvac
+from hvac.exceptions import VaultError
+
+from airflow import AirflowException
+from airflow.models import Connection
+from airflow.secrets import CONN_ENV_PREFIX, BaseSecretsBackend
+from airflow.utils.log.logging_mixin import LoggingMixin
+
+
+class VaultSecrets(BaseSecretsBackend, LoggingMixin):
+"""
+Retrieves Connection object from Hashicorp Vault Secrets
+
+Configurable via ``airflow.cfg`` as follows:
+
+.. code-block:: ini
+
+[secrets]
+backend = airflow.providers.hashicorp.secrets.vault.VaultSecrets
+backend_kwargs = {"path": "airflow", "url": "http://127.0.0.1:8200"}
+
+For example, if your keys are under ``airflow/AIRFLOW_CONN_SMTP_DEFAULT``, 
this would be accessible if you
+provide ``{"path": "airflow"}`` and request conn_id ``smtp_default``.
+
+:param path: Specifies the path of the secret to read.
+:type path: str
+:param url: Base URL for the Vault instance being addressed.
+:type url: str
+:param auth_type: Authentication Type for Vault (one of 'token', 'ldap', 
'userpass', 'approle',
+'github', 'gcp). Default is ``token``.
+:type auth_type: str
+:param mount_point: The "path" the secret engine was mounted on. (Default: 
``secret``)
+:type mount_point: str
+:param token: Authentication token to include in requests sent to Vault.
+(for ``token`` and ``github`` auth_type)
+:type token: str
+:param username: Username for Authentication (for ``ldap`` and 
``userpass`` auth_type)
+:type username: str
+:param password: Password for Authentication (for ``ldap`` and 
``userpass`` auth_type)
+:type password: str
+:param role_id: Role ID for Authentication (for ``approle`` auth_type)
+:type role_id: str
+:param secret_id: Secret ID for Authentication (for ``approle`` auth_type)
+:type secret_id: str
+:param gcp_key_path: Path to GCP Credential JSON file (for ``gcp`` 
auth_type)
+:type gcp_key_path: str
+:param gcp_scopes: Comma-separated string containing GCP scopes (for 
``gcp`` auth_type)
+:type gcp_scopes: str
+"""
+def __init__(  # pylint: disable=too-many-arguments
+self,
+path: str,
+url: Optional[str] = None,
+auth_type: str = 'token',
+mount_point: str = 'secret',
+token: Optional[str] = None,
+username: Optional[str] = None,
+password: Optional[str] = None,
+role_id: Optional[str] = None,
+secret_id: Optional[str] = None,
+gcp_key_path: Optional[str] = None,
+gcp_scopes: Optional[str] = None,
+**kwargs
+):
+super().__init__()
+self.path = path.rstrip('/')
+self.url = url
+self.auth_type = auth_type
+self.kwargs = kwargs
+self.token = token
+self.username = username
+self.password = password
+self.role_id = role_id
+self.secret_id = secret_id
+self.mount_point = mount_point
+self.gcp_key_path = gcp_key_path
+self.gcp_scopes = gcp_scopes
+self._client: Optional[hvac.Client] = None
+
+def get_client(self) -> hvac.Client:
+"""
+Return an authenticated Hashicorp Vault client
+"""
+if not self._client:
+self._client = hvac.Client(url=self.url, **self.kwargs)
+if self.auth_type == "token":
+self._client.token = self.token
+elif self.auth_type == "ldap":
+self._client.auth.ldap.login(
+username=self.username, password=self.password)
+elif self.auth_type == "userpass":
+self._client.auth_userpass(username=self.username, 
password=self.password)
+elif self.auth_type == 

[GitHub] [airflow] ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support for HashiCorp Vault as Secrets Backend

2020-03-17 Thread GitBox
ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support 
for HashiCorp Vault as Secrets Backend
URL: https://github.com/apache/airflow/pull/7741#discussion_r393603600
 
 

 ##
 File path: airflow/providers/hashicorp/secrets/vault.py
 ##
 @@ -0,0 +1,196 @@
+#
+# 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 connections from Hashicorp Vault
+"""
+from typing import List, Optional
+
+import hvac
+from hvac.exceptions import VaultError
+
+from airflow import AirflowException
+from airflow.models import Connection
+from airflow.secrets import CONN_ENV_PREFIX, BaseSecretsBackend
+from airflow.utils.log.logging_mixin import LoggingMixin
+
+
+class VaultSecrets(BaseSecretsBackend, LoggingMixin):
+"""
+Retrieves Connection object from Hashicorp Vault Secrets
 
 Review comment:
   ```suggestion
   Retrieves Connection object from Hashicorp Vault
   ```


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.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [airflow] ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support for HashiCorp Vault as Secrets Backend

2020-03-17 Thread GitBox
ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support 
for HashiCorp Vault as Secrets Backend
URL: https://github.com/apache/airflow/pull/7741#discussion_r393603370
 
 

 ##
 File path: tests/providers/hashicorp/secrets/test_vault.py
 ##
 @@ -0,0 +1,118 @@
+# 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.
+
+from unittest import TestCase, mock
+
+from hvac.exceptions import VaultError
+
+from airflow.providers.hashicorp.secrets.vault import VaultSecrets
+from airflow.secrets import get_connections
+
+
+class TestVaultSecrets(TestCase):
+
+@mock.patch("airflow.providers.hashicorp.secrets.vault.hvac")
+def test_get_conn_uri(self, mock_hvac):
+mock_client = mock.MagicMock()
+mock_hvac.Client.return_value = mock_client
+mock_client.secrets.kv.v2.read_secret_version.return_value = {
+'request_id': '94011e25-f8dc-ec29-221b-1f9c1d9ad2ae',
+'lease_id': '',
+'renewable': False,
+'lease_duration': 0,
+'data': {
+'data': {'AIRFLOW_CONN_TEST_POSTGRES': 
'postgresql://airflow:airflow@host:5432/airflow'},
+'metadata': {'created_time': '2020-03-16T21:01:43.331126Z',
+ 'deletion_time': '',
+ 'destroyed': False,
+ 'version': 1}},
+'wrap_info': None,
+'warnings': None,
+'auth': None
+}
+
+kwargs = {
+"path": "test_path",
+"auth_type": "token",
+"url": "http://127.0.0.1:8200;,
+"token": "s.7AU0I51yv1Q1lxOIg1F3ZRAS"
+}
+
+test_client = VaultSecrets(**kwargs)
+returned_uri = test_client.get_conn_uri(conn_id="test_postgres")
+self.assertEqual('postgresql://airflow:airflow@host:5432/airflow', 
returned_uri)
+
+@mock.patch.dict('os.environ', {
+'AIRFLOW_CONN_TEST_MYSQL': 'mysql://airflow:airflow@host:5432/airflow',
+})
+@mock.patch("airflow.providers.hashicorp.secrets.vault.hvac")
+def test_get_conn_uri_non_existent_key(self, mock_hvac):
+"""
+Test that if the key with connection ID is not present in Vault, 
VaultClient.get_connections
+should return None and fallback to the environment variable if it is 
set
+"""
+mock_client = mock.MagicMock()
+mock_hvac.Client.return_value = mock_client
+# Response does not contain the requested key
+mock_client.secrets.kv.v2.read_secret_version.return_value = {
+'request_id': '94011e25-f8dc-ec29-221b-1f9c1d9ad2ae',
+'lease_id': '',
+'renewable': False,
+'lease_duration': 0,
+'data': {
+'data': {'AIRFLOW_CONN_TEST_POSTGRES': 
'postgresql://airflow:airflow@host:5432/airflow'},
+'metadata': {'created_time': '2020-03-16T21:01:43.331126Z',
+ 'deletion_time': '',
+ 'destroyed': False,
+ 'version': 1}},
+'wrap_info': None,
+'warnings': None,
+'auth': None
+}
+
+kwargs = {
+"path": "test_path",
+"auth_type": "token",
+"url": "http://127.0.0.1:8200;,
+"token": "s.7AU0I51yv1Q1lxOIg1F3ZRAS"
+}
+
+test_client = VaultSecrets(**kwargs)
+self.assertIsNone(test_client.get_conn_uri(conn_id="test_mysql"))
+self.assertIsNone(test_client.get_connections(conn_id="test_mysql"))
+
+# Fallback to connection defined in Environment Variable
 
 Review comment:
   Isn't this test (re)testing the base secrets interface?


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.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [airflow] ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support for HashiCorp Vault as Secrets Backend

2020-03-17 Thread GitBox
ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support 
for HashiCorp Vault as Secrets Backend
URL: https://github.com/apache/airflow/pull/7741#discussion_r393602738
 
 

 ##
 File path: setup.py
 ##
 @@ -551,6 +554,7 @@ def do_setup():
 'grpc': grpc,
 'hdfs': hdfs,
 'hive': hive,
+'hvac': hvac,
 
 Review comment:
   This name isn't very descriptive if you don't already know what the module 
acronym does (and I can't see any docs) about extras? How about calling this 
extra `hasicorp`?


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.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [airflow] ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support for HashiCorp Vault as Secrets Backend

2020-03-17 Thread GitBox
ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support 
for HashiCorp Vault as Secrets Backend
URL: https://github.com/apache/airflow/pull/7741#discussion_r393601898
 
 

 ##
 File path: docs/howto/use-alternative-secrets-backend.rst
 ##
 @@ -0,0 +1,130 @@
+ .. 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.
+
+
+Alternative secrets backend
+---
+
+In addition to retrieving connections from environment variables or the 
metastore database, you can enable
+an alternative secrets backend to retrieve connections,
+such as :ref:`AWS SSM Parameter Store `,
+:ref:`Hashicorp Vault Secrets` or you can :ref:`roll 
your own `.
+
+Search path
+^^^
+When looking up a connection, by default Airflow will search environment 
variables first and metastore
+database second.
+
+If you enable an alternative secrets backend, it will be searched first, 
followed by environment variables,
+then metastore.  This search ordering is not configurable.
+
+.. _secrets_backend_configuration:
+
+Configuration
+^
+
+The ``[secrets]`` section has the following options:
+
+.. code-block:: ini
+
+[secrets]
+backend =
+backend_kwargs =
+
+Set ``backend`` to the fully qualified class name of the backend you want to 
enable.
+
+You can provide ``backend_kwargs`` with json and it will be passed as kwargs 
to the ``__init__`` method of
+your secrets backend.
+
+See :ref:`AWS SSM Parameter Store ` for an 
example configuration.
+
+.. _ssm_parameter_store_secrets:
+
+AWS SSM Parameter Store Secrets Backend
+^^^
+
+To enable SSM parameter store, specify 
:py:class:`~airflow.providers.amazon.aws.secrets.ssm.AwsSsmSecretsBackend`
+as the ``backend`` in  ``[secrets]`` section of ``airflow.cfg``.
+
+Here is a sample configuration:
+
+.. code-block:: ini
+
+[secrets]
+backend = airflow.providers.amazon.aws.secrets.ssm.AwsSsmSecretsBackend
+backend_kwargs = {"prefix": "/airflow", "profile_name": "default"}
+
+If you have set your prefix as ``/airflow``, then for a connection id of 
``smtp_default``, you would want to
+store your connection at ``/airflow/AIRFLOW_CONN_SMTP_DEFAULT``.
+
+Optionally you can supply a profile name to reference aws profile, e.g. 
defined in ``~/.aws/config``.
+
+The value of the SSM parameter must be the :ref:`airflow connection URI 
representation ` of the connection object.
+
+.. _hashicorp_vault_secrets:
+
+Hashicorp Vault Secrets Backend
+^^^
+
+To enable Hashicorp vault to retrieve connection, specify 
:py:class:`~airflow.providers.hashicorp.secrets.vault.VaultSecrets`
+as the ``backend`` in  ``[secrets]`` section of ``airflow.cfg``.
+
+Here is a sample configuration:
+
+.. code-block:: ini
+
+[secrets]
+backend = airflow.providers.hashicorp.secrets.vault.VaultSecrets
+backend_kwargs = {"path": "airflow", "url": "http://127.0.0.1:8200"}
+
+You can also set and pass values to Vault client by setting environment 
variables. All the
+environment variables listed at 
https://www.vaultproject.io/docs/commands/#environment-variables are supported.
+
+Hence, if you set ``VAULT_ADDR`` environment variable like below, you do not 
need to pass ``url``
 
 Review comment:
   This is normal for vault I guess? (i.e. no `AIRFLOW_` prefix here because 
this is expected?)


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.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [airflow] ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support for HashiCorp Vault as Secrets Backend

2020-03-17 Thread GitBox
ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support 
for HashiCorp Vault as Secrets Backend
URL: https://github.com/apache/airflow/pull/7741#discussion_r393601194
 
 

 ##
 File path: airflow/secrets/__init__.py
 ##
 @@ -50,7 +51,7 @@ def __init__(self, **kwargs):
 pass
 
 @abstractmethod
-def get_connections(self, conn_id) -> List[Connection]:
+def get_connections(self, conn_id) -> Optional[List[Connection]]:
 
 Review comment:
   I don't think this should be changed -- return an empty list instead of none?


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.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [airflow] ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support for HashiCorp Vault as Secrets Backend

2020-03-17 Thread GitBox
ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support 
for HashiCorp Vault as Secrets Backend
URL: https://github.com/apache/airflow/pull/7741#discussion_r393600514
 
 

 ##
 File path: airflow/providers/hashicorp/secrets/vault.py
 ##
 @@ -0,0 +1,196 @@
+#
+# 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 connections from Hashicorp Vault
+"""
+from typing import List, Optional
+
+import hvac
+from hvac.exceptions import VaultError
+
+from airflow import AirflowException
+from airflow.models import Connection
+from airflow.secrets import CONN_ENV_PREFIX, BaseSecretsBackend
+from airflow.utils.log.logging_mixin import LoggingMixin
+
+
+class VaultSecrets(BaseSecretsBackend, LoggingMixin):
+"""
+Retrieves Connection object from Hashicorp Vault Secrets
+
+Configurable via ``airflow.cfg`` as follows:
+
+.. code-block:: ini
+
+[secrets]
+backend = airflow.providers.hashicorp.secrets.vault.VaultSecrets
+backend_kwargs = {"path": "airflow", "url": "http://127.0.0.1:8200"}
+
+For example, if your keys are under ``airflow/AIRFLOW_CONN_SMTP_DEFAULT``, 
this would be accessible if you
+provide ``{"path": "airflow"}`` and request conn_id ``smtp_default``.
+
+:param path: Specifies the path of the secret to read.
+:type path: str
+:param url: Base URL for the Vault instance being addressed.
+:type url: str
+:param auth_type: Authentication Type for Vault (one of 'token', 'ldap', 
'userpass', 'approle',
+'github', 'gcp). Default is ``token``.
+:type auth_type: str
+:param mount_point: The "path" the secret engine was mounted on. (Default: 
``secret``)
+:type mount_point: str
+:param token: Authentication token to include in requests sent to Vault.
+(for ``token`` and ``github`` auth_type)
+:type token: str
+:param username: Username for Authentication (for ``ldap`` and 
``userpass`` auth_type)
+:type username: str
+:param password: Password for Authentication (for ``ldap`` and 
``userpass`` auth_type)
+:type password: str
+:param role_id: Role ID for Authentication (for ``approle`` auth_type)
+:type role_id: str
+:param secret_id: Secret ID for Authentication (for ``approle`` auth_type)
+:type secret_id: str
+:param gcp_key_path: Path to GCP Credential JSON file (for ``gcp`` 
auth_type)
+:type gcp_key_path: str
+:param gcp_scopes: Comma-separated string containing GCP scopes (for 
``gcp`` auth_type)
+:type gcp_scopes: str
+"""
+def __init__(  # pylint: disable=too-many-arguments
+self,
+path: str,
+url: Optional[str] = None,
+auth_type: str = 'token',
+mount_point: str = 'secret',
+token: Optional[str] = None,
+username: Optional[str] = None,
+password: Optional[str] = None,
+role_id: Optional[str] = None,
+secret_id: Optional[str] = None,
+gcp_key_path: Optional[str] = None,
+gcp_scopes: Optional[str] = None,
+**kwargs
+):
+super().__init__()
+self.path = path.rstrip('/')
+self.url = url
+self.auth_type = auth_type
+self.kwargs = kwargs
+self.token = token
+self.username = username
+self.password = password
+self.role_id = role_id
+self.secret_id = secret_id
+self.mount_point = mount_point
+self.gcp_key_path = gcp_key_path
+self.gcp_scopes = gcp_scopes
+self._client: Optional[hvac.Client] = None
+
+def get_client(self) -> hvac.Client:
 
 Review comment:
   ```suggestion
   @cached_property
   def client(self) -> hvac.Client:
   ```
   
   And then we don't need `self._client` or the `if` in this fn.


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.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services


[GitHub] [airflow] ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support for HashiCorp Vault as Secrets Backend

2020-03-17 Thread GitBox
ashb commented on a change in pull request #7741: [AIRFLOW-7076] Add support 
for HashiCorp Vault as Secrets Backend
URL: https://github.com/apache/airflow/pull/7741#discussion_r393509505
 
 

 ##
 File path: airflow/providers/hashicorp/secrets/vault.py
 ##
 @@ -0,0 +1,197 @@
+#
+# 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 connections from Hashicorp Vault
+"""
+from typing import List, Optional
+
+import hvac
+from hvac.exceptions import VaultError
+
+from airflow import AirflowException
+from airflow.models import Connection
+from airflow.secrets import CONN_ENV_PREFIX, BaseSecretsBackend
+from airflow.utils.log.logging_mixin import LoggingMixin
+
+
+class VaultSecrets(BaseSecretsBackend, LoggingMixin):
+"""
+Retrieves Connection object from Hashicorp Vault Secrets
+
+Configurable via ``airflow.cfg`` as follows:
+
+.. code-block:: ini
+
+[secrets]
+backend = airflow.providers.hashicorp.secrets.vault.VaultSecrets
+backend_kwargs = {"path": "airflow", "url": "http://127.0.0.1:8200"}
+
+For example, if your keys are under ``airflow/AIRFLOW_CONN_SMTP_DEFAULT``, 
this would be accessible if you
+provide ``{"path": "airflow"}`` and request conn_id ``smtp_default``.
+
+:param path: Specifies the path of the secret to read.
+:type path: str
 
 Review comment:
   Yes. These are for rendered docs - sphinx doesn't currently pick up type 
hints sadly


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.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services