Skip to content

Commit a20d640

Browse files
committed
fix linting
1 parent 9e7f111 commit a20d640

File tree

3 files changed

+96
-93
lines changed

3 files changed

+96
-93
lines changed

superset/Dockerfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ RUN microdnf update \
1818
rm -rf /var/cache/yum
1919

2020
RUN pip install \
21+
--no-cache-dir \
22+
--upgrade \
2123
poetry \
2224
pytest
2325

superset/stackable/opa-authorizer/opa_authorizer/opa_manager.py

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -17,26 +17,24 @@ class OpaSupersetSecurityManager(SupersetSecurityManager):
1717
"""
1818
Custom security manager that syncs user-role mappings from Open Policy Agent to Superset.
1919
"""
20-
AUTH_OPA_CACHE_MAXSIZE_DEFAULT=1000
21-
AUTH_OPA_CACHE_TTL_IN_SEC_DEFAULT=30
22-
AUTH_OPA_REQUEST_URL_DEFAULT='http://opa:8081/'
20+
21+
AUTH_OPA_CACHE_MAXSIZE_DEFAULT = 1000
22+
AUTH_OPA_CACHE_TTL_IN_SEC_DEFAULT = 30
23+
AUTH_OPA_REQUEST_URL_DEFAULT = "http://opa:8081/"
2324

2425
def __init__(self, appbuilder):
2526
self.appbuilder = appbuilder
2627
super().__init__(self.appbuilder)
2728
config = self.appbuilder.get_app.config
2829
self.opa_cache = self.opa_cache = TTLCache(
2930
maxsize=config.get(
30-
'AUTH_OPA_CACHE_MAXSIZE',
31-
self.AUTH_OPA_CACHE_MAXSIZE_DEFAULT
31+
"AUTH_OPA_CACHE_MAXSIZE", self.AUTH_OPA_CACHE_MAXSIZE_DEFAULT
3232
),
3333
ttl=config.get(
34-
'AUTH_OPA_CACHE_TTL_IN_SEC',
35-
self.AUTH_OPA_CACHE_TTL_IN_SEC_DEFAULT
34+
"AUTH_OPA_CACHE_TTL_IN_SEC", self.AUTH_OPA_CACHE_TTL_IN_SEC_DEFAULT
3635
),
3736
)
3837

