Esempio n. 1
0
class BaseApiTests:
    user_tx_authkey = "69ed620926be4067a36402c3f7e9ddf0"

    def setUp(self):
        rebuild_schema()
        self.session = HollowmanSession()
        self.user = User(tx_email="*****@*****.**",
                         tx_name="John Doe",
                         tx_authkey=self.user_tx_authkey)
        self.account_dev = Account(id=4,
                                   name="Dev Team",
                                   namespace="dev",
                                   owner="company")
        self.user.accounts = [self.account_dev]
        self.user.current_account = self.account_dev
        self.session.add(self.account_dev)
        self.session.add(self.user)
        self.session.commit()

        self.proxy_mock_patcher = patch.object(hollowman.routes, 'raw_proxy')
        self.proxy_mock = self.proxy_mock_patcher.start()
        self.proxy_mock.return_value = Response(status=200)

    @property
    def auth_header(self):
        return {"Authorization": f"Token {self.user_tx_authkey}"}

    def tearDown(self):
        patch.stopall()
class DispatchResponse404Test(TestCase):
    @with_json_fixture("single_full_app.json")
    def setUp(self, single_full_app_fixture):
        rebuild_schema()
        self.session = HollowmanSession()
        self.user = User(tx_email="*****@*****.**",
                         tx_name="John Doe",
                         tx_authkey="69ed620926be4067a36402c3f7e9ddf0")
        self.account_dev = Account(id=4,
                                   name="Dev Team",
                                   namespace="dev",
                                   owner="company")
        self.user.accounts = [self.account_dev]
        self.session.add(self.user)
        self.session.add(self.account_dev)
        self.session.commit()

    def test_do_not_dispatch_response_pipeline_if_upstream_returns_404(self):
        auth_header = {
            "Authorization": "Token 69ed620926be4067a36402c3f7e9ddf0"
        }
        with application.test_client() as client:
            with RequestsMock() as rsps:
                rsps.add(method='GET',
                         url=conf.MARATHON_ADDRESSES[0] + '/v2/apps//dev/foo',
                         body=json.dumps({'message': "App /foo not found"}),
                         status=404)
                rsps.add(method='GET',
                         url=conf.MARATHON_ADDRESSES[0] + '/v2/apps/dev/foo',
                         body=json.dumps({'message': "App /foo not found"}),
                         status=404)
                response = client.get("/v2/apps/foo", headers=auth_header)
                self.assertEqual(404, response.status_code)
Esempio n. 3
0
class TestAuthentication(TestCase):
    def setUp(self):
        rebuild_schema()
        self.session = HollowmanSession()

        self.new_dispatcher_user = User(
            tx_email="*****@*****.**",
            tx_name="Xablau",
            tx_authkey="69ed620926be4067a36402c3f7e9ddf0")
        self.normal_user = User(tx_email="*****@*****.**",
                                tx_name="John Doe",
                                tx_authkey="70ed620926be4067a36402c3f7e9ddf0")
        self.account = Account(name="New Account",
                               namespace="acc",
                               owner="company")
        self.normal_user.accounts = [self.account]
        self.session.add_all([self.new_dispatcher_user, self.normal_user])
        self.session.commit()

        self.response_http_200 = Response(status=200)

    def tearDown(self):
        patch.stopall()

    def make_auth_header(self, user, account) -> Dict[str, str]:
        jwt_token = jwt_auth.jwt_encode_callback(
            jwt_generate_user_info(user, account))
        return {"Authorization": "JWT {}".format(jwt_token.decode('utf-8'))}

    @with_json_fixture("single_full_app.json")
    def test_it_creates_a_response_using_a_dict_of_headers(self, fixture):
        """
        O atributo headers de um objeto `request.models.Response` é utilizado
        para gerar o response do holloman. Por ser do tipo `CaseInsentiveDict`,
        quebra a implementação do flask e faz com que seja necessário o typecast
        para `dict`.
        """
        test_client = application.test_client()
        with application.app_context():
            auth_header = self.make_auth_header(self.normal_user,
                                                self.normal_user.accounts[0])
            with RequestsMock() as rsps:
                rsps.add(method='GET',
                         url=conf.MARATHON_ADDRESSES[0] + '/v2/apps',
                         body=json.dumps({'apps': [fixture]}),
                         status=200)
                rsps.add(method='GET',
                         url=conf.MARATHON_ADDRESSES[0] + '/v2/apps//foo',
                         body=json.dumps({'app': fixture}),
                         status=200)
                r = test_client.get("/v2/apps", headers=auth_header)
                self.assertEqual(200, r.status_code)
