Пример #1
0
 def setUp(self):
     super().setUp()
     Config.objects.set_config('external_auth_url',
                               'https://auth.example.com')
     Config.objects.set_config('external_auth_admin_group', 'admins')
     self.auth = MacaroonAPIAuthentication()
     self.mock_service_key_request()
     self.mock_validate = self.patch(maasserver.macaroon_auth,
                                     'validate_user_external_auth')
     self.mock_validate.return_value = True
Пример #2
0
class TestMacaroonAPIAuthentication(MAASServerTestCase,
                                    MacaroonBakeryMockMixin):
    def setUp(self):
        super().setUp()
        Config.objects.set_config('external_auth_url',
                                  'https://auth.example.com')
        self.auth = MacaroonAPIAuthentication()
        self.mock_service_key_request()

    def get_request(self):
        request = factory.make_fake_request('/')
        # add external_auth_info to the request
        ExternalAuthInfoMiddleware().process_request(request)
        return request

    def test_is_authenticated_no_external_auth(self):
        # authentication details are provided
        self.mock_auth_info(username=factory.make_string())
        # ... but external auth is disabled
        Config.objects.set_config('external_auth_url', '')
        self.assertFalse(self.auth.is_authenticated(self.get_request()))

    def test_is_authenticated_no_auth_details(self):
        self.assertFalse(self.auth.is_authenticated(self.get_request()))

    def test_is_authenticated_with_auth(self):
        user = factory.make_User()
        self.mock_auth_info(username=user.username)
        self.assertTrue(self.auth.is_authenticated(self.get_request()))

    def test_is_authenticated_with_auth_creates_user(self):
        username = factory.make_string()
        self.mock_auth_info(username=username)
        self.assertTrue(self.auth.is_authenticated(self.get_request()))
        user = User.objects.get(username=username)
        self.assertIsNotNone(user.id)
        self.assertTrue(user.is_superuser)

    def test_challenge_no_external_auth(self):
        Config.objects.set_config('external_auth_url', '')
        response = self.auth.challenge(self.get_request())
        self.assertEqual(response.status_code, 401)

    def test_challenge(self):
        response = self.auth.challenge(self.get_request())
        self.assertEqual(response.status_code, 401)
        payload = json.loads(response.content)
        self.assertEqual(payload['Code'], 'macaroon discharge required')
        macaroon = payload['Info']['Macaroon']
        # macaroon is requested for this service
        self.assertEqual(macaroon['location'], 'http://testserver/')
        # a third party caveat is added for the external authentication service
        third_party_urls = [
            caveat['cl'] for caveat in macaroon['caveats'] if 'cl' in caveat
        ]
        self.assertEqual(third_party_urls, ['https://auth.example.com'])
Пример #3
0
class TestMacaroonAPIAuthentication(MAASServerTestCase,
                                    MacaroonBakeryMockMixin):
    def setUp(self):
        super().setUp()
        Config.objects.set_config('external_auth_url',
                                  'https://auth.example.com')
        Config.objects.set_config('external_auth_admin_group', 'admins')
        self.auth = MacaroonAPIAuthentication()
        self.mock_service_key_request()
        self.mock_validate = self.patch(maasserver.macaroon_auth,
                                        'validate_user_external_auth')
        self.mock_validate.return_value = True

    def get_request(self):
        request = factory.make_fake_request('/')
        # add external_auth_info to the request
        return ExternalAuthInfoMiddleware(lambda request: request)(request)

    def test_is_authenticated_no_external_auth(self):
        # authentication details are provided
        self.mock_auth_info(username=factory.make_string())
        # ... but external auth is disabled
        Config.objects.set_config('external_auth_url', '')
        self.assertFalse(self.auth.is_authenticated(self.get_request()))

    def test_is_authenticated_no_auth_details(self):
        self.assertFalse(self.auth.is_authenticated(self.get_request()))

    def test_is_authenticated_with_auth(self):
        user = factory.make_User()
        self.mock_auth_info(username=user.username)
        self.assertTrue(self.auth.is_authenticated(self.get_request()))

    def test_is_authenticated_with_auth_creates_user(self):
        username = factory.make_string()
        self.mock_auth_info(username=username)
        self.assertTrue(self.auth.is_authenticated(self.get_request()))
        user = User.objects.get(username=username)
        self.assertIsNotNone(user.id)
        self.assertFalse(user.is_superuser)
        self.assertFalse(user.userprofile.is_local)
        self.mock_validate.assert_called_with(
            user,
            ExternalAuthInfo(type='candid',
                             url='https://auth.example.com',
                             domain='',
                             admin_group='admins'))

    def test_is_authenticated_user_exists_but_local(self):
        user = factory.make_User()
        user.userprofile.is_local = True
        user.userprofile.save()
        self.mock_auth_info(username=user.username)
        self.assertFalse(self.auth.is_authenticated(self.get_request()))

    def test_is_authenticated_validate_if_exists(self):
        user = factory.make_User()
        self.mock_auth_info(username=user.username)
        self.assertTrue(self.auth.is_authenticated(self.get_request()))
        self.mock_validate.assert_called()

    def test_is_authenticated_fails_if_not_validated(self):
        self.mock_validate.return_value = False
        user = factory.make_User()
        self.mock_auth_info(username=user.username)
        self.assertFalse(self.auth.is_authenticated(self.get_request()))

    def test_challenge_no_external_auth(self):
        Config.objects.set_config('external_auth_url', '')
        response = self.auth.challenge(self.get_request())
        self.assertEqual(response.status_code, 401)

    def test_challenge(self):
        response = self.auth.challenge(self.get_request())
        self.assertEqual(response.status_code, 401)
        payload = json.loads(response.content)
        self.assertEqual(payload['Code'], 'macaroon discharge required')
        macaroon = payload['Info']['Macaroon']
        # macaroon is requested for this service
        self.assertEqual(macaroon['location'], 'http://testserver/')
        # a third party caveat is added for the external authentication service
        third_party_urls = [
            caveat['cl'] for caveat in macaroon['caveats'] if 'cl' in caveat
        ]
        self.assertEqual(third_party_urls, ['https://auth.example.com'])