39-
4038
def get_user_roles(self, user: Optional[User] = None) -> List[Role]:
4139
"""
4240
Retrieves a user's roles from an Open Policy Agent instance updating the
@@ -49,27 +47,29 @@ def get_user_roles(self, user: Optional[User] = None) -> List[Role]:
4947

5048
default_role = self.resolve_role(
5149
current_app.config.get("AUTH_USER_REGISTRATION_ROLE")
52-
)
50+
)
5351

5452
opa_role_names = self.get_opa_user_roles(user.username)
55-
logging.info('OPA returned roles: %s', opa_role_names)
53+
logging.info("OPA returned roles: %s", opa_role_names)
5654

5755
opa_roles = set(map(self.resolve_role, opa_role_names))
58-
logging.info('Resolved OPA Roles in Database: %s', opa_roles)
56+
logging.info("Resolved OPA Roles in Database: %s", opa_roles)
5957
# Ensure that in case of a bad or no response from OPA each user will have
6058
# at least one role.
6159
if opa_roles == {None} or opa_roles == set():
6260
opa_roles = {default_role}
6361

6462
if set(user.roles) != opa_roles:
65-
logging.info('Found a diff between %s (Superset) and %s (OPA).',
66-
user.roles, opa_roles)
63+
logging.info(
64+
"Found a diff between %s (Superset) and %s (OPA).",
65+
user.roles,
66+
opa_roles,
67+
)
6768
user.roles = list(opa_roles)
6869
self.update_user(user)
6970

7071
return user.roles
7172

72-
7373
@cachedmethod(lambda self: self.opa_cache)
7474
def get_opa_user_roles(self, username: str) -> set[str]:
7575
"""
@@ -79,35 +79,36 @@ def get_opa_user_roles(self, username: str) -> set[str]:
7979
the connection to OPA is encountered or if OPA didn't return a list.
8080
"""
8181
host, port, tls = self.resolve_opa_base_url()
82-
client = OpaClient(host = host, port = port, ssl = tls)
82+
client = OpaClient(host=host, port=port, ssl=tls)
8383
try:
8484
response = client.query_rule(
85-
input_data = {'username': username},
86-
package_path = current_app.config.get('STACKABLE_OPA_PACKAGE'),
87-
rule_name = current_app.config.get('STACKABLE_OPA_RULE'))
85+
input_data={"username": username},
86+
package_path=current_app.config.get("STACKABLE_OPA_PACKAGE"),
87+
rule_name=current_app.config.get("STACKABLE_OPA_RULE"),
88+
)
8889
except HTTPException as exception:
89-
logging.error('Encountered an exception while querying OPA:%s', exception)
90+
logging.error("Encountered an exception while querying OPA:%s", exception)
9091
return []
91-
roles = response.get('result')
92+
roles = response.get("result")
9293
# If OPA didn't return a result or if the result is not a list, return no roles.
9394
if roles is None or type(roles).__name__ != "list":
94-
logging.error('The OPA query didn\'t return a list: %s', response)
95+
logging.error("The OPA query didn't return a list: %s", response)
9596
return []
9697
return roles
9798

98-
9999
def resolve_opa_base_url(self) -> Tuple[str, int, bool]:
100100
"""
101101
Extracts connection parameters of an Open Policy Agent instance from config.
102102
103103
:returns: Hostname, port and protocol (http/https).
104104
"""
105-
opa_base_path = current_app.config.get('STACKABLE_OPA_BASE_URL', self.AUTH_OPA_REQUEST_URL_DEFAULT)
105+
opa_base_path = current_app.config.get(
106+
"STACKABLE_OPA_BASE_URL", self.AUTH_OPA_REQUEST_URL_DEFAULT
107+
)
106108
[protocol, host, port] = opa_base_path.split(":")
107109
# remove any path be appended to the base url
108-
port = int(port.split('/')[0])
109-
return host.lstrip('/'), port, protocol == 'https'
110-
110+
port = int(port.split("/")[0])
111+
return host.lstrip("/"), port, protocol == "https"
111112

112113
def resolve_role(self, role_name: str) -> Role:
113114
"""
@@ -117,6 +118,6 @@ def resolve_role(self, role_name: str) -> Role:
117118
"""
118119
role = self.find_role(role_name)
119120
if role is None:
120-
logging.info('Creating role %s as it doesn\'t already exist.', role_name)
121+
logging.info("Creating role %s as it doesn't already exist.", role_name)
121122
self.add_role(role_name)
122123
return self.find_role(role_name)

superset/stackable/opa-authorizer/tests/opa_manager_test.py

Lines changed: 66 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ def opa_security_manager(
2727

2828
with app.app_context():
2929
mocker.patch(
30-
'flask_appbuilder.security.sqla.manager.SecurityManager.create_db',
31-
return_value = None
30+
"flask_appbuilder.security.sqla.manager.SecurityManager.create_db",
31+
return_value=None,
3232
)
3333
return OpaSupersetSecurityManager(appbuilder)
3434

@@ -40,17 +40,15 @@ def user() -> User:
4040
"""
4141
user = User()
4242
user.id = 1234
43-
user.first_name = 'mock'
44-
user.last_name = 'mock'
45-
user.username = 'mock'
46-
user.email = '[email protected]'
43+
user.first_name = "mock"
44+
user.last_name = "mock"
45+
user.username = "mock"
46+
user.email = "[email protected]"
4747

4848
return user
4949

5050