Esempio n. 4
0
class TestAuthentication(TestCase):
    @with_json_fixture("single_full_app.json")
    def setUp(self, fixture):
        rebuild_schema()
        self.session = HollowmanSession()
        self.user = User(tx_email="*****@*****.**",
                         tx_name="John Doe",
                         tx_authkey="69ed620926be4067a36402c3f7e9ddf0")
        self.account_dev = Account(id=4,
                                   name="Dev Team",
                                   namespace="dev",
                                   owner="company")
        self.account_infra = Account(name="Infra Team",
                                     namespace="infra",
                                     owner="company")
        self.account_sup = Account(name="Support Team",
                                   namespace="sup",
                                   owner="company")
        self.user.accounts = [self.account_dev, self.account_infra]
        self.session.add(self.user)
        self.session.add(self.account_dev)
        self.session.add(self.account_infra)
        self.session.add(self.account_sup)
        self.user_with_no_accounts = User(
            tx_email="*****@*****.**",
            tx_name="No Accounts",
            tx_authkey="7b4184bfe7d2349eb56bcfb9dc246cf8")
        self.session.add(self.user_with_no_accounts)
        self.account_with_no_user = Account(name="Team Nobody",
                                            namespace="nobody",
                                            owner="nobody")
        self.session.add(self.account_with_no_user)
        self.session.commit()
        self.response_http_200 = MagicMock(status_code=200)
        responses.add(method='GET',
                      url=conf.MARATHON_ADDRESSES[0] + '/v2/apps',
                      body=json.dumps({'apps': [fixture]}),
                      status=200)
        responses.add(method='GET',
                      url=conf.MARATHON_ADDRESSES[0] + '/v2/apps//foo',
                      body=json.dumps({'app': fixture}),
                      status=200)
        responses.start()

    def tearDown(self):
        self.session.close()
        responses.stop()

    def test_populate_request_user_if_key_is_valid(self):
        """
        Populates request.user if authentication is successful
        """
        with application.test_client() as client:
            r = client.get("/v2/apps",
                           headers={
                               "Authorization":
                               "Token 69ed620926be4067a36402c3f7e9ddf0"
                           })
            self.assertEqual(200, r.status_code)
            self.assertEqual("*****@*****.**", request.user.tx_email)

    def test_token_populate_default_account_if_request_account_is_empty(self):
        with application.test_client() as client:
            r = client.get("/v2/apps",
                           headers={
                               "Authorization":
                               "Token 69ed620926be4067a36402c3f7e9ddf0"
                           })
            self.assertEqual(200, r.status_code)
            self.assertEqual("*****@*****.**", request.user.tx_email)
            self.assertEqual(self.account_dev.id,
                             request.user.current_account.id)
            self.assertEqual(self.account_dev.namespace,
                             request.user.current_account.namespace)
            self.assertEqual(self.account_dev.owner,
                             request.user.current_account.owner)

    @unittest.skip("Pode não fazer sentido...")
    def test_jwt_populate_default_account_if_request_account_is_empty(self):
        """
        Como quem gera o token JWT é o server e ele *sempre* coloca account_id (Um user sem nennhuma account associada não se loga), esse request nunca vai acontecer.
        Não acontece pois é impossivel gerar um JWT válido sem ter a SECRET_KEY que só o server tem.
        """
        test_client = application.test_client()
        with application.app_context():
            jwt_token = jwt_auth.jwt_encode_callback(
                {"email": "*****@*****.**"})
            auth_header = {
                "Authorization": "JWT {}".format(jwt_token.decode('utf-8'))
            }
            r = test_client.get("/v2/apps", headers=auth_header)
            self.assertEqual(200, r.status_code)
            self.assertEqual(3, r.user.current_account)

    def test_jwt_return_401_if_user_is_not_linked_to_account(self):
        """
        If user tries to access account without being associated to this account
        """
        test_client = application.test_client()
        with application.app_context():
            jwt_token = jwt_auth.jwt_encode_callback(
                jwt_generate_user_info(self.user, self.account_with_no_user))
            auth_header = {
                "Authorization": "JWT {}".format(jwt_token.decode('utf-8'))
            }
            r = test_client.get("/v2/apps", headers=auth_header)
            self.assertEqual(401, r.status_code)
            self.assertEqual("Permission Denied to access this account",
                             json.loads(r.data)['msg'])

    def test_return_200_if_key_found(self):
        with application.test_client() as client:
            r = client.get("/v2/apps",
                           headers={
                               "Authorization":
                               " Token 69ed620926be4067a36402c3f7e9ddf0"
                           })
            self.assertEqual(200, r.status_code)

    def test_return_401_if_key_not_found(self):
        with application.test_client() as client:
            r = client.get("/v2/apps",
                           headers={"Authorization": "Token token-not-found"})
            self.assertEqual(401, r.status_code)
            self.assertEqual("Authorization token is invalid",
                             json.loads(r.data)['msg'])

    def test_return_401_if_no_token_present(self):
        with application.test_client() as client:
            r = client.get("/v2/apps")
            self.assertEqual(401, r.status_code)
            self.assertEqual("Authorization token is invalid",
                             json.loads(r.data)['msg'])

    def test_jwt_do_not_trigger_token_auth_if_jwt_token_is_present(self):
        """
        Both auth uses the same header: Authorization. Token Auth should *not* be called if current token is JWT
        """
        with application.test_client() as test_client, \
             application.app_context(), \
             patch.object(decorators, "HollowmanSession") as session_mock:
            r = test_client.get("/v2/apps",
                                headers={"Authorization": "JWT Token"})
            self.assertEqual(0, session_mock.call_count)

    def test_token_return_401_if_user_is_not_associated_to_desired_account(
            self):
        """
        Qualquer request com `?account_id` que o usuário nao esteja vinculado, retorna 401
        """
        account_id = self.account_with_no_user.id
        with application.test_client() as client:
            r = client.get("/v2/apps?account_id={}".format(account_id),
                           headers={
                               "Authorization":
                               " Token 69ed620926be4067a36402c3f7e9ddf0"
                           })
            self.assertEqual(401, r.status_code)

    def test_return_200_if_jwt_token_valid(self):
        test_client = application.test_client()
        with application.app_context():
            jwt_token = jwt_auth.jwt_encode_callback(
                jwt_generate_user_info(self.user, self.account_dev))
            auth_header = {
                "Authorization": "JWT {}".format(jwt_token.decode('utf-8'))
            }
            r = test_client.get("/v2/apps", headers=auth_header)
            self.assertEqual(200, r.status_code)

    def test_jwt_populate_request_user_if_token_is_valid(self):
        with application.app_context(), application.test_client(
        ) as test_client:
            jwt_token = jwt_auth.jwt_encode_callback(
                jwt_generate_user_info(self.user, self.account_infra))
            auth_header = {
                "Authorization": "JWT {}".format(jwt_token.decode('utf-8'))
            }
            r = test_client.get("/v2/apps", headers=auth_header)
            self.assertEqual(200, r.status_code)
            self.assertEqual("*****@*****.**", request.user.tx_email)
            self.assertEqual(5, request.user.current_account.id)

    def test_jwt_auth_with_token_from_session_if_headers_not_present(self):
        """
        Se não encontrarmos o token JWT no header, olhamos na flask session procurando por ele.
        """
        test_client = application.test_client()

        with application.app_context(), \
             patch.object(routes, "check_authentication_successful",
                          return_value={"email": self.user.tx_email}):
            jwt_token = jwt_auth.jwt_encode_callback(
                jwt_generate_user_info(self.user, self.account_dev))

            with test_client.session_transaction() as flask_session:
                flask_session['jwt'] = jwt_token

            response = test_client.get("/v2/apps")
            self.assertEqual(200, response.status_code)

    @unittest.skip("Ainda nao temos usuarios validos/ativos/invalidos")
    def test_return_401_if_jwt_token_is_valid_but_user_is_invalid(self):
        """
        User could be inactive or does not exist
        """
        self.fail()

    def test_return_401_if_jwt_token_is_invalid(self):
        with application.app_context(), application.test_client(
        ) as test_client:
            jwt_token = jwt.encode({"email": "*****@*****.**"},
                                   key="wrong key")
            auth_header = {
                "Authorization": "JWT {}".format(jwt_token.decode('utf-8'))
            }
            r = test_client.get("/v2/apps", headers=auth_header)
            self.assertEqual(401, r.status_code)
            self.assertEqual("Authorization token is invalid",
                             json.loads(r.data)['msg'])

    def test_return_401_if_jwt_token_not_present(self):
        test_client = application.test_client()
        with application.app_context():
            r = test_client.get("/v2/apps")
            self.assertEqual(401, r.status_code)
            self.assertEqual("Authorization token is invalid",
                             json.loads(r.data)['msg'])

    def test_redirect_with_jwt_url_is_formed_with_unicode_jwt(self):
        test_client = application.test_client()
        jwt = MagicMock()

        with application.app_context(), \
             patch.object(routes, "check_authentication_successful",
                          return_value={"email": "*****@*****.**"}),\
             patch.object(routes.jwt_auth, "jwt_encode_callback", return_value=jwt), \
             patch.object(routes, 'redirect') as redirect:
            response = test_client.get("/authenticate/google")

            jwt.decode.assert_called_once_with('utf-8')
            redirect.assert_called_once_with("{}?jwt={}".format(
                conf.REDIRECT_AFTER_LOGIN, jwt.decode.return_value))

    def test_login_failed_invalid_oauth2(self):
        test_client = application.test_client()

        with application.app_context(), \
                patch.object(routes, "check_authentication_successful", return_value={}), \
                patch.object(routes, "render_template") as render_mock:
            response = test_client.get("/authenticate/google")

            render_mock.assert_called_once_with("login-failed.html",
                                                reason="Invalid OAuth2 code")

    def test_login_failed_user_not_found(self):
        test_client = application.test_client()

        with application.app_context(), \
                patch.object(routes, "check_authentication_successful", return_value={"email": "*****@*****.**"}), \
                patch.object(routes, "render_template") as render_mock:
            response = test_client.get("/authenticate/google")

            render_mock.assert_called_once_with("login-failed.html",
                                                reason="User not found")

    def test_login_failed_user_does_not_have_any_account(self):
        test_client = application.test_client()

        with application.app_context(), \
                patch.object(routes, "check_authentication_successful", return_value={"email": self.user_with_no_accounts.tx_email}), \
                patch.object(routes, "render_template") as render_mock:
            response = test_client.get("/authenticate/google")

            render_mock.assert_called_once_with(
                "login-failed.html", reason="No associated accounts")

    def test_return_401_user_has_no_associated_account(self):
        with application.test_client() as client:
            r = client.get("/v2/apps",
                           headers={
                               "Authorization":
                               "Token 7b4184bfe7d2349eb56bcfb9dc246cf8"
                           })
            self.assertEqual(401, r.status_code)
            self.assertEqual("No associated account",
                             json.loads(r.data)['msg'])

    def test_jwt_add_redirect_with_account_id_on_token_after_login(self):
        """
        Depois do processo de login, o token JWT conterá o account_id da conta padrão
        do usuário.
        """
        test_client = application.test_client()

        with application.app_context(), \
             patch.object(routes, "check_authentication_successful",
                          return_value={"email": self.user.tx_email}),\
                patch.object(routes, "redirect") as redirect_mock:
            response = test_client.get("/authenticate/google")

            jwt_token = redirect_mock.call_args_list[0][0][0].split("=")[1]
            token_content = jwt.decode(jwt_token, conf.SECRET_KEY)

            self.assertEqual(self.user.tx_email,
                             token_content["user"]["email"])
            self.assertEqual(self.user.tx_name, token_content["user"]["name"])
            self.assertEqual(self.user.accounts[0].id,
                             token_content["current_account"]["id"])
            self.assertEqual(self.user.accounts[0].name,
                             token_content["current_account"]["name"])
            self.assertEqual(self.user.accounts[0].namespace,
                             token_content["current_account"]["namespace"])

    def test_add_default_account_on_first_jwt_token(self):
        """
        Depois do processo de login, o token JWT conterá o account_id da conta padrão
        do usuário.
        """
        test_client = application.test_client()
        jwt = MagicMock()

        with application.app_context(), \
             patch.object(routes, "check_authentication_successful",
                          return_value={"email": self.user.tx_email}),\
                patch.object(routes.jwt_auth, "jwt_encode_callback") as jwt_auth_mock:
            response = test_client.get("/authenticate/google")

            jwt_auth_mock.assert_called_once_with(
                jwt_generate_user_info(self.user, self.user.accounts[0]))

    def test_token_return_401_if_user_has_no_associated_account(self):
        with application.test_client() as client:
            r = client.get("/v2/apps",
                           headers={
                               "Authorization":
                               " Token 7b4184bfe7d2349eb56bcfb9dc246cf8"
                           })
            self.assertEqual(401, r.status_code)
            self.assertEqual("No associated account",
                             json.loads(r.data)['msg'])

    @unittest.skip(
        "Em teoria nunca vai existir um token JWT valido sem account_id. Mais detahes no teste test_jwt_populate_default_account_if_request_account_is_empty"
    )
    def test_jwt_return_401_if_user_has_no_associated_account(self):
        test_client = application.test_client()
        with application.app_context():
            jwt_token = jwt_auth.jwt_encode_callback({
                "email": "*****@*****.**",
                "account_id": 2
            })
            auth_header = {
                "Authorization": "JWT {}".format(jwt_token.decode('utf-8'))
            }
            r = test_client.get("/v2/apps", headers=auth_header)
            self.assertEqual(401, r.status_code)
            self.assertEqual("No associated account",
                             json.loads(r.data)['msg'])

    def test_jwt_return_401_if_when_account_does_not_exist(self):
        test_client = application.test_client()
        with application.app_context():
            jwt_token = jwt_auth.jwt_encode_callback(
                jwt_generate_user_info(self.user, Account(id=1024)))
            auth_header = {
                "Authorization": "JWT {}".format(jwt_token.decode('utf-8'))
            }
            r = test_client.get("/v2/apps", headers=auth_header)
            self.assertEqual(401, r.status_code)
            self.assertEqual("Account does not exist",
                             json.loads(r.data)['msg'])

    def test_token_return_401_if_when_account_does_not_exist(self):
        with application.test_client() as client:
            r = client.get("/v2/apps?account_id=1024",
                           headers={
                               "Authorization":
                               " Token 69ed620926be4067a36402c3f7e9ddf0"
                           })
            self.assertEqual(401, r.status_code)
            self.assertEqual("Account does not exist",
                             json.loads(r.data)['msg'])
