From aa2702da5cc699a3811057b2d0a5659eeabe0374 Mon Sep 17 00:00:00 2001 From: Michael Collins <15347726+michaeljcollinsuk@users.noreply.github.com> Date: Mon, 12 Feb 2024 17:15:10 +0000 Subject: [PATCH] Bugfix/app repo secrets (#1247) * Add method to build App IAM role arn * Update env secrets created when creating auth0 client Adds AWS_DATA_ACCOUNT_ID and APP_ROLE_ARN to secrets that are then used to deploy an app. These are added to both environmnets although currently both values will be the same. This allows it to be extended in the future to have different values for different environments. * Remove unused code --- controlpanel/api/cluster.py | 16 +++++++++++----- controlpanel/api/models/app.py | 4 ++++ controlpanel/frontend/views/apps_mng.py | 10 ---------- tests/api/cluster/test_app.py | 18 ++++++++++++++++++ tests/api/models/test_app.py | 5 +++++ 5 files changed, 38 insertions(+), 15 deletions(-) diff --git a/controlpanel/api/cluster.py b/controlpanel/api/cluster.py index 23e5b5dda..bcc068801 100644 --- a/controlpanel/api/cluster.py +++ b/controlpanel/api/cluster.py @@ -388,6 +388,8 @@ class App(EntityResource): AUTH0_CONNECTIONS = "AUTH0_CONNECTIONS" AUTHENTICATION_REQUIRED = "AUTHENTICATION_REQUIRED" AUTH0_PASSWORDLESS = "AUTH0_PASSWORDLESS" + APP_ROLE_ARN = "APP_ROLE_ARN" + DATA_ACCOUNT_ID = 'DATA_ACCOUNT_ID' def __init__(self, app, github_api_token=None, auth0_instance=None): super(App, self).__init__() @@ -411,7 +413,9 @@ def create_or_update_secrets(self, env_name, secret_data): def _create_secrets(self, env_name, client=None): secret_data: dict = { - App.IP_RANGES: self.app.env_allowed_ip_ranges(env_name=env_name) + App.IP_RANGES: self.app.env_allowed_ip_ranges(env_name=env_name), + App.APP_ROLE_ARN: self.app.iam_role_arn, + App.DATA_ACCOUNT_ID: settings.AWS_DATA_ACCOUNT_ID } if client: secret_data[App.AUTH0_CLIENT_ID] = client["client_id"] @@ -651,12 +655,13 @@ def get_env_vars(self, env_name): return app_env_vars def create_auth_settings( - self, env_name, disable_authentication=False, connections=None, app_domain=None + self, env_name, disable_authentication=False, connections=None, app_domain=None ): client = None group = None - connections = connections or \ - {auth0.ExtendedAuth0.DEFAULT_CONNECTION_OPTION: {}} + if connections is None: + connections = {auth0.ExtendedAuth0.DEFAULT_CONNECTION_OPTION: {}} + if not disable_authentication: client, group = self._get_auth0_instance().setup_auth0_client( client_name=self.app.auth0_client_name(env_name), @@ -665,7 +670,8 @@ def create_auth_settings( app_domain=app_domain ) self.app.save_auth_settings( - env_name=env_name, client=client, group=group) + env_name=env_name, client=client, group=group + ) self._create_secrets(env_name, client=client) self._create_env_vars( env_name, diff --git a/controlpanel/api/models/app.py b/controlpanel/api/models/app.py index 88359206f..288d53811 100644 --- a/controlpanel/api/models/app.py +++ b/controlpanel/api/models/app.py @@ -79,6 +79,10 @@ def _repo_name(self): def release_name(self): return webapp_release_name(self._repo_name) + @property + def iam_role_arn(self): + return cluster.iam_arn(f"role/{self.iam_role_name}") + def get_group_id(self, env_name): return self.get_auth_client(env_name).get("group_id") diff --git a/controlpanel/frontend/views/apps_mng.py b/controlpanel/frontend/views/apps_mng.py index 24b7b9b19..c930b52f1 100644 --- a/controlpanel/frontend/views/apps_mng.py +++ b/controlpanel/frontend/views/apps_mng.py @@ -81,16 +81,6 @@ def _add_ip_allowlists(self, app, envs, ip_allowlists): for env in envs: AppIPAllowList.objects.update_records(app, env, ip_allowlists) - def _create_auth_settigs( - self, app, envs, github_api_token, disable_authentication, connections - ): - for env in envs: - cluster.App(app, github_api_token).create_auth_settings( - env_name=env, - disable_authentication=disable_authentication, - connections=connections, - ) - def _create_or_link_datasource(self, app, user, bucket_data): if bucket_data.get("new_datasource_name"): bucket = S3Bucket.objects.create( diff --git a/tests/api/cluster/test_app.py b/tests/api/cluster/test_app.py index bafa396f1..7530b755d 100644 --- a/tests/api/cluster/test_app.py +++ b/tests/api/cluster/test_app.py @@ -4,6 +4,7 @@ # Third-party import pytest +from django.conf import settings # First-party/Local from controlpanel.api import cluster, models @@ -156,5 +157,22 @@ def test_update_auth_connections(app, ExtendedAuth0): existing_conns='github') +@patch("controlpanel.api.models.App.env_allowed_ip_ranges", new=MagicMock(return_value="1.2.3")) +def test_create_secrets(app): + app_cluster = cluster.App(app) + secrets = { + app_cluster.IP_RANGES: "1.2.3", + app_cluster.APP_ROLE_ARN: app.iam_role_arn, + app_cluster.DATA_ACCOUNT_ID: settings.AWS_DATA_ACCOUNT_ID + } + with patch.object(app_cluster, "create_or_update_secrets"): + app_cluster._create_secrets(env_name="dev", client=None) + app_cluster.create_or_update_secrets.assert_called_once_with( + env_name="dev", + secret_data=secrets + ) + + +# TODO can this be removed? mock_ingress = MagicMock(name="Ingress") mock_ingress.spec.rules = [MagicMock(name="Rule", host="test-app.example.com")] diff --git a/tests/api/models/test_app.py b/tests/api/models/test_app.py index 3d81825ff..c9132c5b0 100644 --- a/tests/api/models/test_app.py +++ b/tests/api/models/test_app.py @@ -204,3 +204,8 @@ def test_app_allowed_ip_ranges(): full_app_ip_ranges = app.app_allowed_ip_ranges assert " " not in full_app_ip_ranges assert len(full_app_ip_ranges.split(",")) == 4 + + +def test_iam_role_arn(): + app = App(slug="example-app") + assert app.iam_role_arn == f"arn:aws:iam::{settings.AWS_DATA_ACCOUNT_ID}:role/test_app_example-app"