Exemple #1
0
 def test_outpost_validaton(self):
     """Test Outpost validation"""
     valid = OutpostSerializer(
         data={
             "name": "foo",
             "type": OutpostType.PROXY,
             "config": default_outpost_config(),
             "providers": [
                 ProxyProvider.objects.create(
                     name="test", authorization_flow=create_test_flow()
                 ).pk
             ],
         }
     )
     self.assertTrue(valid.is_valid())
     invalid = OutpostSerializer(
         data={
             "name": "foo",
             "type": OutpostType.PROXY,
             "config": default_outpost_config(),
             "providers": [
                 LDAPProvider.objects.create(
                     name="test", authorization_flow=create_test_flow()
                 ).pk
             ],
         }
     )
     self.assertFalse(invalid.is_valid())
     self.assertIn("providers", invalid.errors)
Exemple #2
0
 def setUp(self) -> None:
     super().setUp()
     ObjectManager().run()
     self.app = Application.objects.create(name="test", slug="test")
     self.provider: OAuth2Provider = OAuth2Provider.objects.create(
         name="test",
         client_id=generate_id(),
         client_secret=generate_key(),
         authorization_flow=create_test_flow(),
         redirect_uris="",
         signing_key=create_test_cert(),
     )
     self.provider.property_mappings.set(ScopeMapping.objects.all())
     # Needs to be assigned to an application for iss to be set
     self.app.provider = self.provider
     self.app.save()
     self.user = create_test_admin_user()
     self.token: RefreshToken = RefreshToken.objects.create(
         provider=self.provider,
         user=self.user,
         access_token=generate_id(),
         refresh_token=generate_id(),
         _scope="openid user profile",
         _id_token=json.dumps(asdict(IDToken("foo", "bar"), )),
     )
Exemple #3
0
 def test_used_by(self):
     """Test used_by endpoint"""
     self.client.force_login(create_test_admin_user())
     keypair = create_test_cert()
     provider = OAuth2Provider.objects.create(
         name="test",
         client_id="test",
         client_secret=generate_key(),
         authorization_flow=create_test_flow(),
         redirect_uris="http://localhost",
         signing_key=keypair,
     )
     response = self.client.get(
         reverse(
             "authentik_api:certificatekeypair-used-by",
             kwargs={"pk": keypair.pk},
         ))
     self.assertEqual(200, response.status_code)
     self.assertJSONEqual(
         response.content.decode(),
         [{
             "app": "authentik_providers_oauth2",
             "model_name": "oauth2provider",
             "pk": str(provider.pk),
             "name": str(provider),
             "action": DeleteAction.SET_NULL.name,
         }],
     )
Exemple #4
0
 def test_request_refresh_token(self):
     """test request param"""
     provider = OAuth2Provider.objects.create(
         name="test",
         client_id=generate_id(),
         client_secret=generate_key(),
         authorization_flow=create_test_flow(),
         redirect_uris="http://local.invalid",
         signing_key=create_test_cert(),
     )
     header = b64encode(f"{provider.client_id}:{provider.client_secret}".
                        encode()).decode()
     user = create_test_admin_user()
     token: RefreshToken = RefreshToken.objects.create(
         provider=provider,
         user=user,
         refresh_token=generate_id(),
     )
     request = self.factory.post(
         "/",
         data={
             "grant_type": GRANT_TYPE_REFRESH_TOKEN,
             "refresh_token": token.refresh_token,
             "redirect_uri": "http://local.invalid",
         },
         HTTP_AUTHORIZATION=f"Basic {header}",
     )
     params = TokenParams.parse(request, provider, provider.client_id,
                                provider.client_secret)
     self.assertEqual(params.provider, provider)