class RequestHandlersTests(TestCase):
    @with_json_fixture("single_full_app.json")
    def setUp(self, single_full_app_fixture):
        self.request_apps = [
            (MarathonApp(id='/xablau'), MarathonApp(id='/xena')),
            (MarathonApp(id='/foo'), MarathonApp(id='/bar')),
        ]

        rebuild_schema()
        self.session = HollowmanSession()
        self.user = User(tx_email="*****@*****.**",
                         tx_name="John Doe",
                         tx_authkey="69ed620926be4067a36402c3f7e9ddf0")
        self.account_dev = Account(id=4,
                                   name="Dev Team",
                                   namespace="dev",
                                   owner="company")
        self.user.accounts = [self.account_dev]
        self.session.add(self.user)
        self.session.add(self.account_dev)
        self.session.commit()

    def test_it_call_dispatch_using_user_from_request(self):
        """
        Certificamos que o user preenchido no request é repassado para o dispatch
        """
        with application.test_request_context('/v2/apps/foo',
                                              method='GET') as ctx:
            with patch('hollowman.request_handlers.upstream_request'), \
                 patch('hollowman.request_handlers.dispatch') as dispatch_mock:
                user = MagicMock()
                ctx.request.user = user
                request_parser = Request(ctx.request)
                request_parser.split = MagicMock(
                    return_value=[self.request_apps[0]])
                request_parser.join = MagicMock()
                response = new(request_parser)
                dispatch_mock.assert_called_once_with(user=user, request=ANY)

    @with_json_fixture("../fixtures/single_full_app.json")
    def test_versions_endpoint_returns_app_on_root_json(
            self, single_full_app_fixture):
        """
        Apesar de um GET /v2/apps/<app-id> retornat a app em:
            {"app": <app-definition}
        um GET /v2/apps/<app-id>/versions/<version-id> retorna em:
            {<app-definition>}

        Aqui conferimos que nosso pipeline retorna um response consistente com
        essa regra
        """
        auth_header = {
            "Authorization": "Token 69ed620926be4067a36402c3f7e9ddf0"
        }
        single_full_app_fixture['id'] = "/dev/foo"
        with application.test_client() as client:
            with RequestsMock() as rsps:
                rsps.add(method='GET',
                         url=conf.MARATHON_ADDRESSES[0] +
                         '/v2/apps/dev/foo/versions/2017-10-31T13:01:07.768Z',
                         body=json.dumps(single_full_app_fixture),
                         status=200)
                rsps.add(method='GET',
                         url=conf.MARATHON_ADDRESSES[0] + '/v2/apps//dev/foo',
                         body=json.dumps({"app": single_full_app_fixture}),
                         status=200)
                response = client.get(
                    "/v2/apps/foo/versions/2017-10-31T13:01:07.768Z",
                    headers=auth_header)
                self.assertEqual(200, response.status_code)
                self.assertEqual("/foo", json.loads(response.data)['id'])

    @with_json_fixture("../fixtures/single_full_app.json")
    def test_apps_endpoint_accepts_app_with_versions_in_the_name(
            self, single_full_app_fixture):
        """
        Regressão: Commit 0068801288b33a407676a6aa9b521881854de2f7
        Devemos aceitar uma app que possui a string "versions" em um lugar no nome, especialmente no fim
        de uma parte do path, ex: "/workers/conversions/splitter"
        """
        auth_header = {
            "Authorization": "Token 69ed620926be4067a36402c3f7e9ddf0"
        }
        single_full_app_fixture['id'] = "/dev/workers/conversions/splitter"
        with application.test_client() as client:
            with RequestsMock() as rsps:
                rsps.add(method='GET',
                         url=conf.MARATHON_ADDRESSES[0] +
                         '/v2/apps/dev/workers/conversions/splitter',
                         body=json.dumps({"app": single_full_app_fixture}),
                         status=200)
                rsps.add(method='GET',
                         url=conf.MARATHON_ADDRESSES[0] +
                         '/v2/apps//dev/workers/conversions/splitter',
                         body=json.dumps({"app": single_full_app_fixture}),
                         status=200)
                response = client.get("/v2/apps/workers/conversions/splitter",
                                      headers=auth_header)
                self.assertEqual(200, response.status_code)
                self.assertTrue('app' in json.loads(response.data))
                self.assertEqual("/workers/conversions/splitter",
                                 json.loads(response.data)['app']['id'])

    @with_json_fixture("../fixtures/group_dev_namespace_with_apps.json")
    def test_groups_endpoint_returns_group_on_root_json(
            self, group_dev_namespace_fixture):
        auth_header = {
            "Authorization": "Token 69ed620926be4067a36402c3f7e9ddf0"
        }
        with application.test_client() as client:
            with RequestsMock() as rsps:
                rsps.add(
                    method='GET',
                    url=conf.MARATHON_ADDRESSES[0] + '/v2/groups//dev/group-b',
                    body=json.dumps(
                        deepcopy(group_dev_namespace_fixture['groups'][1])),
                    status=200)
                rsps.add(
                    method='GET',
                    url=conf.MARATHON_ADDRESSES[0] + '/v2/groups/dev/group-b',
                    body=json.dumps(
                        deepcopy(group_dev_namespace_fixture['groups'][1])),
                    status=200)
                rsps.add(method='GET',
                         url=conf.MARATHON_ADDRESSES[0] +
                         '/v2/groups//dev/group-b/group-b0',
                         body=json.dumps(
                             deepcopy(group_dev_namespace_fixture['groups'][1]
                                      ['groups'][0])),
                         status=200)
                response = client.get("/v2/groups/group-b",
                                      headers=auth_header)
                self.assertEqual(200, response.status_code)
                self.assertEqual("/group-b", json.loads(response.data)['id'])

    @with_json_fixture("../fixtures/queue/get.json")
    def test_queue_removes_queued_appps_from_other_namespaces(
            self, queue_get_fixture):
        """
        Removemos todas as apps que não sejam do namespace atual.
        Esse teste tambéem confirma que o namespace é removido dos elementos
        que voltam no response.
        """
        auth_header = {
            "Authorization": "Token 69ed620926be4067a36402c3f7e9ddf0"
        }
        with application.test_client() as client:
            with RequestsMock() as rsps:
                rsps.add(method='GET',
                         url=conf.MARATHON_ADDRESSES[0] + '/v2/queue',
                         status=200,
                         json=queue_get_fixture)

                response = client.get("/v2/queue", headers=auth_header)
                self.assertEqual(200, response.status_code)
                response_data = json.loads(response.data)
                self.assertEqual(1, len(response_data['queue']))
                self.assertEqual("/waiting",
                                 response_data['queue'][0]['app']['id'])

    def test_get_empty_apps_listing(self):
        auth_header = {
            "Authorization": "Token 69ed620926be4067a36402c3f7e9ddf0"
        }
        with application.test_client() as client:
            with RequestsMock() as rsps:
                rsps.add(method='GET',
                         url=conf.MARATHON_ADDRESSES[0] + '/v2/apps',
                         body=json.dumps({"apps": []}),
                         status=200)
                response = client.get("/v2/apps", headers=auth_header)
                self.assertEqual(200, response.status_code)
                response_body = json.loads(response.data)
                self.assertEqual({"apps": []}, response_body)
