Skip to content

Commit 5e35926

Browse files
committed
Remove permissions to read Configurations for User and Viewer roles (#14067)
Only `Admin` or `Op` roles should have permissions to view Configurations. Previously, Users with `User` or `Viewer` role were able to get/view configurations using the REST API or in the Webserver. From Airflow 2.0.1, only users with `Admin` or `Op` role would be able to get/view Configurations. (cherry picked from commit 3909232)
1 parent 51cd910 commit 5e35926

File tree

5 files changed

+93
-3
lines changed

5 files changed

+93
-3
lines changed

UPDATING.md

+11
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,17 @@ https://developers.google.com/style/inclusive-documentation
6868
6969
-->
7070

71+
### Permission to view Airflow Configurations has been removed from `User` and `Viewer` role
72+
73+
Previously, Users with `User` or `Viewer` role were able to get/view configurations using
74+
the REST API or in the Webserver. From Airflow 2.0.1, only users with `Admin` or `Op` role would be able
75+
to get/view Configurations.
76+
77+
To allow users with other roles to view configuration, add `can read on Configurations` permissions to that role.
78+
79+
Note that if `[webserver] expose_config` is set to `False`, the API will throw a `403` response even if
80+
the user has role with `can read on Configurations` permission.
81+
7182
### Default `[celery] worker_concurrency` is changed to `16`
7283

7384
The default value for `[celery] worker_concurrency` was `16` for Airflow <2.0.0.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#
2+
# Licensed to the Apache Software Foundation (ASF) under one
3+
# or more contributor license agreements. See the NOTICE file
4+
# distributed with this work for additional information
5+
# regarding copyright ownership. The ASF licenses this file
6+
# to you under the Apache License, Version 2.0 (the
7+
# "License"); you may not use this file except in compliance
8+
# with the License. You may obtain a copy of the License at
9+
#
10+
# http://www.apache.org/licenses/LICENSE-2.0
11+
#
12+
# Unless required by applicable law or agreed to in writing,
13+
# software distributed under the License is distributed on an
14+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
# KIND, either express or implied. See the License for the
16+
# specific language governing permissions and limitations
17+
# under the License.
18+
19+
"""Remove can_read permission on config resource for User and Viewer role
20+
21+
Revision ID: 82b7c48c147f
22+
Revises: 449b4072c2da
23+
Create Date: 2021-02-04 12:45:58.138224
24+
25+
"""
26+
27+
from airflow.security import permissions
28+
from airflow.www.app import create_app
29+
30+
# revision identifiers, used by Alembic.
31+
revision = '82b7c48c147f'
32+
down_revision = '449b4072c2da'
33+
branch_labels = None
34+
depends_on = None
35+
36+
37+
def upgrade():
38+
"""Remove can_read permission on config resource for User and Viewer role"""
39+
appbuilder = create_app(config={'FAB_UPDATE_PERMS': False}).appbuilder
40+
roles_to_modify = [role for role in appbuilder.sm.get_all_roles() if role.name in ["User", "Viewer"]]
41+
can_read_on_config_perm = appbuilder.sm.find_permission_view_menu(
42+
permissions.ACTION_CAN_READ, permissions.RESOURCE_CONFIG
43+
)
44+
45+
for role in roles_to_modify:
46+
if appbuilder.sm.exist_permission_on_roles(
47+
permissions.RESOURCE_CONFIG, permissions.ACTION_CAN_READ, [role.id]
48+
):
49+
appbuilder.sm.del_permission_role(role, can_read_on_config_perm)
50+
51+
52+
def downgrade():
53+
"""Add can_read permission on config resource for User and Viewer role"""
54+
appbuilder = create_app(config={'FAB_UPDATE_PERMS': False}).appbuilder
55+
roles_to_modify = [role for role in appbuilder.sm.get_all_roles() if role.name in ["User", "Viewer"]]
56+
can_read_on_config_perm = appbuilder.sm.find_permission_view_menu(
57+
permissions.ACTION_CAN_READ, permissions.RESOURCE_CONFIG
58+
)
59+
60+
for role in roles_to_modify:
61+
if not appbuilder.sm.exist_permission_on_roles(
62+
permissions.RESOURCE_CONFIG, permissions.ACTION_CAN_READ, [role.id]
63+
):
64+
appbuilder.sm.add_permission_role(role, can_read_on_config_perm)

airflow/www/security.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ class AirflowSecurityManager(SecurityManager, LoggingMixin): # pylint: disable=
5252

5353
# [START security_viewer_perms]
5454
VIEWER_PERMISSIONS = [
55-
(permissions.ACTION_CAN_READ, permissions.RESOURCE_CONFIG),
5655
(permissions.ACTION_CAN_READ, permissions.RESOURCE_DAG),
5756
(permissions.ACTION_CAN_READ, permissions.RESOURCE_DAG_CODE),
5857
(permissions.ACTION_CAN_READ, permissions.RESOURCE_DAG_RUN),
@@ -103,6 +102,7 @@ class AirflowSecurityManager(SecurityManager, LoggingMixin): # pylint: disable=
103102

104103
# [START security_op_perms]
105104
OP_PERMISSIONS = [
105+
(permissions.ACTION_CAN_READ, permissions.RESOURCE_CONFIG),
106106
(permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_ADMIN_MENU),
107107
(permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_CONNECTION),
108108
(permissions.ACTION_CAN_ACCESS_MENU, permissions.RESOURCE_POOL),

docs/apache-airflow/security/access-control.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ Stable API Permissions
138138
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
139139
Endpoint Method Permissions Minimum Role
140140
================================================================================== ====== ================================================================= ============
141-
/config GET Configurations.can_read Viewer
141+
/config GET Configurations.can_read Op
142142
/connections GET Connections.can_read Op
143143
/connections POST Connections.can_create Op
144144
/connections/{connection_id} DELETE Connections.can_delete Op

tests/www/test_security.py

+16-1
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,6 @@ def test_get_user_roles(self):
254254

255255
def test_get_user_roles_for_anonymous_user(self):
256256
viewer_role_perms = {
257-
(permissions.ACTION_CAN_READ, permissions.RESOURCE_CONFIG),
258257
(permissions.ACTION_CAN_READ, permissions.RESOURCE_DAG),
259258
(permissions.ACTION_CAN_READ, permissions.RESOURCE_DAG_CODE),
260259
(permissions.ACTION_CAN_READ, permissions.RESOURCE_DAG_RUN),
@@ -527,3 +526,19 @@ def test_override_role_vm(self):
527526
test_security_manager = MockSecurityManager(appbuilder=self.appbuilder)
528527
assert len(test_security_manager.VIEWER_VMS) == 1
529528
assert test_security_manager.VIEWER_VMS == {'Airflow'}
529+
530+
def test_correct_roles_have_perms_to_read_config(self):
531+
roles_to_check = self.security_manager.get_all_roles()
532+
assert len(roles_to_check) >= 5
533+
for role in roles_to_check:
534+
if role.name in ["Admin", "Op"]:
535+
assert self.security_manager.exist_permission_on_roles(
536+
permissions.RESOURCE_CONFIG, permissions.ACTION_CAN_READ, [role.id]
537+
)
538+
else:
539+
assert not self.security_manager.exist_permission_on_roles(
540+
permissions.RESOURCE_CONFIG, permissions.ACTION_CAN_READ, [role.id]
541+
), (
542+
f"{role.name} should not have {permissions.ACTION_CAN_READ} "
543+
f"on {permissions.RESOURCE_CONFIG}"
544+
)

0 commit comments

Comments
 (0)