Exemple #5
0
 def test_request_auth_code(self):
     """test request param"""
     provider = OAuth2Provider.objects.create(
         name="test",
         client_id=generate_id(),
         client_secret=generate_key(),
         authorization_flow=create_test_flow(),
         redirect_uris="http://testserver",
         signing_key=create_test_cert(),
     )
     header = b64encode(f"{provider.client_id}:{provider.client_secret}".
                        encode()).decode()
     user = create_test_admin_user()
     code = AuthorizationCode.objects.create(code="foobar",
                                             provider=provider,
                                             user=user)
     request = self.factory.post(
         "/",
         data={
             "grant_type": GRANT_TYPE_AUTHORIZATION_CODE,
             "code": code.code,
             "redirect_uri": "http://testserver",
         },
         HTTP_AUTHORIZATION=f"Basic {header}",
     )
     params = TokenParams.parse(request, provider, provider.client_id,
                                provider.client_secret)
     self.assertEqual(params.provider, provider)
     with self.assertRaises(TokenError):
         TokenParams.parse(request, provider, provider.client_id,
                           generate_key())
 def test_invalid_redirect_uri(self):
     """test missing/invalid redirect URI"""
     OAuth2Provider.objects.create(
         name="test",
         client_id="test",
         authorization_flow=create_test_flow(),
         redirect_uris="http://local.invalid",
     )
     with self.assertRaises(RedirectUriError):
         request = self.factory.get("/",
                                    data={
                                        "response_type": "code",
                                        "client_id": "test"
                                    })
         OAuthAuthorizationParams.from_request(request)
     with self.assertRaises(RedirectUriError):
         request = self.factory.get(
             "/",
             data={
                 "response_type": "code",
                 "client_id": "test",
                 "redirect_uri": "http://localhost",
             },
         )
         OAuthAuthorizationParams.from_request(request)
Exemple #7
0
 def test_refresh_token_revoke(self):
     """test request param"""
     provider = OAuth2Provider.objects.create(
         name="test",
         client_id=generate_id(),
         client_secret=generate_key(),
         authorization_flow=create_test_flow(),
         redirect_uris="http://testserver",
         signing_key=create_test_cert(),
     )
     # Needs to be assigned to an application for iss to be set
     self.app.provider = provider
     self.app.save()
     header = b64encode(f"{provider.client_id}:{provider.client_secret}".
                        encode()).decode()
     user = create_test_admin_user()
     token: RefreshToken = RefreshToken.objects.create(
         provider=provider,
         user=user,
         refresh_token=generate_id(),
     )
     # Create initial refresh token
     response = self.client.post(
         reverse("authentik_providers_oauth2:token"),
         data={
             "grant_type": GRANT_TYPE_REFRESH_TOKEN,
             "refresh_token": token.refresh_token,
             "redirect_uri": "http://testserver",
         },
         HTTP_AUTHORIZATION=f"Basic {header}",
     )
     new_token: RefreshToken = (RefreshToken.objects.filter(
         user=user).exclude(pk=token.pk).first())
     # Post again with initial token -> get new refresh token
     # and revoke old one
     response = self.client.post(
         reverse("authentik_providers_oauth2:token"),
         data={
             "grant_type": GRANT_TYPE_REFRESH_TOKEN,
             "refresh_token": new_token.refresh_token,
             "redirect_uri": "http://local.invalid",
         },
         HTTP_AUTHORIZATION=f"Basic {header}",
     )
     self.assertEqual(response.status_code, 200)
     # Post again with old token, is now revoked and should error
     response = self.client.post(
         reverse("authentik_providers_oauth2:token"),
         data={
             "grant_type": GRANT_TYPE_REFRESH_TOKEN,
             "refresh_token": new_token.refresh_token,
             "redirect_uri": "http://local.invalid",
         },
         HTTP_AUTHORIZATION=f"Basic {header}",
     )
     self.assertEqual(response.status_code, 400)
     self.assertTrue(
         Event.objects.filter(
             action=EventAction.SUSPICIOUS_REQUEST).exists())
Exemple #8
0
 def setUp(self):
     ObjectManager().run()
     cert = create_test_cert()
     self.provider: SAMLProvider = SAMLProvider.objects.create(
         authorization_flow=create_test_flow(),
         acs_url="http://testserver/source/saml/provider/acs/",
         signing_kp=cert,
         verification_kp=cert,
     )
     self.provider.property_mappings.set(SAMLPropertyMapping.objects.all())
     self.provider.save()
     self.source = SAMLSource.objects.create(
         slug="provider",
         issuer="authentik",
         signing_kp=cert,
         pre_authentication_flow=create_test_flow(),
     )
     self.factory = RequestFactory()
 def test_default_view(self):
     """Test that ToDefaultFlow returns the expected URL"""
     Flow.objects.filter(designation=FlowDesignation.INVALIDATION).delete()
     flow = create_test_flow(FlowDesignation.INVALIDATION)
     response = self.client.get(
         reverse("authentik_flows:default-invalidation"), )
     expected_url = reverse("authentik_core:if-flow",
                            kwargs={"flow_slug": flow.slug})
     self.assertEqual(response.status_code, 302)
     self.assertEqual(response.url, expected_url)