class OwnerFilterTest(unittest.TestCase):
    @with_json_fixture("single_full_app.json")
    def setUp(self, single_full_app_fixture):
        self.filter = AddOwnerConstraintFilter()
        rebuild_schema()
        self.session = HollowmanSession()
        self.user = User(tx_email="*****@*****.**",
                         tx_name="John Doe",
                         tx_authkey="69ed620926be4067a36402c3f7e9ddf0")
        self.account_dev = Account(id=4,
                                   name="Dev Team",
                                   namespace="dev",
                                   owner="company")
        self.user.accounts = [self.account_dev]
        self.session.add(self.user)
        self.session.add(self.account_dev)
        self.session.commit()

        self.request_app = SieveMarathonApp.from_json(single_full_app_fixture)
        self.original_app = SieveMarathonApp.from_json(single_full_app_fixture)
        self.user.current_account = self.account_dev

    def test_create_app_add_constraint_app_with_no_constraint(self):
        self.request_app.constraints = []
        filtered_app = self.filter.write(self.user, self.request_app,
                                         SieveMarathonApp())

        owner_constraint = filtered_app.get_constraints_by_name("owner")
        self.assertEqual(1, len(filtered_app.constraints))
        self.assertEqual(1, len(owner_constraint))
        self.assertEqual(self.account_dev.owner, owner_constraint[0].value)

    def test_update_app_add_constraint_app_with_no_constraint(self):
        self.request_app.constraints = []
        self.original_app.constraints = []
        filtered_app = self.filter.write(self.user, self.request_app,
                                         self.original_app)

        owner_constraint = filtered_app.get_constraints_by_name("owner")
        self.assertEqual(1, len(filtered_app.constraints))
        self.assertEqual(1, len(owner_constraint))
        self.assertEqual(self.account_dev.owner, owner_constraint[0].value)

    def test_create_app_constraint_exist_with_wrong_value(self):
        self.request_app.constraints.append(
            MarathonConstraint(field="owner",
                               operator="LIKE",
                               value="other-owner"))
        filtered_app = self.filter.write(self.user, self.request_app,
                                         SieveMarathonApp())

        owner_constraint = filtered_app.get_constraints_by_name("owner")
        self.assertEqual(2, len(filtered_app.constraints))
        self.assertEqual(1, len(owner_constraint))
        self.assertEqual(self.account_dev.owner, owner_constraint[0].value)

    def test_update_app_constraint_exist_with_wrong_value(self):
        self.request_app.constraints.append(
            MarathonConstraint(field="owner",
                               operator="LIKE",
                               value="other-owner"))
        filtered_app = self.filter.write(self.user, self.request_app,
                                         self.original_app)

        owner_constraint = filtered_app.get_constraints_by_name("owner")
        self.assertEqual(2, len(filtered_app.constraints))
        self.assertEqual(1, len(owner_constraint))
        self.assertEqual(self.account_dev.owner, owner_constraint[0].value)

    def test_create_app_add_constraint_app_with_other_constraints(self):
        filtered_app = self.filter.write(self.user, self.request_app,
                                         SieveMarathonApp())

        owner_constraint = filtered_app.get_constraints_by_name("owner")
        self.assertEqual(2, len(filtered_app.constraints))
        self.assertEqual(1, len(owner_constraint))
        self.assertEqual(self.account_dev.owner, owner_constraint[0].value)

    def test_update_app_add_constraint_app_with_other_constraints(self):
        filtered_app = self.filter.write(self.user, self.request_app,
                                         self.original_app)

        owner_constraint = filtered_app.get_constraints_by_name("owner")
        self.assertEqual(2, len(filtered_app.constraints))
        self.assertEqual(1, len(owner_constraint))
        self.assertEqual(self.account_dev.owner, owner_constraint[0].value)

    def test_update_app_trying_to_remove_constraint(self):
        self.original_app.constraints.append(
            MarathonConstraint(field="owner",
                               operator="LIKE",
                               value=self.account_dev.owner))
        filtered_app = self.filter.write(self.user, self.request_app,
                                         self.original_app)

        owner_constraint = filtered_app.get_constraints_by_name("owner")
        self.assertEqual(2, len(filtered_app.constraints))
        self.assertEqual(
            "srv2.*",
            filtered_app.get_constraints_by_name("hostname")[0].value)
        self.assertEqual(1, len(owner_constraint))
        self.assertEqual(self.account_dev.owner, owner_constraint[0].value)