Пример #4
0
                if user.username not in SYSTEM_USERS:
                    external_auth_info = request.external_auth_info
                    is_local_user = user.userprofile.is_local
                    if external_auth_info:
                        if is_local_user:
                            return False
                        if not validate_user_external_auth(
                                user, external_auth_info):
                            return False
                    elif not is_local_user:
                        return False

                request.user = user
                request.consumer = consumer
                request.throttle_extra = token.consumer.id
                return True

        return False

    def challenge(self, request):
        # Beware: this returns 401: Unauthorized, not 403: Forbidden
        # as the name implies.
        return rc.FORBIDDEN


# OAuth and macaroon-based authentication for the APIs.
api_auth = (
    MAASAPIAuthentication(realm="MAAS API"),
    MacaroonAPIAuthentication(),
)
Пример #5
0
class TestMacaroonAPIAuthentication(
    MAASServerTestCase, MacaroonBakeryMockMixin
):
    def setUp(self):
        super().setUp()
        Config.objects.set_config(
            "external_auth_url", "https://auth.example.com"
        )
        Config.objects.set_config("external_auth_admin_group", "admins")
        self.auth = MacaroonAPIAuthentication()
        self.mock_service_key_request()
        self.mock_validate = self.patch(
            maasserver.macaroon_auth, "validate_user_external_auth"
        )
        self.mock_validate.return_value = True

    def get_request(self):
        request = factory.make_fake_request("/")
        # add external_auth_info to the request
        return ExternalAuthInfoMiddleware(lambda request: request)(request)

    def test_is_authenticated_no_external_auth(self):
        # authentication details are provided
        self.mock_auth_info(username=factory.make_string())
        # ... but external auth is disabled
        Config.objects.set_config("external_auth_url", "")
        self.assertFalse(self.auth.is_authenticated(self.get_request()))

    def test_is_authenticated_no_auth_details(self):
        self.assertFalse(self.auth.is_authenticated(self.get_request()))

    def test_is_authenticated_with_auth(self):
        user = factory.make_User()
        self.mock_auth_info(username=user.username)
        self.assertTrue(self.auth.is_authenticated(self.get_request()))

    def test_is_authenticated_with_auth_creates_user(self):
        username = factory.make_string()
        self.mock_auth_info(username=username)
        self.assertTrue(self.auth.is_authenticated(self.get_request()))
        user = User.objects.get(username=username)
        self.assertIsNotNone(user.id)
        self.assertFalse(user.is_superuser)
        self.assertFalse(user.userprofile.is_local)
        self.mock_validate.assert_called_with(
            user,
            ExternalAuthInfo(
                type="candid",
                url="https://auth.example.com",
                domain="",
                admin_group="admins",
            ),
        )

    def test_is_authenticated_user_exists_but_local(self):
        user = factory.make_User()
        user.userprofile.is_local = True
        user.userprofile.save()
        self.mock_auth_info(username=user.username)
        self.assertFalse(self.auth.is_authenticated(self.get_request()))

    def test_is_authenticated_validate_if_exists(self):
        user = factory.make_User()
        self.mock_auth_info(username=user.username)
        self.assertTrue(self.auth.is_authenticated(self.get_request()))
        self.mock_validate.assert_called()

    def test_is_authenticated_fails_if_not_validated(self):
        self.mock_validate.return_value = False
        user = factory.make_User()
        self.mock_auth_info(username=user.username)
        self.assertFalse(self.auth.is_authenticated(self.get_request()))

    def test_challenge_no_external_auth(self):
        Config.objects.set_config("external_auth_url", "")
        response = self.auth.challenge(self.get_request())
        self.assertEqual(response.status_code, 401)

    def test_challenge(self):
        response = self.auth.challenge(self.get_request())
        self.assertEqual(response.status_code, 401)
        payload = json.loads(response.content)
        self.assertEqual(payload["Code"], "macaroon discharge required")
        macaroon = payload["Info"]["Macaroon"]
        # macaroon is requested for this service
        self.assertEqual(macaroon["location"], "http://testserver/")
        # a third party caveat is added for the external authentication service
        third_party_urls = [
            caveat["cl"] for caveat in macaroon["caveats"] if "cl" in caveat
        ]
        self.assertEqual(third_party_urls, ["https://auth.example.com"])
Пример #6
0
 def setUp(self):
     super().setUp()
     Config.objects.set_config('external_auth_url',
                               'https://auth.example.com')
     self.auth = MacaroonAPIAuthentication()
     self.mock_service_key_request()