Exemple #10
0
 def test_metadata_without_signautre(self):
     """Test Metadata generation being valid"""
     source = SAMLSource.objects.create(
         slug="provider",
         issuer="authentik",
         pre_authentication_flow=create_test_flow(),
     )
     request = self.factory.get("/")
     xml = MetadataProcessor(source, request).build_entity_descriptor()
     metadata = ElementTree.fromstring(xml)
     self.assertEqual(metadata.attrib["entityID"], "authentik")
Exemple #11
0
 def test_recovery(self):
     """Test user recovery link (no recovery flow set)"""
     flow = create_test_flow(FlowDesignation.RECOVERY)
     tenant: Tenant = create_test_tenant()
     tenant.flow_recovery = flow
     tenant.save()
     self.client.force_login(self.admin)
     response = self.client.get(
         reverse("authentik_api:user-recovery", kwargs={"pk": self.user.pk})
     )
     self.assertEqual(response.status_code, 200)
Exemple #12
0
 def test_metadata(self):
     """Test metadata export (normal)"""
     self.client.logout()
     provider = SAMLProvider.objects.create(
         name="test",
         authorization_flow=create_test_flow(),
     )
     Application.objects.create(name="test", provider=provider, slug="test")
     response = self.client.get(
         reverse("authentik_api:samlprovider-metadata",
                 kwargs={"pk": provider.pk}), )
     self.assertEqual(200, response.status_code)
Exemple #13
0
    def test_kubernetes_controller_ingress(self):
        """Test Kubernetes Controller's Ingress"""
        provider: ProxyProvider = ProxyProvider.objects.create(
            name="test",
            internal_host="http://localhost",
            external_host="https://localhost",
            authorization_flow=create_test_flow(),
        )
        provider2: ProxyProvider = ProxyProvider.objects.create(
            name="test2",
            internal_host="http://otherhost",
            external_host="https://otherhost",
            mode=ProxyMode.FORWARD_SINGLE,
            authorization_flow=create_test_flow(),
        )

        service_connection = KubernetesServiceConnection.objects.first()
        outpost: Outpost = Outpost.objects.create(
            name="test",
            type=OutpostType.PROXY,
            service_connection=service_connection,
        )
        outpost.providers.add(provider)

        self.controller = ProxyKubernetesController(outpost,
                                                    service_connection)

        ingress_rec = IngressReconciler(self.controller)
        ingress = ingress_rec.retrieve()

        self.assertEqual(len(ingress.spec.rules), 1)
        self.assertEqual(ingress.spec.rules[0].host, "localhost")

        # add provider, check again
        outpost.providers.add(provider2)
        ingress = ingress_rec.retrieve()

        self.assertEqual(len(ingress.spec.rules), 2)
        self.assertEqual(ingress.spec.rules[0].host, "localhost")
        self.assertEqual(ingress.spec.rules[1].host, "otherhost")
Exemple #14
0
 def test_recovery_email_no_stage(self):
     """Test user recovery link (no email stage)"""
     self.user.email = "*****@*****.**"
     self.user.save()
     flow = create_test_flow(designation=FlowDesignation.RECOVERY)
     tenant: Tenant = create_test_tenant()
     tenant.flow_recovery = flow
     tenant.save()
     self.client.force_login(self.admin)
     response = self.client.get(
         reverse("authentik_api:user-recovery-email", kwargs={"pk": self.user.pk})
     )
     self.assertEqual(response.status_code, 404)
Exemple #15
0
 def test_hs256(self):
     """Test JWKS request with HS256"""
     provider = OAuth2Provider.objects.create(
         name="test",
         client_id="test",
         authorization_flow=create_test_flow(),
         redirect_uris="http://local.invalid",
     )
     app = Application.objects.create(name="test",
                                      slug="test",
                                      provider=provider)
     response = self.client.get(
         reverse("authentik_providers_oauth2:jwks",
                 kwargs={"application_slug": app.slug}))
     self.assertJSONEqual(response.content.decode(), {})