Esempio n. 7
0
class TestAccountEndpoints(unittest.TestCase):
    def setUp(self):
        rebuild_schema()
        self.session = HollowmanSession()

        self.account_dev = Account(id=4,
                                   name="Dev Team",
                                   namespace="dev",
                                   owner="company")
        self.account_infra = Account(name="Infra Team",
                                     namespace="infra",
                                     owner="company")

        self.user = User(tx_email="*****@*****.**", tx_name="John Doe")
        self.user.accounts = [self.account_dev, self.account_infra]

        self.user_with_one_account = User(
            tx_email="*****@*****.**",
            tx_name="User One Account")
        self.user_with_one_account.accounts = [self.account_dev]

        self.session.add(self.account_dev)
        self.session.add(self.account_infra)

        self.session.add(self.user)
        self.session.add(self.user_with_one_account)
        self.session.commit()

    def tearDown(self):
        self.session.close()

    def generate_jwt_token_for_user(self, user, account):
        return jwt_auth.jwt_encode_callback(
            jwt_generate_user_info(user, account))

    def test_get_current_user_info_valid_auth(self):
        with application.app_context(), \
                application.test_client() as client:
            jwt_token = self.generate_jwt_token_for_user(
                self.user, self.user.accounts[0])
            response = client.get("/hollow/account/me",
                                  headers={
                                      "Authorization":
                                      "JWT {}".format(jwt_token.decode("utf8"))
                                  })
            self.assertEqual(200, response.status_code)
            response_data = json.loads(response.data)

            self.assertEqual(self.user.tx_email,
                             response_data["user"]["email"])
            self.assertEqual(self.user.tx_name, response_data["user"]["name"])
            self.assertEqual(self.user.accounts[0].id,
                             response_data["current_account"]["id"])
            self.assertEqual(self.user.accounts[0].name,
                             response_data["current_account"]["name"])

    def test_get_current_user_info_auth_invalid(self):
        with application.app_context(), \
                application.test_client() as client:
            response = client.get("/hollow/account/me")
            self.assertEqual(401, response.status_code)

    def test_change_account_has_permmission(self):
        """
        Troca para uma conta que o user atual está vinculado.
        """
        with application.app_context(), \
                application.test_client() as client:
            jwt_token = self.generate_jwt_token_for_user(
                self.user, self.user.accounts[0])
            response = client.post(
                "/hollow/account/change/{}".format(self.user.accounts[1].id),
                headers={
                    "Authorization": "JWT {}".format(jwt_token.decode("utf8"))
                })
            self.assertEqual(200, response.status_code)
            response_data = json.loads(response.data)

            self.assertEqual(self.user.tx_email,
                             response_data["user"]["email"])
            self.assertEqual(self.user.tx_name, response_data["user"]["name"])
            self.assertEqual(self.user.accounts[1].id,
                             response_data["current_account"]["id"])
            self.assertEqual(self.user.accounts[1].name,
                             response_data["current_account"]["name"])

            jwt_response_token = response_data["jwt_token"]
            self.assertTrue(jwt_response_token)
            returned_token = jwt.decode(jwt_response_token, key=SECRET_KEY)
            self.assertEqual(self.user.tx_email,
                             returned_token["user"]["email"])
            self.assertEqual(self.user.tx_name, returned_token["user"]["name"])
            self.assertEqual(self.user.accounts[1].id,
                             returned_token["current_account"]["id"])
            self.assertEqual(self.user.accounts[1].name,
                             returned_token["current_account"]["name"])

    def test_change_account_user_is_not_associated(self):
        """
        Retorna HTTP 401 se tentarmos trocar para uma conta que não
        estamos vinculados, ou seja, não existe registro na tabela `user_has_account`
        """
        with application.app_context(), \
                application.test_client() as client:
            jwt_token = self.generate_jwt_token_for_user(
                self.user, self.user.accounts[0])
            response = client.post("/hollow/account/change/42",
                                   headers={
                                       "Authorization":
                                       "JWT {}".format(
                                           jwt_token.decode("utf8"))
                                   })
            self.assertEqual(401, response.status_code)
            self.assertEquals("Not associated with account",
                              json.loads(response.data)["msg"])

    def test_change_to_next_account_one_account_left(self):
        """
        User tem duas accounts, está usando a primeira e pede pra trocar para a proxima.
        Retornamos a segunda
        """
        with application.app_context(), \
                application.test_client() as client:
            jwt_token = self.generate_jwt_token_for_user(
                self.user, self.user.accounts[0])
            response = client.post("/hollow/account/next",
                                   headers={
                                       "Authorization":
                                       "JWT {}".format(
                                           jwt_token.decode("utf8"))
                                   })
            self.assertEqual(200, response.status_code)
            response_data = json.loads(response.data)

            self.assertEqual(self.user.tx_email,
                             response_data["user"]["email"])
            self.assertEqual(self.user.tx_name, response_data["user"]["name"])
            self.assertEqual(self.user.accounts[1].id,
                             response_data["current_account"]["id"])
            self.assertEqual(self.user.accounts[1].name,
                             response_data["current_account"]["name"])

            jwt_response_header = response_data["jwt_token"]
            self.assertTrue(jwt_response_header)
            returned_token = jwt.decode(jwt_response_header, key=SECRET_KEY)
            self.assertEqual(self.user.tx_email,
                             returned_token["user"]["email"])
            self.assertEqual(self.user.tx_name, returned_token["user"]["name"])
            self.assertEqual(self.user.accounts[1].id,
                             returned_token["current_account"]["id"])
            self.assertEqual(self.user.accounts[1].name,
                             returned_token["current_account"]["name"])

    def test_test_change_to_next_account_no_account_left(self):
        """
        User tem duas accounts e já está usando a segunda, quando pedir a próxima
        retornamos a primeira account
        """
        with application.app_context(), \
                application.test_client() as client:
            jwt_token = self.generate_jwt_token_for_user(
                self.user, self.user.accounts[1])
            response = client.post("/hollow/account/next",
                                   headers={
                                       "Authorization":
                                       "JWT {}".format(
                                           jwt_token.decode("utf8"))
                                   })
            self.assertEqual(200, response.status_code)
            response_data = json.loads(response.data)

            self.assertEqual(self.user.tx_email,
                             response_data["user"]["email"])
            self.assertEqual(self.user.tx_name, response_data["user"]["name"])
            self.assertEqual(self.user.accounts[0].id,
                             response_data["current_account"]["id"])
            self.assertEqual(self.user.accounts[0].name,
                             response_data["current_account"]["name"])

            jwt_response_header = response_data["jwt_token"]
            self.assertTrue(jwt_response_header)
            returned_token = jwt.decode(jwt_response_header, key=SECRET_KEY)
            self.assertEqual(self.user.tx_email,
                             returned_token["user"]["email"])
            self.assertEqual(self.user.tx_name, returned_token["user"]["name"])
            self.assertEqual(self.user.accounts[0].id,
                             returned_token["current_account"]["id"])
            self.assertEqual(self.user.accounts[0].name,
                             returned_token["current_account"]["name"])
