Files
superset2/tests/integration_tests/security/api_tests.py
David Aaron Suddjian 4ad5ad045a feat: embedded dashboard core (#17530)
* feat(dashboard): embedded dashboard UI configuration (#17175) (#17450)

* setup embedded provider

* update ui configuration

* fix test

* feat: Guest token (for embedded dashboard auth) (#17517)

* generate an embed token

* improve existing tests

* add some auth setup, and rename token

* fix the stuff for compatibility with external request loaders

* docs, standard jwt claims, tweaks

* black

* lint

* tests, and safer token decoding

* linting

* type annotation

* prettier

* add feature flag

* quiet pylint

* apparently typing is a problem again

* Make guest role name configurable

* fake being a non-anonymous user

* just one log entry

* customizable algo

* lint

* lint again

* 403 works now!

* get guest token from header instead of cookie

* Revert "403 works now!"

This reverts commit df2f49a6d4.

* fix tests

* Revert "Revert "403 works now!""

This reverts commit 883dff38f1.

* rename method

* correct import

* feat: entry for embedded dashboard (#17529)

* create entry for embedded dashboard in webpack

* add cookies

* lint

* token message handshake

* guestTokenHeaderName

* use setupClient instead of calling configure

* rename the webpack chunk

* simplified handshake

* embedded entrypoint: render a proper app

* make the embedded page accept anonymous connections

* format

* lint

* fix test
# Conflicts:
#	superset-frontend/src/embedded/index.tsx
#	superset/views/core.py

* lint

* Update superset-frontend/src/embedded/index.tsx

Co-authored-by: David Aaron Suddjian <1858430+suddjian@users.noreply.github.com>

* comment out origins checks

* move embedded for core to dashboard

* pylint

* isort

Co-authored-by: David Aaron Suddjian <aasuddjian@gmail.com>
Co-authored-by: David Aaron Suddjian <1858430+suddjian@users.noreply.github.com>

* feat: Authorizing guest access to embedded dashboards (#17757)

* helper methods and dashboard access

* guest token dashboard authz

* adjust csrf exempt list

* eums don't work that way

* Remove unnecessary import

* move row level security tests to their own file

* a bit of refactoring

* add guest token security tests

* refactor tests

* clean imports

* variable names can be too long apparently

* missing argument to get_user_roles

* don't redefine builtins

* remove unused imports

* fix test import

* default to global user when getting roles

* missing import

* mock it

* test get_user_roles

* infer g.user for ease of tests

* remove redundant check

* tests for guest user security manager fns

* use algo to get rid of warning messages

* tweaking access checks

* fix guest token security tests

* missing imports

* more tests

* more testing and also some small refactoring

* move validation out of parsing

* fix dashboard access check again

* add more test

Co-authored-by: Lily Kuang <lily@preset.io>

* feat: Row Level Security rules for guest tokens (#17836)

* helper methods and dashboard access

* guest token dashboard authz

* adjust csrf exempt list

* eums don't work that way

* Remove unnecessary import

* move row level security tests to their own file

* a bit of refactoring

* add guest token security tests

* refactor tests

* clean imports

* variable names can be too long apparently

* missing argument to get_user_roles

* don't redefine builtins

* remove unused imports

* fix test import

* default to global user when getting roles

* missing import

* mock it

* test get_user_roles

* infer g.user for ease of tests

* remove redundant check

* tests for guest user security manager fns

* use algo to get rid of warning messages

* tweaking access checks

* fix guest token security tests

* missing imports

* more tests

* more testing and also some small refactoring

* move validation out of parsing

* fix dashboard access check again

* rls rules for guest tokens

* test guest token rls rules

* more flexible rls rules

* lint

* fix tests

* fix test

* defaults

* fix some tests

* fix some tests

* lint

Co-authored-by: Lily Kuang <lily@preset.io>

* SupersetClient guest token test

* Apply suggestions from code review

Co-authored-by: Lily Kuang <lily@preset.io>

Co-authored-by: Lily Kuang <lily@preset.io>
2022-01-25 16:41:32 -08:00

96 lines
3.3 KiB
Python

# 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.
# isort:skip_file
"""Tests for security api methods"""
import json
import jwt
from tests.integration_tests.base_tests import SupersetTestCase
from flask_wtf.csrf import generate_csrf
class TestSecurityCsrfApi(SupersetTestCase):
resource_name = "security"
def _assert_get_csrf_token(self):
uri = f"api/v1/{self.resource_name}/csrf_token/"
response = self.client.get(uri)
self.assert200(response)
data = json.loads(response.data.decode("utf-8"))
self.assertEqual(generate_csrf(), data["result"])
def test_get_csrf_token(self):
"""
Security API: Test get CSRF token
"""
self.login(username="admin")
self._assert_get_csrf_token()
def test_get_csrf_token_gamma(self):
"""
Security API: Test get CSRF token by gamma
"""
self.login(username="gamma")
self._assert_get_csrf_token()
def test_get_csrf_unauthorized(self):
"""
Security API: Test get CSRF no login
"""
self.logout()
uri = f"api/v1/{self.resource_name}/csrf_token/"
response = self.client.get(uri)
self.assert401(response)
class TestSecurityGuestTokenApi(SupersetTestCase):
uri = f"api/v1/security/guest_token/"
def test_post_guest_token_unauthenticated(self):
"""
Security API: Cannot create a guest token without authentication
"""
self.logout()
response = self.client.post(self.uri)
self.assert401(response)
def test_post_guest_token_unauthorized(self):
"""
Security API: Cannot create a guest token without authorization
"""
self.login(username="gamma")
response = self.client.post(self.uri)
self.assert403(response)
def test_post_guest_token_authorized(self):
self.login(username="admin")
user = {"username": "bob", "first_name": "Bob", "last_name": "Also Bob"}
resource = {"type": "dashboard", "id": "blah"}
rls_rule = {"dataset": 1, "clause": "1=1"}
params = {"user": user, "resources": [resource], "rls": [rls_rule]}
response = self.client.post(
self.uri, data=json.dumps(params), content_type="application/json"
)
self.assert200(response)
token = json.loads(response.data)["token"]
decoded_token = jwt.decode(token, self.app.config["GUEST_TOKEN_JWT_SECRET"])
self.assertEqual(user, decoded_token["user"])
self.assertEqual(resource, decoded_token["resources"][0])