Exemple #16
0
    def test_metadata_schema(self):
        """Test Metadata generation being valid"""
        source = SAMLSource.objects.create(
            slug="provider",
            issuer="authentik",
            signing_kp=create_test_cert(),
            pre_authentication_flow=create_test_flow(),
        )
        request = self.factory.get("/")
        xml = MetadataProcessor(source, request).build_entity_descriptor()
        metadata = etree.fromstring(xml)  # nosec

        schema = etree.XMLSchema(
            etree.parse("xml/saml-schema-metadata-2.0.xsd"))  # nosec
        self.assertTrue(schema.validate(metadata))
Exemple #17
0
 def test_import_failed(self):
     """Test metadata import (invalid xml)"""
     with TemporaryFile() as metadata:
         metadata.write(b"invalid")
         metadata.seek(0)
         response = self.client.post(
             reverse("authentik_api:samlprovider-import-metadata"),
             {
                 "file": metadata,
                 "name": "test",
                 "authorization_flow": create_test_flow().slug,
             },
             format="multipart",
         )
     self.assertEqual(400, response.status_code)
Exemple #18
0
 def test_outpost_config(self):
     """Test Outpost's config field"""
     provider = ProxyProvider.objects.create(name="test", authorization_flow=create_test_flow())
     invalid = OutpostSerializer(data={"name": "foo", "providers": [provider.pk], "config": ""})
     self.assertFalse(invalid.is_valid())
     self.assertIn("config", invalid.errors)
     valid = OutpostSerializer(
         data={
             "name": "foo",
             "providers": [provider.pk],
             "config": default_outpost_config("foo"),
             "type": OutpostType.PROXY,
         }
     )
     self.assertTrue(valid.is_valid())
    def test_default_view_invalid_plan(self):
        """Test that ToDefaultFlow returns the expected URL (with an invalid plan)"""
        Flow.objects.filter(designation=FlowDesignation.INVALIDATION).delete()
        flow = create_test_flow(FlowDesignation.INVALIDATION)
        plan = FlowPlan(flow_pk=flow.pk.hex + "aa")
        session = self.client.session
        session[SESSION_KEY_PLAN] = plan
        session.save()

        response = self.client.get(
            reverse("authentik_flows:default-invalidation"), )
        expected_url = reverse("authentik_core:if-flow",
                               kwargs={"flow_slug": flow.slug})
        self.assertEqual(response.status_code, 302)
        self.assertEqual(response.url, expected_url)
Exemple #20
0
 def test_metadata_invalid(self):
     """Test metadata export (invalid)"""
     self.client.logout()
     # Provider without application
     provider = SAMLProvider.objects.create(
         name="test",
         authorization_flow=create_test_flow(),
     )
     response = self.client.get(
         reverse("authentik_api:samlprovider-metadata",
                 kwargs={"pk": provider.pk}), )
     self.assertEqual(200, response.status_code)
     response = self.client.get(
         reverse("authentik_api:samlprovider-metadata",
                 kwargs={"pk": "abc"}), )
     self.assertEqual(404, response.status_code)
 def test_signed_static(self):
     """Test post request with static request"""
     provider = SAMLProvider(
         name="aws",
         authorization_flow=create_test_flow(),
         acs_url=("https://eu-central-1.signin.aws.amazon.com/platform/"
                  "saml/acs/2d737f96-55fb-4035-953e-5e24134eb778"),
         audience="https://10.120.20.200/saml-sp/SAML2/POST",
         issuer="https://10.120.20.200/saml-sp/SAML2/POST",
         signing_kp=create_test_cert(),
     )
     parsed_request = AuthNRequestParser(provider).parse(POST_REQUEST)
     self.assertEqual(parsed_request.id,
                      "aws_LDxLGeubpc5lx12gxCgS6uPbix1yd5re")
     self.assertEqual(parsed_request.name_id_policy,
                      SAML_NAME_ID_FORMAT_EMAIL)
