This is an automated email from the ASF dual-hosted git repository.

uranusjr pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new 24a53fb  Add config to warn public deployment exposure in UI (#18557)
24a53fb is described below

commit 24a53fb6476a3f671859451049407ba2b8d931c8
Author: Shakaib Khan <[email protected]>
AuthorDate: Fri Dec 24 05:24:31 2021 -0500

    Add config to warn public deployment exposure in UI (#18557)
    
    Co-authored-by: eladkal <[email protected]>
    Co-authored-by: Shakaib Khan <[email protected]>
    Co-authored-by: Kaxil Naik <[email protected]>
---
 airflow/config_templates/config.yml          |  7 +++++++
 airflow/config_templates/default_airflow.cfg |  3 +++
 airflow/www/views.py                         | 25 ++++++++++++++++++++++++-
 docs/apache-airflow/security/webserver.rst   | 11 +++++++++++
 tests/www/views/test_views_base.py           |  2 +-
 tests/www/views/test_views_robots.py         | 13 +++++++++++++
 6 files changed, 59 insertions(+), 2 deletions(-)

diff --git a/airflow/config_templates/config.yml 
b/airflow/config_templates/config.yml
index d0b9730..f929e73 100644
--- a/airflow/config_templates/config.yml
+++ b/airflow/config_templates/config.yml
@@ -1303,6 +1303,13 @@
       type: integer
       example: ~
       default: "3"
+    - name: warn_deployment_exposure
+      description: |
+        Boolean for displaying warning for publicly viewable deployment
+      version_added: 2.3.0
+      type: boolean
+      example: ~
+      default: "True"
 
 - name: email
   description: |
diff --git a/airflow/config_templates/default_airflow.cfg 
b/airflow/config_templates/default_airflow.cfg
index 496616b..f81312b 100644
--- a/airflow/config_templates/default_airflow.cfg
+++ b/airflow/config_templates/default_airflow.cfg
@@ -655,6 +655,9 @@ session_lifetime_minutes = 43200
 # when auto-refresh is turned on
 auto_refresh_interval = 3
 
+# Boolean for displaying warning for publicly viewable deployment
+warn_deployment_exposure = True
+
 [email]
 
 # Configuration email backend and whether to
diff --git a/airflow/www/views.py b/airflow/www/views.py
index f018a40..c5d9d23 100644
--- a/airflow/www/views.py
+++ b/airflow/www/views.py
@@ -120,7 +120,7 @@ from airflow.utils.log.log_reader import TaskLogReader
 from airflow.utils.session import create_session, provide_session
 from airflow.utils.state import State
 from airflow.utils.strings import to_boolean
-from airflow.utils.timezone import td_format
+from airflow.utils.timezone import td_format, utcnow
 from airflow.version import version
 from airflow.www import auth, utils as wwwutils
 from airflow.www.decorators import action_logging, gzipped
@@ -788,6 +788,29 @@ class Airflow(AirflowBaseView):
                 # Second segment is a version marker that we don't need to 
show.
                 yield segments[2], table_name
 
+        if (
+            permissions.ACTION_CAN_ACCESS_MENU,
+            permissions.RESOURCE_ADMIN_MENU,
+        ) in user_permissions and conf.getboolean("webserver", 
"warn_deployment_exposure"):
+            robots_file_access_count = (
+                session.query(Log)
+                .filter(Log.event == "robots")
+                .filter(Log.dttm > (utcnow() - timedelta(days=7)))
+                .count()
+            )
+            if robots_file_access_count > 0:
+                flash(
+                    Markup(
+                        'Recent requests have been made to /robots.txt. '
+                        'This indicates that this deployment may be accessible 
to the public internet. '
+                        'This warning can be disabled by setting 
webserver.warn_deployment_exposure=False in '
+                        'airflow.cfg. Read more about web deployment security 
<a href='
+                        f'"{get_docs_url("security/webserver.html")}">'
+                        'here</a>'
+                    ),
+                    "warning",
+                )
+
         return self.render_template(
             'airflow/dags.html',
             dags=dags,
diff --git a/docs/apache-airflow/security/webserver.rst 
b/docs/apache-airflow/security/webserver.rst
index f168faa..91a06ad 100644
--- a/docs/apache-airflow/security/webserver.rst
+++ b/docs/apache-airflow/security/webserver.rst
@@ -31,6 +31,17 @@ set the below:
     [webserver]
     x_frame_enabled = False
 
+Disable Deployment Exposure Warning
+---------------------------------------
+
+Airflow warns when recent requests are made to ``/robot.txt``. To disable this 
warning set ``warn_deployment_exposure`` to
+``False`` as below:
+
+.. code-block:: ini
+
+    [webserver]
+    warn_deployment_exposure = False
+
 Sensitive Variable fields
 -------------------------
 
diff --git a/tests/www/views/test_views_base.py 
b/tests/www/views/test_views_base.py
index cc99682..5759369 100644
--- a/tests/www/views/test_views_base.py
+++ b/tests/www/views/test_views_base.py
@@ -30,7 +30,7 @@ from tests.test_utils.www import check_content_in_response, 
check_content_not_in
 
 
 def test_index(admin_client):
-    with assert_queries_count(49):
+    with assert_queries_count(50):
         resp = admin_client.get('/', follow_redirects=True)
     check_content_in_response('DAGs', resp)
 
diff --git a/tests/www/views/test_views_robots.py 
b/tests/www/views/test_views_robots.py
index e9fa986..232bfe0 100644
--- a/tests/www/views/test_views_robots.py
+++ b/tests/www/views/test_views_robots.py
@@ -14,8 +14,21 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
+from tests.test_utils.config import conf_vars
 
 
 def test_robots(viewer_client):
     resp = viewer_client.get('/robots.txt', follow_redirects=True)
     assert resp.data.decode('utf-8') == "User-agent: *\nDisallow: /\n"
+
+
+def test_deployment_warning_config(admin_client):
+    warn_text = "webserver.warn_deployment_exposure"
+    admin_client.get('/robots.txt', follow_redirects=True)
+    resp = admin_client.get('', follow_redirects=True)
+    assert warn_text in resp.data.decode('utf-8')
+
+    with conf_vars({('webserver', 'warn_deployment_exposure'): 'False'}):
+        admin_client.get('/robots.txt', follow_redirects=True)
+        resp = admin_client.get('/robots.txt', follow_redirects=True)
+        assert warn_text not in resp.data.decode('utf-8')

Reply via email to