Esempio n. 8
0
class RoutesTest(unittest.TestCase):
    def setUp(self):
        rebuild_schema()
        self.session = HollowmanSession()
        self.user = User(tx_email="*****@*****.**",
                         tx_name="John Doe",
                         tx_authkey="69ed620926be4067a36402c3f7e9ddf0")
        self.account_dev = Account(id=4,
                                   name="Dev Team",
                                   namespace="dev",
                                   owner="company")
        self.user.accounts = [self.account_dev]
        self.session.add(self.account_dev)
        self.session.add(self.user)
        self.session.commit()

        self.proxy_mock_patcher = patch.object(hollowman.routes, 'raw_proxy')
        self.proxy_mock = self.proxy_mock_patcher.start()
        self.proxy_mock.return_value = Response(status=200)

    def tearDown(self):
        self.session.close()
        self.proxy_mock_patcher.stop()

    def test_v2_artifacts(self):
        with application.test_client() as client:
            client.get("/v2/artifacts",
                       headers={
                           "Authorization":
                           "Token 69ed620926be4067a36402c3f7e9ddf0"
                       })

            client.get("/v2/artifacts/etc/hosts",
                       headers={
                           "Authorization":
                           "Token 69ed620926be4067a36402c3f7e9ddf0"
                       })
            client.put("/v2/artifacts/etc/hosts",
                       headers={
                           "Authorization":
                           "Token 69ed620926be4067a36402c3f7e9ddf0"
                       })
            client.post("/v2/artifacts/etc/hosts",
                        headers={
                            "Authorization":
                            "Token 69ed620926be4067a36402c3f7e9ddf0"
                        })
            client.delete("/v2/artifacts/etc/hosts",
                          headers={
                              "Authorization":
                              "Token 69ed620926be4067a36402c3f7e9ddf0"
                          })

            client.get("/v2/artifacts//etc/hosts",
                       headers={
                           "Authorization":
                           "Token 69ed620926be4067a36402c3f7e9ddf0"
                       })
            client.put("/v2/artifacts//etc/hosts",
                       headers={
                           "Authorization":
                           "Token 69ed620926be4067a36402c3f7e9ddf0"
                       })
            client.post("/v2/artifacts//etc/hosts",
                        headers={
                            "Authorization":
                            "Token 69ed620926be4067a36402c3f7e9ddf0"
                        })
            client.delete("/v2/artifacts//etc/hosts",
                          headers={
                              "Authorization":
                              "Token 69ed620926be4067a36402c3f7e9ddf0"
                          })
        self.assertEqual(9, self.proxy_mock.call_count)

    def test_v2_info(self):
        with application.test_client() as client:
            client.get("/v2/info",
                       headers={
                           "Authorization":
                           "Token 69ed620926be4067a36402c3f7e9ddf0"
                       })
            self.assertEqual(1, self.proxy_mock.call_count)

    def test_v2_leader(self):
        with application.test_client() as client:
            client.get("/v2/leader",
                       headers={
                           "Authorization":
                           "Token 69ed620926be4067a36402c3f7e9ddf0"
                       })
            client.delete("/v2/leader",
                          headers={
                              "Authorization":
                              "Token 69ed620926be4067a36402c3f7e9ddf0"
                          })
            self.assertEqual(2, self.proxy_mock.call_count)

    def test_v2_info(self):
        with application.test_client() as client:
            client.get("/v2/info",
                       headers={
                           "Authorization":
                           "Token 69ed620926be4067a36402c3f7e9ddf0"
                       })
            self.assertEqual(1, self.proxy_mock.call_count)

    def test_ping(self):
        with application.test_client() as client:
            client.get("/ping",
                       headers={
                           "Authorization":
                           "Token 69ed620926be4067a36402c3f7e9ddf0"
                       })
            self.assertEqual(1, self.proxy_mock.call_count)

    def test_metrics(self):
        with application.test_client() as client:
            client.get("/metrics",
                       headers={
                           "Authorization":
                           "Token 69ed620926be4067a36402c3f7e9ddf0"
                       })
            self.assertEqual(1, self.proxy_mock.call_count)