Exemple #22
0
 def test_refresh_token_view(self):
     """test request param"""
     provider = OAuth2Provider.objects.create(
         name="test",
         client_id=generate_id(),
         client_secret=generate_key(),
         authorization_flow=create_test_flow(),
         redirect_uris="http://local.invalid",
         signing_key=create_test_cert(),
     )
     # Needs to be assigned to an application for iss to be set
     self.app.provider = provider
     self.app.save()
     header = b64encode(f"{provider.client_id}:{provider.client_secret}".
                        encode()).decode()
     user = create_test_admin_user()
     token: RefreshToken = RefreshToken.objects.create(
         provider=provider,
         user=user,
         refresh_token=generate_id(),
     )
     response = self.client.post(
         reverse("authentik_providers_oauth2:token"),
         data={
             "grant_type": GRANT_TYPE_REFRESH_TOKEN,
             "refresh_token": token.refresh_token,
             "redirect_uri": "http://local.invalid",
         },
         HTTP_AUTHORIZATION=f"Basic {header}",
         HTTP_ORIGIN="http://local.invalid",
     )
     new_token: RefreshToken = (RefreshToken.objects.filter(
         user=user).exclude(pk=token.pk).first())
     self.assertEqual(response["Access-Control-Allow-Credentials"], "true")
     self.assertEqual(response["Access-Control-Allow-Origin"],
                      "http://local.invalid")
     self.assertJSONEqual(
         response.content.decode(),
         {
             "access_token": new_token.access_token,
             "refresh_token": new_token.refresh_token,
             "token_type": "bearer",
             "expires_in": 2592000,
             "id_token": provider.encode(new_token.id_token.to_dict(), ),
         },
     )
     self.validate_jwt(new_token, provider)
Exemple #23
0
 def test_rs256(self):
     """Test JWKS request with RS256"""
     provider = OAuth2Provider.objects.create(
         name="test",
         client_id="test",
         authorization_flow=create_test_flow(),
         redirect_uris="http://local.invalid",
         signing_key=create_test_cert(),
     )
     app = Application.objects.create(name="test",
                                      slug="test",
                                      provider=provider)
     response = self.client.get(
         reverse("authentik_providers_oauth2:jwks",
                 kwargs={"application_slug": app.slug}))
     body = json.loads(response.content.decode())
     self.assertEqual(len(body["keys"]), 1)
Exemple #24
0
 def test_import_success(self):
     """Test metadata import (success case)"""
     with TemporaryFile() as metadata:
         metadata.write(METADATA_SIMPLE.encode())
         metadata.seek(0)
         response = self.client.post(
             reverse("authentik_api:samlprovider-import-metadata"),
             {
                 "file":
                 metadata,
                 "name":
                 "test",
                 "authorization_flow":
                 create_test_flow(FlowDesignation.AUTHORIZATION).slug,
             },
             format="multipart",
         )
     self.assertEqual(204, response.status_code)
 def setUp(self):
     super().setUp()
     # Ensure that local connection have been created
     outpost_local_connection()
     self.provider: ProxyProvider = ProxyProvider.objects.create(
         name="test",
         internal_host="http://localhost",
         external_host="http://localhost",
         authorization_flow=create_test_flow(),
     )
     self.service_connection = KubernetesServiceConnection.objects.first()
     self.outpost: Outpost = Outpost.objects.create(
         name="test",
         type=OutpostType.PROXY,
         service_connection=self.service_connection,
     )
     self.outpost.providers.add(self.provider)
     self.outpost.save()
Exemple #26
0
    def test_service_account_permissions(self):
        """Test that the service account has correct permissions"""
        provider: ProxyProvider = ProxyProvider.objects.create(
            name="test",
            internal_host="http://localhost",
            external_host="http://localhost",
            authorization_flow=create_test_flow(),
        )
        outpost: Outpost = Outpost.objects.create(
            name="test",
            type=OutpostType.PROXY,
        )

        # Before we add a provider, the user should only have access to the outpost
        permissions = UserObjectPermission.objects.filter(user=outpost.user)
        self.assertEqual(len(permissions), 1)
        self.assertEqual(permissions[0].object_pk, str(outpost.pk))

        # We add a provider, user should only have access to outpost and provider
        outpost.providers.add(provider)
        permissions = UserObjectPermission.objects.filter(user=outpost.user).order_by(
            "content_type__model"
        )
        self.assertEqual(len(permissions), 2)
        self.assertEqual(permissions[0].object_pk, str(outpost.pk))
        self.assertEqual(permissions[1].object_pk, str(provider.pk))

        # Provider requires a certificate-key-pair, user should have permissions for it
        keypair = create_test_cert()
        provider.certificate = keypair
        provider.save()
        permissions = UserObjectPermission.objects.filter(user=outpost.user).order_by(
            "content_type__model"
        )
        self.assertEqual(len(permissions), 3)
        self.assertEqual(permissions[0].object_pk, str(keypair.pk))
        self.assertEqual(permissions[1].object_pk, str(outpost.pk))
        self.assertEqual(permissions[2].object_pk, str(provider.pk))

        # Remove provider from outpost, user should only have access to outpost
        outpost.providers.remove(provider)
        permissions = UserObjectPermission.objects.filter(user=outpost.user)
        self.assertEqual(len(permissions), 1)
        self.assertEqual(permissions[0].object_pk, str(outpost.pk))
