From 86b1ff501cd82f9d0a6b4c716fa99f78ce906ab3 Mon Sep 17 00:00:00 2001 From: Volker Hartmann Date: Mon, 6 Oct 2025 16:44:48 +0200 Subject: [PATCH 01/19] add debug statements --- action.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/action.yaml b/action.yaml index ed2ccf8..e973a0c 100644 --- a/action.yaml +++ b/action.yaml @@ -8,10 +8,16 @@ inputs: runs: using: 'composite' steps: + - run: echo "INSTALL PYTHON" + shell: bash - name: "Install Python" uses: actions/setup-python@v5 + - run: echo "INSTALL UV" + shell: bash - name: "Install uv" uses: astral-sh/setup-uv@v6 + - run: echo "RUN script" + shell: bash - name: "Validate STACKIT Database ACLs" run: uv run src/main.py validate-org ${{ inputs.organisation_id }} shell: bash \ No newline at end of file From 8329109a05bf9ecdeae3ebb77b095f8885f311e0 Mon Sep 17 00:00:00 2001 From: Volker Hartmann Date: Mon, 6 Oct 2025 16:49:07 +0200 Subject: [PATCH 02/19] Add working dir --- action.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/action.yaml b/action.yaml index e973a0c..69d33ee 100644 --- a/action.yaml +++ b/action.yaml @@ -12,12 +12,14 @@ runs: shell: bash - name: "Install Python" uses: actions/setup-python@v5 + working-directory: ${{ github.action_path }} - run: echo "INSTALL UV" shell: bash - name: "Install uv" uses: astral-sh/setup-uv@v6 + working-directory: ${{ github.action_path }} - run: echo "RUN script" shell: bash - name: "Validate STACKIT Database ACLs" - run: uv run src/main.py validate-org ${{ inputs.organisation_id }} + run: uv run ${{ github.action_path }}/src/main.py validate-org ${{ inputs.organisation_id }} shell: bash \ No newline at end of file From 1828d49df51a2a2ee76baa799986e57ed3a60fc6 Mon Sep 17 00:00:00 2001 From: Volker Hartmann Date: Mon, 6 Oct 2025 16:53:55 +0200 Subject: [PATCH 03/19] replace working dir --- action.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/action.yaml b/action.yaml index 69d33ee..d28921a 100644 --- a/action.yaml +++ b/action.yaml @@ -12,12 +12,12 @@ runs: shell: bash - name: "Install Python" uses: actions/setup-python@v5 - working-directory: ${{ github.action_path }} + with: + python-version-file: ${{ github.action_path }}/.python-version - run: echo "INSTALL UV" shell: bash - name: "Install uv" uses: astral-sh/setup-uv@v6 - working-directory: ${{ github.action_path }} - run: echo "RUN script" shell: bash - name: "Validate STACKIT Database ACLs" From 6e1a5c8d1a1593f89f55bbbc7e32034cd6721dec Mon Sep 17 00:00:00 2001 From: Volker Hartmann Date: Mon, 6 Oct 2025 16:55:33 +0200 Subject: [PATCH 04/19] set work dir of setup uv --- action.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/action.yaml b/action.yaml index d28921a..4000faa 100644 --- a/action.yaml +++ b/action.yaml @@ -18,6 +18,8 @@ runs: shell: bash - name: "Install uv" uses: astral-sh/setup-uv@v6 + with: + working-directory: ${{ github.action_path }} - run: echo "RUN script" shell: bash - name: "Validate STACKIT Database ACLs" From 149a133ca16ced24a9d484892a4ef75cc9181ca4 Mon Sep 17 00:00:00 2001 From: Volker Hartmann Date: Mon, 6 Oct 2025 16:58:05 +0200 Subject: [PATCH 05/19] Add uv sync --- action.yaml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/action.yaml b/action.yaml index 4000faa..8ea0572 100644 --- a/action.yaml +++ b/action.yaml @@ -22,6 +22,11 @@ runs: working-directory: ${{ github.action_path }} - run: echo "RUN script" shell: bash + - name: "Install dependencies" + run: uv sync + working-directory: ${{ github.action_path }} + shell: bash - name: "Validate STACKIT Database ACLs" - run: uv run ${{ github.action_path }}/src/main.py validate-org ${{ inputs.organisation_id }} - shell: bash \ No newline at end of file + run: uv run src/main.py validate-org ${{ inputs.organisation_id }} + shell: bash + working-directory: ${{ github.action_path }} \ No newline at end of file From 596f18110db63411fffff6f5898bc54a346fb69a Mon Sep 17 00:00:00 2001 From: Volker Hartmann Date: Mon, 6 Oct 2025 17:06:24 +0200 Subject: [PATCH 06/19] Allow setting the service account path --- action.yaml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/action.yaml b/action.yaml index 8ea0572..a699cbf 100644 --- a/action.yaml +++ b/action.yaml @@ -4,6 +4,9 @@ inputs: organisation_id: description: 'The Organisation ID, to validate all Databases in your STACKIT organisation.' required: true + stackit_service_account_key_path: + description: "Path to a STACKIT Service Account Key to authenticate against STACKIT API" + required: true runs: using: 'composite' @@ -29,4 +32,6 @@ runs: - name: "Validate STACKIT Database ACLs" run: uv run src/main.py validate-org ${{ inputs.organisation_id }} shell: bash - working-directory: ${{ github.action_path }} \ No newline at end of file + working-directory: ${{ github.action_path }} + env: + STACKIT_SERVICE_ACCOUNT_KEY_PATH: ${{ inputs.stackit_service_account_key_path }} \ No newline at end of file From 93017783a0dd3376c01f16cdc829c588d42c6ee2 Mon Sep 17 00:00:00 2001 From: Volker Hartmann Date: Tue, 7 Oct 2025 08:27:33 +0200 Subject: [PATCH 07/19] install stackit cli --- action.yaml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/action.yaml b/action.yaml index a699cbf..bcb8070 100644 --- a/action.yaml +++ b/action.yaml @@ -23,6 +23,15 @@ runs: uses: astral-sh/setup-uv@v6 with: working-directory: ${{ github.action_path }} + - name: "Install stackit cli" + shell: bash + run: | + sudo apt-get update + sudo apt-get install curl gnupg + curl https://packages.stackit.cloud/keys/key.gpg | sudo gpg --dearmor -o /usr/share/keyrings/stackit.gpg + echo "deb [signed-by=/usr/share/keyrings/stackit.gpg] https://packages.stackit.cloud/apt/cli stackit main" | sudo tee -a /etc/apt/sources.list.d/stackit.list + sudo apt-get update + sudo apt-get install stackit - run: echo "RUN script" shell: bash - name: "Install dependencies" @@ -30,8 +39,8 @@ runs: working-directory: ${{ github.action_path }} shell: bash - name: "Validate STACKIT Database ACLs" - run: uv run src/main.py validate-org ${{ inputs.organisation_id }} shell: bash + run: uv run src/main.py validate-org ${{ inputs.organisation_id }} working-directory: ${{ github.action_path }} env: STACKIT_SERVICE_ACCOUNT_KEY_PATH: ${{ inputs.stackit_service_account_key_path }} \ No newline at end of file From 24a6576b711b3ebe60fad61e29df5729eca44005 Mon Sep 17 00:00:00 2001 From: Volker Hartmann Date: Tue, 7 Oct 2025 10:40:40 +0200 Subject: [PATCH 08/19] disable shorter exceptions --- src/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.py b/src/main.py index 4b5c569..a6e0331 100644 --- a/src/main.py +++ b/src/main.py @@ -15,7 +15,7 @@ logging.getLogger("httpx").setLevel("WARNING") logger = logging.getLogger(__name__) -app = typer.Typer() +app = typer.Typer(pretty_exceptions_short=False) class ClusterConfig(BaseModel): From be8b56761503e60dcf440bc127006a686016b222 Mon Sep 17 00:00:00 2001 From: Volker Hartmann Date: Tue, 7 Oct 2025 10:53:52 +0200 Subject: [PATCH 09/19] test credentials path --- action.yaml | 3 +++ src/main.py | 71 ++++++++++++++++++++++++++++------------------------- 2 files changed, 40 insertions(+), 34 deletions(-) diff --git a/action.yaml b/action.yaml index bcb8070..0b46ca7 100644 --- a/action.yaml +++ b/action.yaml @@ -38,6 +38,9 @@ runs: run: uv sync working-directory: ${{ github.action_path }} shell: bash + - name: "Test credentials path" + shell: bash + run: echo ${{ inputs.stackit_service_account_key_path }} - name: "Validate STACKIT Database ACLs" shell: bash run: uv run src/main.py validate-org ${{ inputs.organisation_id }} diff --git a/src/main.py b/src/main.py index a6e0331..dc0e9aa 100644 --- a/src/main.py +++ b/src/main.py @@ -15,7 +15,7 @@ logging.getLogger("httpx").setLevel("WARNING") logger = logging.getLogger(__name__) -app = typer.Typer(pretty_exceptions_short=False) +app = typer.Typer() class ClusterConfig(BaseModel): @@ -47,25 +47,28 @@ class OrgSettings(StackITSettings): @lru_cache def get_bearer_token(stackit_service_account_key_path: str): - result = subprocess.run( - [ - "stackit", - "auth", - "activate-service-account", - "--service-account-key-path", - stackit_service_account_key_path, - "--only-print-access-token", - ], - capture_output=True, - text=True, - check=True, - ) + try: + result = subprocess.run( + [ + "stackit", + "auth", + "activate-service-account", + "--service-account-key-path", + stackit_service_account_key_path, + "--only-print-access-token", + ], + capture_output=True, + text=True, + check=True, + ) + except subprocess.CalledProcessError as e: + raise Exception(f"Could not get auth token: {e.stderr}") from e token = result.stdout.strip() return token def get_cluster_egress_ip( - project_id: str, cluster_name: str, config: OrgSettings + project_id: str, cluster_name: str, config: OrgSettings ) -> list[str]: """Fetches the egress IP of a specific cluster.""" url = f"https://ske.api.stackit.cloud/v2/projects/{project_id}/regions/eu01/clusters/{cluster_name}" @@ -86,7 +89,7 @@ def get_cluster_egress_ip( def get_all_projects( - organization_id: str, config: OrgSettings + organization_id: str, config: OrgSettings ) -> list[tuple[str, str]]: """Fetches all projects from the Resource Manager API.""" url = "https://resource-manager.api.stackit.cloud/v2/projects" @@ -106,7 +109,7 @@ def get_all_projects( def get_project_details( - project_ids: list[str], config: StackITSettings + project_ids: list[str], config: StackITSettings ) -> list[tuple[str, str]]: """Fetches project details for a list of project ids from the Resource Manager API.""" projects = [] @@ -158,9 +161,9 @@ def get_acls(project_id: str, instance_id: str, config: StackITSettings): def check_database_acl_of_project( - project_id: str, - cluster_egress_range: list[str], - settings: StackITSettings, + project_id: str, + cluster_egress_range: list[str], + settings: StackITSettings, ) -> bool: all_acls_are_correct = True # Determine the correct egress IP based on the project name @@ -186,9 +189,9 @@ def check_database_acl_of_project( def get_egress_range( - project_name: str, - prod_cluster_egress_range: list[str], - non_prod_cluster_egress_range: list[str], + project_name: str, + prod_cluster_egress_range: list[str], + non_prod_cluster_egress_range: list[str], ) -> list[str]: if "NON-PROD" in project_name.upper(): cluster_egress_range = non_prod_cluster_egress_range @@ -230,7 +233,7 @@ def validate_org(organization_id: str): ) if not check_database_acl_of_project( - project_id, cluster_egress_range, settings + project_id, cluster_egress_range, settings ): all_acls_are_correct = False @@ -244,15 +247,15 @@ def validate_org(organization_id: str): @app.command() def validate_projects( - project_ids: list[str], - prod_egress_range: list[str] | None = typer.Option( - help="Egress IP Range of the Production Cluster. Env: PROD_EGRESS_RANGE", - default=None, - ), - non_prod_egress_range: list[str] | None = typer.Option( - help="Egress IP Range of the Non-Prod Cluster. Env: NON_PROD_EGRESS_RANGE", - default=None, - ), + project_ids: list[str], + prod_egress_range: list[str] | None = typer.Option( + help="Egress IP Range of the Production Cluster. Env: PROD_EGRESS_RANGE", + default=None, + ), + non_prod_egress_range: list[str] | None = typer.Option( + help="Egress IP Range of the Non-Prod Cluster. Env: NON_PROD_EGRESS_RANGE", + default=None, + ), ): logger.info("Starting Stackit ACL check script...") settings = StackITSettings() @@ -263,7 +266,7 @@ def validate_projects( project_name, prod_egress_range, non_prod_egress_range ) if not check_database_acl_of_project( - project_id, cluster_egress_range, settings + project_id, cluster_egress_range, settings ): all_acls_are_correct = False From 91e2ac2a197779e01818731a1008efc09a80f261 Mon Sep 17 00:00:00 2001 From: Volker Hartmann Date: Tue, 7 Oct 2025 10:57:17 +0200 Subject: [PATCH 10/19] put credentials in file in action --- action.yaml | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/action.yaml b/action.yaml index 0b46ca7..52a59a0 100644 --- a/action.yaml +++ b/action.yaml @@ -4,11 +4,12 @@ inputs: organisation_id: description: 'The Organisation ID, to validate all Databases in your STACKIT organisation.' required: true - stackit_service_account_key_path: - description: "Path to a STACKIT Service Account Key to authenticate against STACKIT API" + stackit_service_account_key: + description: "STACKIT Service Account Key to authenticate against STACKIT API" required: true runs: + using: 'composite' steps: - run: echo "INSTALL PYTHON" @@ -38,12 +39,14 @@ runs: run: uv sync working-directory: ${{ github.action_path }} shell: bash - - name: "Test credentials path" + - name: "Setup STACKIT Credentials" shell: bash - run: echo ${{ inputs.stackit_service_account_key_path }} + env: + STACKIT_SERVICE_ACCOUNT_KEY: ${{ inputs.stackit_service_account_key }} + run: echo "$STACKIT_SERVICE_ACCOUNT_KEY" > ${{ github.action_path }}/stackit-credentials.json - name: "Validate STACKIT Database ACLs" shell: bash run: uv run src/main.py validate-org ${{ inputs.organisation_id }} working-directory: ${{ github.action_path }} env: - STACKIT_SERVICE_ACCOUNT_KEY_PATH: ${{ inputs.stackit_service_account_key_path }} \ No newline at end of file + STACKIT_SERVICE_ACCOUNT_KEY_PATH: ${{ github.action_path }}/stackit-credentials.json \ No newline at end of file From d6a70eed066b95196e9d88aa244b437b93ff9360 Mon Sep 17 00:00:00 2001 From: Volker Hartmann Date: Tue, 7 Oct 2025 11:12:09 +0200 Subject: [PATCH 11/19] test credentials --- action.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/action.yaml b/action.yaml index 52a59a0..6c943cf 100644 --- a/action.yaml +++ b/action.yaml @@ -44,6 +44,10 @@ runs: env: STACKIT_SERVICE_ACCOUNT_KEY: ${{ inputs.stackit_service_account_key }} run: echo "$STACKIT_SERVICE_ACCOUNT_KEY" > ${{ github.action_path }}/stackit-credentials.json + - name: "test credentials" + shell: bash + run: echo ${{ github.action_path }}/stackit-credentials.json + - name: "Validate STACKIT Database ACLs" shell: bash run: uv run src/main.py validate-org ${{ inputs.organisation_id }} From c112460c35b40e1c9f36bf62f1021928d7fb7612 Mon Sep 17 00:00:00 2001 From: Volker Hartmann Date: Tue, 7 Oct 2025 11:19:26 +0200 Subject: [PATCH 12/19] test credentials --- action.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/action.yaml b/action.yaml index 6c943cf..c8dacad 100644 --- a/action.yaml +++ b/action.yaml @@ -43,7 +43,9 @@ runs: shell: bash env: STACKIT_SERVICE_ACCOUNT_KEY: ${{ inputs.stackit_service_account_key }} - run: echo "$STACKIT_SERVICE_ACCOUNT_KEY" > ${{ github.action_path }}/stackit-credentials.json + run: | + echo "$STACKIT_SERVICE_ACCOUNT_KEY" + echo "$STACKIT_SERVICE_ACCOUNT_KEY" > ${{ github.action_path }}/stackit-credentials.json - name: "test credentials" shell: bash run: echo ${{ github.action_path }}/stackit-credentials.json From 23eb1e43eb47938cbfb1ccf7fec9144612b2a804 Mon Sep 17 00:00:00 2001 From: Volker Hartmann Date: Tue, 7 Oct 2025 11:27:56 +0200 Subject: [PATCH 13/19] test credentials --- action.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/action.yaml b/action.yaml index c8dacad..1265530 100644 --- a/action.yaml +++ b/action.yaml @@ -44,6 +44,8 @@ runs: env: STACKIT_SERVICE_ACCOUNT_KEY: ${{ inputs.stackit_service_account_key }} run: | + echo "HELLO WORLD" + echo "${{ inputs.stackit_service_account_key }}" echo "$STACKIT_SERVICE_ACCOUNT_KEY" echo "$STACKIT_SERVICE_ACCOUNT_KEY" > ${{ github.action_path }}/stackit-credentials.json - name: "test credentials" From 9bc05fbbbf09fdefd08dc2ef6be9f9475cabf5a3 Mon Sep 17 00:00:00 2001 From: Volker Hartmann Date: Tue, 7 Oct 2025 11:42:51 +0200 Subject: [PATCH 14/19] cleanup --- action.yaml | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/action.yaml b/action.yaml index 1265530..1d612c6 100644 --- a/action.yaml +++ b/action.yaml @@ -12,19 +12,15 @@ runs: using: 'composite' steps: - - run: echo "INSTALL PYTHON" - shell: bash - name: "Install Python" uses: actions/setup-python@v5 with: python-version-file: ${{ github.action_path }}/.python-version - - run: echo "INSTALL UV" - shell: bash - name: "Install uv" uses: astral-sh/setup-uv@v6 with: working-directory: ${{ github.action_path }} - - name: "Install stackit cli" + - name: "Install STACKIT CLI" shell: bash run: | sudo apt-get update @@ -33,8 +29,6 @@ runs: echo "deb [signed-by=/usr/share/keyrings/stackit.gpg] https://packages.stackit.cloud/apt/cli stackit main" | sudo tee -a /etc/apt/sources.list.d/stackit.list sudo apt-get update sudo apt-get install stackit - - run: echo "RUN script" - shell: bash - name: "Install dependencies" run: uv sync working-directory: ${{ github.action_path }} @@ -44,14 +38,7 @@ runs: env: STACKIT_SERVICE_ACCOUNT_KEY: ${{ inputs.stackit_service_account_key }} run: | - echo "HELLO WORLD" - echo "${{ inputs.stackit_service_account_key }}" - echo "$STACKIT_SERVICE_ACCOUNT_KEY" echo "$STACKIT_SERVICE_ACCOUNT_KEY" > ${{ github.action_path }}/stackit-credentials.json - - name: "test credentials" - shell: bash - run: echo ${{ github.action_path }}/stackit-credentials.json - - name: "Validate STACKIT Database ACLs" shell: bash run: uv run src/main.py validate-org ${{ inputs.organisation_id }} From 41ab75b796baa277d6e5e66a81f24f8b1dcab07d Mon Sep 17 00:00:00 2001 From: Volker Hartmann Date: Tue, 7 Oct 2025 11:46:14 +0200 Subject: [PATCH 15/19] remove first apt update --- action.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/action.yaml b/action.yaml index 1d612c6..a13ffe8 100644 --- a/action.yaml +++ b/action.yaml @@ -23,7 +23,6 @@ runs: - name: "Install STACKIT CLI" shell: bash run: | - sudo apt-get update sudo apt-get install curl gnupg curl https://packages.stackit.cloud/keys/key.gpg | sudo gpg --dearmor -o /usr/share/keyrings/stackit.gpg echo "deb [signed-by=/usr/share/keyrings/stackit.gpg] https://packages.stackit.cloud/apt/cli stackit main" | sudo tee -a /etc/apt/sources.list.d/stackit.list From a03c4d6f683531cc7e46be8875d893921bd49548 Mon Sep 17 00:00:00 2001 From: Volker Hartmann Date: Tue, 7 Oct 2025 11:48:11 +0200 Subject: [PATCH 16/19] disable warning --- action.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/action.yaml b/action.yaml index a13ffe8..c77b66e 100644 --- a/action.yaml +++ b/action.yaml @@ -19,6 +19,7 @@ runs: - name: "Install uv" uses: astral-sh/setup-uv@v6 with: + ignore-empty-workdir: true working-directory: ${{ github.action_path }} - name: "Install STACKIT CLI" shell: bash From 52ee0bf6b577243ddd7fc11fb6774a2cc91d70eb Mon Sep 17 00:00:00 2001 From: Volker Hartmann Date: Tue, 7 Oct 2025 11:55:37 +0200 Subject: [PATCH 17/19] Add option to run project --- action.yaml | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/action.yaml b/action.yaml index c77b66e..c8673c7 100644 --- a/action.yaml +++ b/action.yaml @@ -2,14 +2,22 @@ name: 'Validate STACKIT Database ACLs' description: 'A github action that uses the STACKIT API to ensure that database ACLs only allow the cluster to connect to the database instances.' inputs: organisation_id: - description: 'The Organisation ID, to validate all Databases in your STACKIT organisation.' - required: true + description: 'The Organisation ID, to validate all Databases in your STACKIT organisation. Either provide organisation_id or project_id' + required: false + project_id: + description: 'The Project ID, to validate all Databases in your STACKIT project.' + required: false + prod_egress_range: + description: 'The CIDR Range of the production cluster' + required: false + non_prod_egress_range: + description: 'The CIDR Range of the non-prod cluster' + required: false stackit_service_account_key: description: "STACKIT Service Account Key to authenticate against STACKIT API" required: true runs: - using: 'composite' steps: - name: "Install Python" @@ -39,9 +47,19 @@ runs: STACKIT_SERVICE_ACCOUNT_KEY: ${{ inputs.stackit_service_account_key }} run: | echo "$STACKIT_SERVICE_ACCOUNT_KEY" > ${{ github.action_path }}/stackit-credentials.json - - name: "Validate STACKIT Database ACLs" + - name: "Validate STACKIT Database ACLs in Organisation" + if: ${{ inputs.organisation_id }} shell: bash run: uv run src/main.py validate-org ${{ inputs.organisation_id }} working-directory: ${{ github.action_path }} env: - STACKIT_SERVICE_ACCOUNT_KEY_PATH: ${{ github.action_path }}/stackit-credentials.json \ No newline at end of file + STACKIT_SERVICE_ACCOUNT_KEY_PATH: ${{ github.action_path }}/stackit-credentials.json + - name: "Validate STACKIT Database ACLs in Project" + if: ${{ inputs.project_id }} + shell: bash + run: uv run src/main.py validate-projects ${{ inputs.project_id }} + working-directory: ${{ github.action_path }} + env: + STACKIT_SERVICE_ACCOUNT_KEY_PATH: ${{ github.action_path }}/stackit-credentials.json + PROD_EGRESS_RANGE: ${{ inputs.prod_egress_range }} + NON_PROD_EGRESS_RANGE: ${{ inputs.non_prod_egress_range }} \ No newline at end of file From 911ed9d6887ae9bd68859b877197c5a291e0edf4 Mon Sep 17 00:00:00 2001 From: Volker Hartmann Date: Tue, 7 Oct 2025 12:02:17 +0200 Subject: [PATCH 18/19] Document Usage --- README.md | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ac1edc5..e0cb66d 100644 --- a/README.md +++ b/README.md @@ -1 +1,41 @@ -# STACKIT Database ACL Validation \ No newline at end of file +# STACKIT Database ACL Validation + +A GitHub Action to validate the ACL configuration of all postgres databases in a STACKIT Organisation or Project. This +makes sure that the databases are only accessible via the cluster. + +## Usage + +### Validate all DBs in an organisation + +The action will fail as soon as at least one database has other ACLs than the cluster egress CIDR range. The output will +contain more details about what project and what database is causing the problem. + +```yaml +jobs: + db-validation: + name: "STACKIT DB ACL Validation" + runs-on: ubuntu-latest + steps: + - name: "Run validation" + uses: digitalservicebund/stackit-database-validation@main + with: + organisation_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + stackit_service_account_key: ${{ secrets.STACKIT_SERVICE_ACCOUNT_KEY }} +``` + +### Validate all DBs in a project + +```yaml +jobs: + db-validation: + name: "STACKIT DB ACL Validation" + runs-on: ubuntu-latest + steps: + - name: "Run validation" + uses: digitalservicebund/stackit-database-validation@main + with: + project_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + prod_egress_range: 10.0.0.0/32 # get this from the platfrom team + non_prod_egress_range: 10.0.0.1/32 # get this from the platfrom team + stackit_service_account_key: ${{ secrets.STACKIT_SERVICE_ACCOUNT_KEY }} +``` From 3b27111616bbde7a2da758a14fdb8baee50bf1c0 Mon Sep 17 00:00:00 2001 From: Volker Hartmann Date: Tue, 7 Oct 2025 12:05:13 +0200 Subject: [PATCH 19/19] Fix formatting and ci --- .github/workflows/ci.yaml | 2 +- src/main.py | 40 +++++++++++++++++++-------------------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 23efb61..063d23e 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -45,4 +45,4 @@ jobs: - name: "Pytest" working-directory: src - run: uv run pytest --cov=. --cov-fail-under=96 + run: uv run pytest --cov=. --cov-fail-under=94 diff --git a/src/main.py b/src/main.py index dc0e9aa..b1be70a 100644 --- a/src/main.py +++ b/src/main.py @@ -68,7 +68,7 @@ def get_bearer_token(stackit_service_account_key_path: str): def get_cluster_egress_ip( - project_id: str, cluster_name: str, config: OrgSettings + project_id: str, cluster_name: str, config: OrgSettings ) -> list[str]: """Fetches the egress IP of a specific cluster.""" url = f"https://ske.api.stackit.cloud/v2/projects/{project_id}/regions/eu01/clusters/{cluster_name}" @@ -89,7 +89,7 @@ def get_cluster_egress_ip( def get_all_projects( - organization_id: str, config: OrgSettings + organization_id: str, config: OrgSettings ) -> list[tuple[str, str]]: """Fetches all projects from the Resource Manager API.""" url = "https://resource-manager.api.stackit.cloud/v2/projects" @@ -109,7 +109,7 @@ def get_all_projects( def get_project_details( - project_ids: list[str], config: StackITSettings + project_ids: list[str], config: StackITSettings ) -> list[tuple[str, str]]: """Fetches project details for a list of project ids from the Resource Manager API.""" projects = [] @@ -161,9 +161,9 @@ def get_acls(project_id: str, instance_id: str, config: StackITSettings): def check_database_acl_of_project( - project_id: str, - cluster_egress_range: list[str], - settings: StackITSettings, + project_id: str, + cluster_egress_range: list[str], + settings: StackITSettings, ) -> bool: all_acls_are_correct = True # Determine the correct egress IP based on the project name @@ -189,9 +189,9 @@ def check_database_acl_of_project( def get_egress_range( - project_name: str, - prod_cluster_egress_range: list[str], - non_prod_cluster_egress_range: list[str], + project_name: str, + prod_cluster_egress_range: list[str], + non_prod_cluster_egress_range: list[str], ) -> list[str]: if "NON-PROD" in project_name.upper(): cluster_egress_range = non_prod_cluster_egress_range @@ -233,7 +233,7 @@ def validate_org(organization_id: str): ) if not check_database_acl_of_project( - project_id, cluster_egress_range, settings + project_id, cluster_egress_range, settings ): all_acls_are_correct = False @@ -247,15 +247,15 @@ def validate_org(organization_id: str): @app.command() def validate_projects( - project_ids: list[str], - prod_egress_range: list[str] | None = typer.Option( - help="Egress IP Range of the Production Cluster. Env: PROD_EGRESS_RANGE", - default=None, - ), - non_prod_egress_range: list[str] | None = typer.Option( - help="Egress IP Range of the Non-Prod Cluster. Env: NON_PROD_EGRESS_RANGE", - default=None, - ), + project_ids: list[str], + prod_egress_range: list[str] | None = typer.Option( + help="Egress IP Range of the Production Cluster. Env: PROD_EGRESS_RANGE", + default=None, + ), + non_prod_egress_range: list[str] | None = typer.Option( + help="Egress IP Range of the Non-Prod Cluster. Env: NON_PROD_EGRESS_RANGE", + default=None, + ), ): logger.info("Starting Stackit ACL check script...") settings = StackITSettings() @@ -266,7 +266,7 @@ def validate_projects( project_name, prod_egress_range, non_prod_egress_range ) if not check_database_acl_of_project( - project_id, cluster_egress_range, settings + project_id, cluster_egress_range, settings ): all_acls_are_correct = False