diff --git a/dpl/api/api_gateway.py b/dpl/api/api_gateway.py index c3f3969..03d4c41 100644 --- a/dpl/api/api_gateway.py +++ b/dpl/api/api_gateway.py @@ -34,6 +34,15 @@ def auth(self, username: str, password: str) -> str: """ return self._am.auth_user(username, password) + @property + def is_insecure(self) -> bool: + """ + Returns a value of 'is_insecure' property of AuthManager + + :return: True if insecure mode is enabled, False otherwise + """ + return self._am.is_insecure + def _check_permission(self, token: str, requested_action): """ Checks is specified action is permitted for this token diff --git a/dpl/api/rest_api.py b/dpl/api/rest_api.py index 04fedc0..bfbc26d 100644 --- a/dpl/api/rest_api.py +++ b/dpl/api/rest_api.py @@ -62,7 +62,7 @@ async def proxy(self, request, *args, **kwargs): token = headers.get("Authorization", None) - if token is None: + if (token is None) and (self._gateway.is_insecure is False): return make_error_response(status=401, message="Authorization header is not available or is null") return await decorated_callable(self, request, *args, **kwargs, token=token) diff --git a/dpl/auth/auth_manager.py b/dpl/auth/auth_manager.py index 6a326d0..9b6fe43 100644 --- a/dpl/auth/auth_manager.py +++ b/dpl/auth/auth_manager.py @@ -13,10 +13,41 @@ class AuthManager(object): AuthManager is a class that controls users and their access to different parts of the system """ - def __init__(self): + def __init__(self, insecure: bool = False): + """ + Constructor. Allows to disable token checking ALTOGETHER. + USE INSECURE MODE ONLY WHEN YOU KNOW WHAT YOU ARE DOING! + :param insecure: disable token checking + """ self._users = dict() # type: Dict[str, User] self._root_user = None # type: User self._token_manager = TokenManager() + self._is_insecure = insecure + + @property + def is_insecure(self) -> bool: + """ + Indicates is AuthManager in insecure mode. Or, in other words, is token + checking disabled. + :return: True if insecure, False otherwise + """ + return self._is_insecure + + @is_insecure.setter + def is_insecure(self, new_value: bool): + """ + Allows to enable secure mode. Only + :param new_value: new value of is_secure property + :return: None + """ + if not isinstance(new_value, bool): + raise TypeError("The value of 'new_value' parameter must to boolean") + + if new_value: # if new_value == True: + raise ValueError("Insecure mode can't be enabled in runtime. Please, edit" + "persistent configuration and restart this application.") + + self._is_insecure = new_value @property def users(self) -> Set[str]: @@ -166,5 +197,7 @@ def is_token_grants(self, token: str, requested_action: object) -> bool: :return: true if permission is granted, false otherwise """ # TODO: Implement permission checking + if self._is_insecure: + return True # WARNING: all token values are accepted in insecure mode return self._token_manager.is_token_present(token) diff --git a/dpl/core/controller.py b/dpl/core/controller.py index 50156db..af7e173 100644 --- a/dpl/core/controller.py +++ b/dpl/core/controller.py @@ -16,14 +16,16 @@ def __init__(self): self._placements = PlacementManager() self._bm = BindingManager() - self._auth_manager = auth.AuthManager() + self._conf.load_config() + core_settings = self._conf.get_by_subsystem('core') # type: dict + insecure_enabled = core_settings.get('insecure_enabled', False) + + self._auth_manager = auth.AuthManager(insecure=insecure_enabled) self._api_gateway = api.ApiGateway(self._auth_manager, self._bm, self._placements) self._rest_api = api.RestApi(self._api_gateway) async def start(self): - self._conf.load_config() - core_settings = self._conf.get_by_subsystem("core") placement_settings = self._conf.get_by_subsystem("placements") connection_settings = self._conf.get_by_subsystem("connections") diff --git a/samples/config/core/core.json b/samples/config/core/core.json index 09ad5a1..c34f0e2 100644 --- a/samples/config/core/core.json +++ b/samples/config/core/core.json @@ -1,4 +1,5 @@ { "enabled_integrations": ["dummy"], - "debug": true + "debug": true, + "insecure_enabled": true } \ No newline at end of file diff --git a/unittests/auth/test_auth_manager.py b/unittests/auth/test_auth_manager.py index a93d24f..97f60c7 100644 --- a/unittests/auth/test_auth_manager.py +++ b/unittests/auth/test_auth_manager.py @@ -47,6 +47,7 @@ def test_creation(self): am = AuthManager() self.assertFalse(am.users) # Assert that there is no users after creation + self.assertFalse(am.is_insecure) # Assert that insecure mode is disabled by default def test_root_user_creation(self): am = AuthManager() @@ -240,6 +241,38 @@ def test_password_change_invalidates_tokens(self): self.assertFalse(am.is_token_grants(old_root_token, None)) + def test_insecure_mode_token_not_checked(self): + am = AuthManager(insecure=True) + + self.assertTrue(am.is_token_grants('abcdefgh', None)) + + def test_insecure_mode_runtime_disable(self): + am = AuthManager(insecure=True) + self.assertTrue(am.is_insecure) + self.assertTrue(am.is_token_grants('abcdefgh', None)) + + am.is_insecure = False + self.assertFalse(am.is_insecure) + self.assertFalse(am.is_token_grants('abcdefgh', None)) + + def test_insecure_mode_setter_only_bool(self): + am = AuthManager(insecure=True) + + with self.assertRaises(TypeError): + am.is_insecure = 'foo' + + with self.assertRaises(TypeError): + am.is_insecure = None + + with self.assertRaises(TypeError): + am.is_insecure = self + + def test_insecure_mode_runtime_enable(self): + am = AuthManager() + + with self.assertRaises(ValueError): + am.is_insecure = True + if __name__ == '__main__': unittest.main()