Exemple #27
0
 def test_auth_code_view(self):
     """test request param"""
     provider = OAuth2Provider.objects.create(
         name="test",
         client_id=generate_id(),
         client_secret=generate_key(),
         authorization_flow=create_test_flow(),
         redirect_uris="http://local.invalid",
         signing_key=create_test_cert(),
     )
     # Needs to be assigned to an application for iss to be set
     self.app.provider = provider
     self.app.save()
     header = b64encode(f"{provider.client_id}:{provider.client_secret}".
                        encode()).decode()
     user = create_test_admin_user()
     code = AuthorizationCode.objects.create(code="foobar",
                                             provider=provider,
                                             user=user,
                                             is_open_id=True)
     response = self.client.post(
         reverse("authentik_providers_oauth2:token"),
         data={
             "grant_type": GRANT_TYPE_AUTHORIZATION_CODE,
             "code": code.code,
             "redirect_uri": "http://local.invalid",
         },
         HTTP_AUTHORIZATION=f"Basic {header}",
     )
     new_token: RefreshToken = RefreshToken.objects.filter(
         user=user).first()
     self.assertJSONEqual(
         response.content.decode(),
         {
             "access_token": new_token.access_token,
             "refresh_token": new_token.refresh_token,
             "token_type": "bearer",
             "expires_in": 2592000,
             "id_token": provider.encode(new_token.id_token.to_dict(), ),
         },
     )
     self.validate_jwt(new_token, provider)
Exemple #28
0
    def test_recovery_email(self):
        """Test user recovery link"""
        self.user.email = "*****@*****.**"
        self.user.save()
        flow = create_test_flow(FlowDesignation.RECOVERY)
        tenant: Tenant = create_test_tenant()
        tenant.flow_recovery = flow
        tenant.save()

        stage = EmailStage.objects.create(name="email")

        self.client.force_login(self.admin)
        response = self.client.get(
            reverse(
                "authentik_api:user-recovery-email",
                kwargs={"pk": self.user.pk},
            )
            + f"?email_stage={stage.pk}"
        )
        self.assertEqual(response.status_code, 204)
 def test_signed_detached_static(self):
     """Test request with detached signature,
     taken from https://www.samltool.com/generic_sso_req.php"""
     static_keypair = CertificateKeyPair.objects.create(
         name="samltool", certificate_data=REDIRECT_CERT)
     provider = SAMLProvider(
         name="samltool",
         authorization_flow=create_test_flow(),
         acs_url="https://10.120.20.200/saml-sp/SAML2/POST",
         audience="https://10.120.20.200/saml-sp/SAML2/POST",
         issuer="https://10.120.20.200/saml-sp/SAML2/POST",
         signing_kp=static_keypair,
         verification_kp=static_keypair,
     )
     parsed_request = AuthNRequestParser(provider).parse_detached(
         REDIRECT_REQUEST, REDIRECT_RELAY_STATE, REDIRECT_SIGNATURE,
         REDIRECT_SIG_ALG)
     self.assertEqual(parsed_request.id,
                      "_dcf55fcd27a887e60a7ef9ee6fd3adab")
     self.assertEqual(parsed_request.name_id_policy,
                      SAML_NAME_ID_FORMAT_UNSPECIFIED)
     self.assertEqual(parsed_request.relay_state, REDIRECT_RELAY_STATE)
Exemple #30
0
    def test_kubernetes_controller_static(self):
        """Test Kubernetes Controller"""
        provider: ProxyProvider = ProxyProvider.objects.create(
            name="test",
            internal_host="http://localhost",
            external_host="http://localhost",
            authorization_flow=create_test_flow(),
        )
        service_connection = KubernetesServiceConnection.objects.first()
        outpost: Outpost = Outpost.objects.create(
            name="test",
            type=OutpostType.PROXY,
            service_connection=service_connection,
        )
        outpost.providers.add(provider)
        outpost.save()

        self.controller = ProxyKubernetesController(outpost,
                                                    service_connection)
        manifest = self.controller.get_static_deployment()
        self.assertEqual(
            len(list(yaml.load_all(manifest, Loader=yaml.SafeLoader))), 4)