51-
def test_opa_security_manager(
52-
opa_security_manager: OpaSupersetSecurityManager
53-
) -> None:
51+
def test_opa_security_manager(opa_security_manager: OpaSupersetSecurityManager) -> None:
5452
"""
5553
Test that the OPA security manager can be built.
5654
"""
@@ -66,24 +64,25 @@ def test_add_roles(
6664
"""
6765
Test that roles are correctly added to a user.
6866
"""
69-
opa_roles = ['Test1', 'Test2', 'Test3']
67+
opa_roles = ["Test1", "Test2", "Test3"]
7068

7169
with app.app_context():
7270
mocker.patch(
73-
'flask_appbuilder.security.sqla.manager.SecurityManager.update_user',
74-
return_value = True
71+
"flask_appbuilder.security.sqla.manager.SecurityManager.update_user",
72+
return_value=True,
7573
)
7674
mocker.patch(
77-
'opa_authorizer.opa_manager.OpaSupersetSecurityManager.get_opa_user_roles',
78-
return_value = opa_roles
75+
"opa_authorizer.opa_manager.OpaSupersetSecurityManager.get_opa_user_roles",
76+
return_value=opa_roles,
7977
)
8078
mocker.patch(
81-
'opa_authorizer.opa_manager.OpaSupersetSecurityManager.resolve_role',
82-
wraps=mock_resolve_role
79+
"opa_authorizer.opa_manager.OpaSupersetSecurityManager.resolve_role",
80+
wraps=mock_resolve_role,
8381
)
8482

85-
assert set(map(lambda r: r.name, opa_security_manager.get_user_roles(user))) \
86-
== set(opa_roles)
83+
assert set(
84+
map(lambda r: r.name, opa_security_manager.get_user_roles(user))
85+
) == set(opa_roles)
8786

8887

8988
def test_change_roles(
@@ -95,26 +94,27 @@ def test_change_roles(
9594
"""
9695
Test that roles are correcty changed on a user.
9796
"""
98-
opa_roles = ['Test4']
97+
opa_roles = ["Test4"]
9998

10099
with app.app_context():
101100
mocker.patch(
102-
'flask_appbuilder.security.sqla.manager.SecurityManager.update_user',
103-
return_value = True
101+
"flask_appbuilder.security.sqla.manager.SecurityManager.update_user",
102+
return_value=True,
104103
)
105104
mocker.patch(
106-
'opa_authorizer.opa_manager.OpaSupersetSecurityManager.get_opa_user_roles',
107-
return_value = opa_roles
105+
"opa_authorizer.opa_manager.OpaSupersetSecurityManager.get_opa_user_roles",
106+
return_value=opa_roles,
108107
)
109108
mocker.patch(
110-
'opa_authorizer.opa_manager.OpaSupersetSecurityManager.resolve_role',
111-
wraps=mock_resolve_role
109+
"opa_authorizer.opa_manager.OpaSupersetSecurityManager.resolve_role",
110+
wraps=mock_resolve_role,
112111
)
113-
user_roles = ['Test1', 'Test2', 'Test3']
112+
user_roles = ["Test1", "Test2", "Test3"]
114113
user.roles = list(map(opa_security_manager.resolve_role, user_roles))
115114

116-
assert set(map(lambda r: r.name, opa_security_manager.get_user_roles(user))) \
117-
== set(opa_roles)
115+
assert set(
116+
map(lambda r: r.name, opa_security_manager.get_user_roles(user))
117+
) == set(opa_roles)
118118

119119

120120
def test_no_roles(
@@ -130,19 +130,21 @@ def test_no_roles(
130130

131131
with app.app_context():
132132
mocker.patch(
133-
'flask_appbuilder.security.sqla.manager.SecurityManager.update_user',
134-
return_value = True
133+
"flask_appbuilder.security.sqla.manager.SecurityManager.update_user",
134+
return_value=True,
135135
)
136136
mocker.patch(
137-
'opa_authorizer.opa_manager.OpaSupersetSecurityManager.get_opa_user_roles',
138-
return_value = opa_roles
137+
"opa_authorizer.opa_manager.OpaSupersetSecurityManager.get_opa_user_roles",
138+
return_value=opa_roles,
139139
)
140140
mocker.patch(
141-
'opa_authorizer.opa_manager.OpaSupersetSecurityManager.resolve_role',
142-
wraps=mock_resolve_role
141+
"opa_authorizer.opa_manager.OpaSupersetSecurityManager.resolve_role",
142+
wraps=mock_resolve_role,
143143
)
144144

145-
assert set(map(lambda r: r.name, opa_security_manager.get_user_roles(user))) == {'Public'}
145+
assert set(
146+
map(lambda r: r.name, opa_security_manager.get_user_roles(user))
147+
) == {"Public"}
146148

147149

148150
def test_get_opa_roles(
@@ -153,20 +155,17 @@ def test_get_opa_roles(
153155
"""
154156
Test that roles are correctly extracted from the OPA response.
155157
"""
156-
roles = ['Test1', 'Test2', 'Test3']
157-
response = {'result': roles}
158+
roles = ["Test1", "Test2", "Test3"]
159+
response = {"result": roles}
158160

159161
with app.app_context():
162+
mocker.patch("opa_client.opa.OpaClient.query_rule", return_value=response)
160163
mocker.patch(
161-
'opa_client.opa.OpaClient.query_rule',
162-
return_value = response
163-
)
164-
mocker.patch(
165-
'opa_authorizer.opa_manager.OpaSupersetSecurityManager.resolve_opa_base_url',
166-
return_value = ('opa-instance', 8081, False)
164+
"opa_authorizer.opa_manager.OpaSupersetSecurityManager.resolve_opa_base_url",
165+
return_value=("opa-instance", 8081, False),
167166
)
168167

169-
assert opa_security_manager.get_opa_user_roles('User1') == roles
168+
assert opa_security_manager.get_opa_user_roles("User1") == roles
170169

171170

172171
def test_get_opa_roles_no_result(
@@ -177,19 +176,16 @@ def test_get_opa_roles_no_result(
177176
"""
178177
Test that no roles are returned if the OPA response doesn't contain a query result.
179178
"""
180-
response = {'error': 'error occurred'}
179+
response = {"error": "error occurred"}
181180

182181
with app.app_context():
182+
mocker.patch("opa_client.opa.OpaClient.query_rule", return_value=response)
183183
mocker.patch(
184-
'opa_client.opa.OpaClient.query_rule',
185-
return_value = response
186-
)
187-
mocker.patch(
188-
'opa_authorizer.opa_manager.OpaSupersetSecurityManager.resolve_opa_base_url',
189-
return_value = ('opa-instance', 8081, False)
184+
"opa_authorizer.opa_manager.OpaSupersetSecurityManager.resolve_opa_base_url",
185+
return_value=("opa-instance", 8081, False),
190186
)
191187

192-
assert opa_security_manager.get_opa_user_roles('User1') == []
188+
assert opa_security_manager.get_opa_user_roles("User1") == []
193189

194190

195191
def test_get_opa_roles_not_a_list(
@@ -200,19 +196,16 @@ def test_get_opa_roles_not_a_list(
200196
"""
201197
Test that no roles are returned if the query result doesn't contain a list.
202198
"""
203-
response = {'result': "['Test1', 'Test2', 'Test3']"} # type string not list
199+
response = {"result": "['Test1', 'Test2', 'Test3']"} # type string not list
204200

205201
with app.app_context():
202+
mocker.patch("opa_client.opa.OpaClient.query_rule", return_value=response)
206203
mocker.patch(
207-
'opa_client.opa.OpaClient.query_rule',
208-
return_value = response
209-
)
210-
mocker.patch(
211-
'opa_authorizer.opa_manager.OpaSupersetSecurityManager.resolve_opa_base_url',
212-
return_value = ('opa-instance', 8081, False)
204+
"opa_authorizer.opa_manager.OpaSupersetSecurityManager.resolve_opa_base_url",
205+
return_value=("opa-instance", 8081, False),
213206
)
214207

215-
assert opa_security_manager.get_opa_user_roles('User1') == []
208+
assert opa_security_manager.get_opa_user_roles("User1") == []
216209

217210

218211
def test_resolve_opa_base_url(
@@ -225,10 +218,13 @@ def test_resolve_opa_base_url(
225218
"""
226219
with app.app_context():
227220
mocker.patch(
228-
'flask.current_app.config.get',
229-
return_value = 'http://opa-instance:8081'
221+
"flask.current_app.config.get", return_value="http://opa-instance:8081"
222+
)
223+
assert opa_security_manager.resolve_opa_base_url() == (
224+
"opa-instance",
225+
8081,
226+
False,
230227
)
231-
assert opa_security_manager.resolve_opa_base_url() == ('opa-instance', 8081, False)
232228

233229

234230
def test_resolve_opa_base_url_with_path(
@@ -242,10 +238,14 @@ def test_resolve_opa_base_url_with_path(
242238
"""
243239
with app.app_context():
244240
mocker.patch(
245-
'flask.current_app.config.get',
246-
return_value = 'http://opa-instance:8081/v1/data/superset'
241+
"flask.current_app.config.get",
242+
return_value="http://opa-instance:8081/v1/data/superset",
243+
)
244+
assert opa_security_manager.resolve_opa_base_url() == (
245+
"opa-instance",
246+
8081,
247+
False,
247248
)
248-
assert opa_security_manager.resolve_opa_base_url() == ('opa-instance', 8081, False)
249249

250250

251251
def mock_resolve_role(role_name: str) -> Role:

0 commit comments

Comments
 (0)