From f6f00449873ade15cb21f85db7da5b664bb3c524 Mon Sep 17 00:00:00 2001 From: Eric Wyles <23637493+ericwyles@users.noreply.github.com> Date: Wed, 14 Aug 2024 08:57:34 -0500 Subject: [PATCH 01/25] feat: add SETUID capability for gitlab runner container security context --- values/common-values.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/values/common-values.yaml b/values/common-values.yaml index f82f025..1d550d0 100644 --- a/values/common-values.yaml +++ b/values/common-values.yaml @@ -50,6 +50,7 @@ securityContext: privileged: false capabilities: drop: ["ALL"] + add: ["SETUID"] service: enabled: true From 28cda4cdaabc17ba2f8e460972ae4b8f771ac41a Mon Sep 17 00:00:00 2001 From: Eric Wyles <23637493+ericwyles@users.noreply.github.com> Date: Wed, 14 Aug 2024 09:21:26 -0500 Subject: [PATCH 02/25] actually more like this --- values/common-values.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/values/common-values.yaml b/values/common-values.yaml index 1d550d0..ac0c8af 100644 --- a/values/common-values.yaml +++ b/values/common-values.yaml @@ -37,6 +37,8 @@ runners: run_as_non_root = true run_as_user = 1001 run_as_group = 0 + [runners.kubernetes.build_container_security_context] + cap_add = ["CAP_SETUID"] concurrent: 50 @@ -50,7 +52,6 @@ securityContext: privileged: false capabilities: drop: ["ALL"] - add: ["SETUID"] service: enabled: true From 0917e38ee0a2bebe4c1c2f58e6b2b3274e9e17a8 Mon Sep 17 00:00:00 2001 From: Eric Wyles <23637493+ericwyles@users.noreply.github.com> Date: Wed, 14 Aug 2024 11:43:23 -0500 Subject: [PATCH 03/25] update doc --- docs/configuration.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/configuration.md b/docs/configuration.md index 40d4f4b..72a9f60 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -2,6 +2,16 @@ GitLab Runners in this package are configured through the upstream [GitLab Runner chart](https://docs.gitlab.com/runner/install/kubernetes.html) as well as a UDS configuration chart that supports the following: +## Node Configuration + +> [!IMPORTANT] +> Any kubernetes node that will be executing gitlab runners must set the sysctl `user.max_user_namespaces` value to nonzero. This is required to run builds inside Linux Containers from the runner pods. This is a [STIG finding](https://www.stigviewer.com/stig/red_hat_enterprise_linux_9/2023-09-13/finding/V-257816) but is `Not Applicable` when running Linux containers. + +Example: +``` +sysctl -w user.max_user_namespaces=30110 +``` + ## Networking Network policies are controlled via the `uds-gitlab-runner-config` chart in accordance with the [common patterns for networking within UDS Software Factory](https://github.com/defenseunicorns/uds-software-factory/blob/main/docs/networking.md). Because GitLab runners do not interact with external resources like databases or object storage they only implement `custom` networking for both the runner namespace and the runner sandbox namespace: From 372fe4c5d4c99764e01c70a28ae8fe8003965ae5 Mon Sep 17 00:00:00 2001 From: Eric Wyles <23637493+ericwyles@users.noreply.github.com> Date: Wed, 14 Aug 2024 11:47:02 -0500 Subject: [PATCH 04/25] formatting --- docs/configuration.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index 72a9f60..b60022d 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -5,10 +5,12 @@ GitLab Runners in this package are configured through the upstream [GitLab Runne ## Node Configuration > [!IMPORTANT] -> Any kubernetes node that will be executing gitlab runners must set the sysctl `user.max_user_namespaces` value to nonzero. This is required to run builds inside Linux Containers from the runner pods. This is a [STIG finding](https://www.stigviewer.com/stig/red_hat_enterprise_linux_9/2023-09-13/finding/V-257816) but is `Not Applicable` when running Linux containers. +> Any kubernetes node that will run GitLab Runner pods must set the sysctl `user.max_user_namespaces` value to nonzero. This is required to run builds inside Linux Containers from the runner pods. +> +> This is a [STIG finding](https://www.stigviewer.com/stig/red_hat_enterprise_linux_9/2023-09-13/finding/V-257816) but is `Not Applicable` when running Linux containers. Example: -``` +```bash sysctl -w user.max_user_namespaces=30110 ``` From 7c6d6124dbe9c0e7290ec7b1d4324511ce07b311 Mon Sep 17 00:00:00 2001 From: Eric Wyles <23637493+ericwyles@users.noreply.github.com> Date: Wed, 14 Aug 2024 11:49:42 -0500 Subject: [PATCH 05/25] formatting --- docs/configuration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/configuration.md b/docs/configuration.md index b60022d..7304779 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -5,7 +5,7 @@ GitLab Runners in this package are configured through the upstream [GitLab Runne ## Node Configuration > [!IMPORTANT] -> Any kubernetes node that will run GitLab Runner pods must set the sysctl `user.max_user_namespaces` value to nonzero. This is required to run builds inside Linux Containers from the runner pods. +> Any kubernetes node that will run GitLab Runner pods must set the sysctl `user.max_user_namespaces` value to nonzero. This is required to run builds inside Linux containers from the runner pods. > > This is a [STIG finding](https://www.stigviewer.com/stig/red_hat_enterprise_linux_9/2023-09-13/finding/V-257816) but is `Not Applicable` when running Linux containers. From 65c81d427c28dcab9551fdfcf75ac5c51c49e8ee Mon Sep 17 00:00:00 2001 From: Eric Wyles <23637493+ericwyles@users.noreply.github.com> Date: Wed, 14 Aug 2024 12:37:24 -0500 Subject: [PATCH 06/25] Update docs/configuration.md Co-authored-by: Wayne Starr --- docs/configuration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/configuration.md b/docs/configuration.md index 7304779..0480d5e 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -5,7 +5,7 @@ GitLab Runners in this package are configured through the upstream [GitLab Runne ## Node Configuration > [!IMPORTANT] -> Any kubernetes node that will run GitLab Runner pods must set the sysctl `user.max_user_namespaces` value to nonzero. This is required to run builds inside Linux containers from the runner pods. +> Any kubernetes node that will run GitLab Runner pods to use tooling like [Buildah](https://buildah.io/) must set sysctl `user.max_user_namespaces` to a nonzero value. This is required to run these container builds inside Linux containers from the runner pods. > > This is a [STIG finding](https://www.stigviewer.com/stig/red_hat_enterprise_linux_9/2023-09-13/finding/V-257816) but is `Not Applicable` when running Linux containers. From e82715b9640be315bc65bc75c64eb8e56d6833f3 Mon Sep 17 00:00:00 2001 From: Eric Wyles <23637493+ericwyles@users.noreply.github.com> Date: Wed, 14 Aug 2024 16:44:18 -0500 Subject: [PATCH 07/25] updates --- chart/templates/uds-policy-exemptions.yaml | 16 ++++++++++++++++ chart/values.yaml | 2 ++ values/common-values.yaml | 8 +++++++- zarf.yaml | 3 +++ 4 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 chart/templates/uds-policy-exemptions.yaml diff --git a/chart/templates/uds-policy-exemptions.yaml b/chart/templates/uds-policy-exemptions.yaml new file mode 100644 index 0000000..d846236 --- /dev/null +++ b/chart/templates/uds-policy-exemptions.yaml @@ -0,0 +1,16 @@ +{{- if not .Values.disableRestrictCapabilitiesExemption }} +apiVersion: uds.dev/v1alpha1 +kind: Exemption +metadata: + name: gitlab-runner-container-building + namespace: uds-policy-exemptions +spec: + exemptions: + - description: Allow more capabilities for container build tools (Buildah) to be able to map user and group IDs + policies: + - RestrictCapabilities + title: "gitlab-runner-container-building" + matcher: + namespace: gitlab-runner-sandbox + name: "^runner-.*" +{{- end }} diff --git a/chart/values.yaml b/chart/values.yaml index 6f5e79c..f097a24 100644 --- a/chart/values.yaml +++ b/chart/values.yaml @@ -7,6 +7,8 @@ serviceAccountName: "gitlab-runner" runnerAuthToken: "###ZARF_VAR_RUNNER_AUTH_TOKEN###" +disableRestrictCapabilitiesExemption: "###ZARF_VAR_DISABLE_RESTRICTCAPABILITIES_EXEMPTION###" + custom: [] # - direction: Egress # remoteGenerated: Anywhere diff --git a/values/common-values.yaml b/values/common-values.yaml index ac0c8af..03200f6 100644 --- a/values/common-values.yaml +++ b/values/common-values.yaml @@ -10,6 +10,8 @@ rbac: resources: [""] verbs: [""] +disableRestrictCapabilitiesExemption: "###ZARF_VAR_DISABLE_RESTRICTCAPABILITIES_EXEMPTION###" + runners: secret: gitlab-gitlab-runner-secret runUntagged: true @@ -39,7 +41,11 @@ runners: run_as_group = 0 [runners.kubernetes.build_container_security_context] cap_add = ["CAP_SETUID"] - + {{- if not .Values.disableRestrictCapabilitiesExemption }} + [runners.kubernetes.build_container_security_context] + [runners.kubernetes.build_container_security_context.capabilities] + add = ["SETUID", "SETGID"] + {{- end }} concurrent: 50 podSecurityContext: diff --git a/zarf.yaml b/zarf.yaml index b7d0cce..523f449 100644 --- a/zarf.yaml +++ b/zarf.yaml @@ -14,6 +14,9 @@ variables: description: The Runner Authentication Token to use when registering the GitLab Runner (if none is provided will register a default instance runner) - name: RUNNER_SANDBOX_NAMESPACE default: gitlab-runner-sandbox + - name: DISABLE_RESTRICTCAPABILITIES_EXEMPTION + description: Set this to true to disable UDS policy exemption for RestrictCapabilities. This will also disable the "SETUID", "SETGID" capabilities on the runner security context since they will not be allowed by pepr. + default: false components: - name: gitlab-runner From c41da1b3af3f65a774c87cbfbe1c1c066a432052 Mon Sep 17 00:00:00 2001 From: Eric Wyles <23637493+ericwyles@users.noreply.github.com> Date: Wed, 14 Aug 2024 16:45:36 -0500 Subject: [PATCH 08/25] don't quote me on that --- chart/values.yaml | 2 +- values/common-values.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/chart/values.yaml b/chart/values.yaml index f097a24..7be9dde 100644 --- a/chart/values.yaml +++ b/chart/values.yaml @@ -7,7 +7,7 @@ serviceAccountName: "gitlab-runner" runnerAuthToken: "###ZARF_VAR_RUNNER_AUTH_TOKEN###" -disableRestrictCapabilitiesExemption: "###ZARF_VAR_DISABLE_RESTRICTCAPABILITIES_EXEMPTION###" +disableRestrictCapabilitiesExemption: ###ZARF_VAR_DISABLE_RESTRICTCAPABILITIES_EXEMPTION### custom: [] # - direction: Egress diff --git a/values/common-values.yaml b/values/common-values.yaml index 03200f6..c24fafb 100644 --- a/values/common-values.yaml +++ b/values/common-values.yaml @@ -10,7 +10,7 @@ rbac: resources: [""] verbs: [""] -disableRestrictCapabilitiesExemption: "###ZARF_VAR_DISABLE_RESTRICTCAPABILITIES_EXEMPTION###" +disableRestrictCapabilitiesExemption: ###ZARF_VAR_DISABLE_RESTRICTCAPABILITIES_EXEMPTION### runners: secret: gitlab-gitlab-runner-secret From 751abeba19b80ed770ca890165e8cbd47683b78a Mon Sep 17 00:00:00 2001 From: Eric Wyles <23637493+ericwyles@users.noreply.github.com> Date: Mon, 19 Aug 2024 11:02:29 -0500 Subject: [PATCH 09/25] wip --- chart/templates/uds-policy-exemptions.yaml | 4 ++-- chart/values.yaml | 2 +- values/common-values.yaml | 15 +++++++-------- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/chart/templates/uds-policy-exemptions.yaml b/chart/templates/uds-policy-exemptions.yaml index d846236..d34e27d 100644 --- a/chart/templates/uds-policy-exemptions.yaml +++ b/chart/templates/uds-policy-exemptions.yaml @@ -1,4 +1,4 @@ -{{- if not .Values.disableRestrictCapabilitiesExemption }} +{{- if .Values.enableRestrictCapabilitiesExemption }} apiVersion: uds.dev/v1alpha1 kind: Exemption metadata: @@ -13,4 +13,4 @@ spec: matcher: namespace: gitlab-runner-sandbox name: "^runner-.*" -{{- end }} +{{- end }} \ No newline at end of file diff --git a/chart/values.yaml b/chart/values.yaml index 7be9dde..6fe84d1 100644 --- a/chart/values.yaml +++ b/chart/values.yaml @@ -7,7 +7,7 @@ serviceAccountName: "gitlab-runner" runnerAuthToken: "###ZARF_VAR_RUNNER_AUTH_TOKEN###" -disableRestrictCapabilitiesExemption: ###ZARF_VAR_DISABLE_RESTRICTCAPABILITIES_EXEMPTION### +enableRestrictCapabilitiesExemption: true custom: [] # - direction: Egress diff --git a/values/common-values.yaml b/values/common-values.yaml index c24fafb..425f862 100644 --- a/values/common-values.yaml +++ b/values/common-values.yaml @@ -10,7 +10,7 @@ rbac: resources: [""] verbs: [""] -disableRestrictCapabilitiesExemption: ###ZARF_VAR_DISABLE_RESTRICTCAPABILITIES_EXEMPTION### +enableRestrictCapabilitiesExemption: true runners: secret: gitlab-gitlab-runner-secret @@ -35,17 +35,16 @@ runners: "uds/user" = "${UDS_RUN_AS_USER}" "uds/group" = "${UDS_RUN_AS_GROUP}" "uds/network-access-gitlab" = "true" - [runners.kubernetes.helper_container_security_context] - run_as_non_root = true - run_as_user = 1001 - run_as_group = 0 - [runners.kubernetes.build_container_security_context] - cap_add = ["CAP_SETUID"] - {{- if not .Values.disableRestrictCapabilitiesExemption }} + {{- if .Values.enableRestrictCapabilitiesExemption }} [runners.kubernetes.build_container_security_context] [runners.kubernetes.build_container_security_context.capabilities] add = ["SETUID", "SETGID"] {{- end }} + [runners.kubernetes.helper_container_security_context] + run_as_non_root = true + run_as_user = 1001 + run_as_group = 0 + concurrent: 50 podSecurityContext: From 1a277cbc1391d17708892d0191b2222ed752ad4d Mon Sep 17 00:00:00 2001 From: Eric Wyles <23637493+ericwyles@users.noreply.github.com> Date: Wed, 21 Aug 2024 12:29:05 -0500 Subject: [PATCH 10/25] wip --- chart/templates/uds-policy-exemptions.yaml | 4 ++-- chart/values.yaml | 2 +- values/common-values.yaml | 4 ++-- zarf.yaml | 5 ++--- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/chart/templates/uds-policy-exemptions.yaml b/chart/templates/uds-policy-exemptions.yaml index d34e27d..2bd1cbf 100644 --- a/chart/templates/uds-policy-exemptions.yaml +++ b/chart/templates/uds-policy-exemptions.yaml @@ -1,4 +1,4 @@ -{{- if .Values.enableRestrictCapabilitiesExemption }} +{{- if .Values.enableSecurityCapabilities }} apiVersion: uds.dev/v1alpha1 kind: Exemption metadata: @@ -13,4 +13,4 @@ spec: matcher: namespace: gitlab-runner-sandbox name: "^runner-.*" -{{- end }} \ No newline at end of file +{{- end }} diff --git a/chart/values.yaml b/chart/values.yaml index 6fe84d1..b38aa6e 100644 --- a/chart/values.yaml +++ b/chart/values.yaml @@ -7,7 +7,7 @@ serviceAccountName: "gitlab-runner" runnerAuthToken: "###ZARF_VAR_RUNNER_AUTH_TOKEN###" -enableRestrictCapabilitiesExemption: true +enableSecurityCapabilities: true custom: [] # - direction: Egress diff --git a/values/common-values.yaml b/values/common-values.yaml index 425f862..4fec8b8 100644 --- a/values/common-values.yaml +++ b/values/common-values.yaml @@ -10,7 +10,7 @@ rbac: resources: [""] verbs: [""] -enableRestrictCapabilitiesExemption: true +enableSecurityCapabilities: ###ZARF_VAR_ENABLE_SECURITY_CAPABILITIES### runners: secret: gitlab-gitlab-runner-secret @@ -35,7 +35,7 @@ runners: "uds/user" = "${UDS_RUN_AS_USER}" "uds/group" = "${UDS_RUN_AS_GROUP}" "uds/network-access-gitlab" = "true" - {{- if .Values.enableRestrictCapabilitiesExemption }} + {{- if .Values.enableSecurityCapabilities }} [runners.kubernetes.build_container_security_context] [runners.kubernetes.build_container_security_context.capabilities] add = ["SETUID", "SETGID"] diff --git a/zarf.yaml b/zarf.yaml index 523f449..0bdcf27 100644 --- a/zarf.yaml +++ b/zarf.yaml @@ -14,9 +14,8 @@ variables: description: The Runner Authentication Token to use when registering the GitLab Runner (if none is provided will register a default instance runner) - name: RUNNER_SANDBOX_NAMESPACE default: gitlab-runner-sandbox - - name: DISABLE_RESTRICTCAPABILITIES_EXEMPTION - description: Set this to true to disable UDS policy exemption for RestrictCapabilities. This will also disable the "SETUID", "SETGID" capabilities on the runner security context since they will not be allowed by pepr. - default: false + - name: ENABLE_SECURITY_CAPABILITIES + default: "true" components: - name: gitlab-runner From 9cb271501ba17f961ef67646911cf10c55506ad9 Mon Sep 17 00:00:00 2001 From: Eric Wyles <23637493+ericwyles@users.noreply.github.com> Date: Wed, 21 Aug 2024 16:18:19 -0500 Subject: [PATCH 11/25] unbreak my heart --- chart/values.yaml | 2 +- common/zarf.yaml | 2 ++ values/config-values.yaml | 1 + zarf.yaml | 2 +- 4 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 values/config-values.yaml diff --git a/chart/values.yaml b/chart/values.yaml index b38aa6e..3ad82ed 100644 --- a/chart/values.yaml +++ b/chart/values.yaml @@ -7,7 +7,7 @@ serviceAccountName: "gitlab-runner" runnerAuthToken: "###ZARF_VAR_RUNNER_AUTH_TOKEN###" -enableSecurityCapabilities: true +enableSecurityCapabilities: false custom: [] # - direction: Egress diff --git a/common/zarf.yaml b/common/zarf.yaml index 4baa2b7..9f2f2ee 100644 --- a/common/zarf.yaml +++ b/common/zarf.yaml @@ -12,6 +12,8 @@ components: namespace: gitlab-runner version: 0.1.0 localPath: ../chart + valuesFiles: + - ../values/config-values.yaml - name: gitlab-runner namespace: gitlab-runner url: https://charts.gitlab.io diff --git a/values/config-values.yaml b/values/config-values.yaml new file mode 100644 index 0000000..a2dfa7d --- /dev/null +++ b/values/config-values.yaml @@ -0,0 +1 @@ +enableSecurityCapabilities: ###ZARF_VAR_ENABLE_SECURITY_CAPABILITIES### \ No newline at end of file diff --git a/zarf.yaml b/zarf.yaml index 0bdcf27..d2da315 100644 --- a/zarf.yaml +++ b/zarf.yaml @@ -15,7 +15,7 @@ variables: - name: RUNNER_SANDBOX_NAMESPACE default: gitlab-runner-sandbox - name: ENABLE_SECURITY_CAPABILITIES - default: "true" + default: "false" components: - name: gitlab-runner From b2c05c1da034e37fec3904b81fa194f5805a4c90 Mon Sep 17 00:00:00 2001 From: Eric Wyles <23637493+ericwyles@users.noreply.github.com> Date: Wed, 21 Aug 2024 16:22:10 -0500 Subject: [PATCH 12/25] lint --- values/config-values.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/values/config-values.yaml b/values/config-values.yaml index a2dfa7d..c5da88d 100644 --- a/values/config-values.yaml +++ b/values/config-values.yaml @@ -1 +1 @@ -enableSecurityCapabilities: ###ZARF_VAR_ENABLE_SECURITY_CAPABILITIES### \ No newline at end of file +enableSecurityCapabilities: ###ZARF_VAR_ENABLE_SECURITY_CAPABILITIES### From c4cc91eedeadcabab89e4ab215edefb8dc4e2160 Mon Sep 17 00:00:00 2001 From: Eric Wyles <23637493+ericwyles@users.noreply.github.com> Date: Fri, 23 Aug 2024 13:17:37 -0500 Subject: [PATCH 13/25] it works, still refactoring --- .gitignore | 3 + tasks/test.yaml | 38 +++-- tests/common.ts | 107 ++++++++++++ tests/journey/pipeline-run-kitteh.test.ts | 54 ++++++ .../journey/pipeline-run-podman-fail.test.ts | 54 ++++++ .../pipeline-run-podman-success.test.ts | 54 ++++++ tests/journey/pipeline-run.test.ts | 159 +++++++++++------- .../repo-sources/kitteh/.gitlab-ci.yml | 0 .../repo-sources/podman/.gitlab-ci.yml | 6 + tests/journey/repo-sources/podman/Dockerfile | 2 + tests/journey/repo-sources/podman/test.txt | 1 + tests/package/zarf.yaml | 11 -- 12 files changed, 405 insertions(+), 84 deletions(-) create mode 100644 tests/journey/pipeline-run-kitteh.test.ts create mode 100644 tests/journey/pipeline-run-podman-fail.test.ts create mode 100644 tests/journey/pipeline-run-podman-success.test.ts rename .gitlab-ci.yml => tests/journey/repo-sources/kitteh/.gitlab-ci.yml (100%) create mode 100644 tests/journey/repo-sources/podman/.gitlab-ci.yml create mode 100644 tests/journey/repo-sources/podman/Dockerfile create mode 100644 tests/journey/repo-sources/podman/test.txt delete mode 100644 tests/package/zarf.yaml diff --git a/.gitignore b/.gitignore index b5d753f..f91aa23 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,6 @@ overlay-values-* # Dependency files uds-config-gitlab.yaml + +#place where temporary git repos are created +**tmp-repos diff --git a/tasks/test.yaml b/tasks/test.yaml index 38c36d4..67e0e9c 100644 --- a/tasks/test.yaml +++ b/tasks/test.yaml @@ -8,14 +8,8 @@ tasks: # Ensure all GL services are up - task: gitlab-ingress # Run checks on initial deployment - - task: glr-health-check - - task: glr-run-check - # Create a runner token and hide the secret from the GLR package - - task: glr-create-runner-token - - task: glr-backup-registration-secret - # Remove the GLR package and redeploy with the manual token - - task: remove:test-bundle - # TODO: (@WSTARR) Maru will complain about "cyclical" task imports if this imports the deploy task from uds-common. This is a bug: https://github.com/defenseunicorns/maru-runner/issues/122 + - task: glr-registration-check + - task: glr-run-check-defaults - description: Get the current UDS Bundle name cmd: cat bundle/uds-bundle.yaml | ./uds zarf tools yq .metadata.name setVariables: @@ -24,10 +18,19 @@ tasks: cmd: cat bundle/uds-bundle.yaml | ./uds zarf tools yq .metadata.version setVariables: - name: BUNDLE_VERSION + - description: Deploy GitLab runner with SETUID and SETGID capabilities + cmd: UDS_CONFIG=bundle/uds-config.yaml ./uds deploy bundle/uds-bundle-${BUNDLE_NAME}-${UDS_ARCH}-${BUNDLE_VERSION}.tar.zst --confirm --no-progress --set ENABLE_SECURITY_CAPABILITIES=true + - task: glr-run-check-elevated-security-capabilities + # Create a runner token and hide the secret from the GLR package + - task: glr-create-runner-token + - task: glr-backup-registration-secret + # Remove the GLR package and redeploy with the manual token + - task: remove:test-bundle + # TODO: (@WSTARR) Maru will complain about "cyclical" task imports if this imports the deploy task from uds-common. This is a bug: https://github.com/defenseunicorns/maru-runner/issues/122 - description: Deploys the current GitLab runner package cmd: UDS_CONFIG=bundle/uds-config.yaml ./uds deploy bundle/uds-bundle-${BUNDLE_NAME}-${UDS_ARCH}-${BUNDLE_VERSION}.tar.zst --confirm --no-progress --set RUNNER_AUTH_TOKEN=${RUNNER_AUTH_TOKEN} # Check that the runner registered and restore the secret - - task: glr-health-check + - task: glr-registration-check - task: glr-restore-registration-secret - name: gitlab-ingress @@ -45,7 +48,7 @@ tasks: exit 1 fi - - name: glr-health-check + - name: glr-registration-check description: Check the status of Gitlab Runner actions: - description: Check Gitlab Runner Secret @@ -58,12 +61,23 @@ tasks: dir: tests cmd: npm test -- journey/registration.test.ts - - name: glr-run-check + - name: glr-run-check-defaults description: Check that a GitLab repository can trigger a gitlab runner to run actions: - description: Setup a repository and trigger a pipeline job dir: tests - cmd: npm test -- journey/pipeline-run.test.ts + cmd: | + npm test -- journey/pipeline-run-kitteh.test.ts + npm test -- journey/pipeline-run-podman-fail.test.ts + + - name: glr-run-check-elevated-security-capabilities + description: Check that a GitLab repository can trigger a gitlab runner to run + actions: + - description: Setup a repository and trigger a pipeline job + dir: tests + cmd: | + npm test -- journey/pipeline-run-kitteh.test.ts + npm test -- journey/pipeline-run-podman-success.test.ts - name: glr-create-runner-token description: Create a runner auth token and set the variable RUNNER_AUTH_TOKEN diff --git a/tests/common.ts b/tests/common.ts index e266e95..7d5d53a 100644 --- a/tests/common.ts +++ b/tests/common.ts @@ -1,4 +1,9 @@ import { spawnSync } from "child_process"; +import { execSync } from 'child_process'; +import { K8s, kind } from "kubernetes-fluent-client"; +import { rm } from 'fs/promises'; +import * as fs from 'fs'; +import * as path from 'path'; export function zarfExec(args: string[], captureOutput = false) { const argString = args.join(" ") @@ -22,3 +27,105 @@ export async function retry(funcCb: Function, retries = 3, timeout = 3000) { } return result } + +export async function createToken(nowMillis: number, tokenName: string) { + const toolboxPods = await K8s(kind.Pod).InNamespace("gitlab").WithLabel("app", "toolbox").Get(); + const toolboxPod = toolboxPods.items.at(0); + console.log('Using gitlab-rails runner to configure root token'); + zarfExec(["tools", + "kubectl", + "--namespace", "gitlab", + "exec", + "-i", + toolboxPod?.metadata?.name!, + "--", + `gitlab-rails runner "token = User.find_by_username('root').personal_access_tokens.create(scopes: ['api', 'admin_mode', 'read_repository', 'write_repository'], name: 'Root Test Token ${nowMillis}', expires_at: 1.days.from_now); token.set_token('${tokenName}'); token.save!"` + ]); +} + +export function createNewGitlabProject(gitRepoDir: string, sourceDir: string, tokenName: string, gitProjectName: string) { + console.log(`Setting up new git repo at ${gitRepoDir}`); + copyFilesToGitRepoDir(sourceDir, gitRepoDir); + execSync('git init', { cwd: gitRepoDir }); + execSync('git add . ', { cwd: gitRepoDir }); + execSync('git config commit.gpgsign false', { cwd: gitRepoDir }); // need this so that gpg signing doesn't attempt to happen locally when running tests + execSync('git commit -m "Initial commit" ', { cwd: gitRepoDir }); + execSync(`git remote add origin https://root:${tokenName}@gitlab.uds.dev/root/${gitProjectName}.git`, { cwd: gitRepoDir }); + execSync('git push -u origin --all', { cwd: gitRepoDir }); +} + +export async function getGitlabProjectId(gitProjectName: string, headers: HeadersInit) { + const projectResp = await fetch(`https://gitlab.uds.dev/api/v4/projects?search=${encodeURIComponent(gitProjectName)}`, { headers }); + const projects = await projectResp.json(); + + const project = projects.find((p: { name: string; }) => p.name === gitProjectName); + const projectId = project?.id; + return projectId; +} + +export async function unprotectRunner(headers: HeadersInit, tokenName: string) { + const runnerIDResp = await (await fetch(`https://gitlab.uds.dev/api/v4/runners/all`, { headers })).json(); + const runnerID = runnerIDResp[0].id; + const runnerResp = await fetch(`https://gitlab.uds.dev/api/v4/runners/${runnerID}`, { + headers: [ + ["PRIVATE-TOKEN", tokenName], + ["Content-Type", "application/x-www-form-urlencoded"] + ], + body: "access_level=not_protected", + method: "put" + }); + expect(runnerResp.status).toBe(200); +} + +export async function checkJobResults(projectId: any, headers: HeadersInit, expectedJobLogOutputs: string[], expectedStatus: string) { + let status = await retry(async () => { + const jobIDResp = await (await fetch(`https://gitlab.uds.dev/api/v4/projects/${projectId}/jobs`, { headers })).json(); + + // Print the job response (useful for debugging) + console.log(jobIDResp); + + if (jobIDResp.length > 0 && (jobIDResp[0].status === "success" || jobIDResp[0].status === "failed")) { + const jobID = jobIDResp[0].id; + const jobLog = await (await fetch(`https://gitlab.uds.dev/api/v4/projects/${projectId}/jobs/${jobID}/trace`, { headers })).text(); + + // Print the job log (useful for debugging) + console.log(jobLog); + + expectedJobLogOutputs.forEach( expectedOutput => { + expect(jobLog).toContain(expectedOutput); + }); + return jobIDResp[0].status; + } + return false; + }, 7, 7000); + expect(status).toBe(expectedStatus); +} + +export async function deleteDirectory(path: string) { + try { + await rm(path, { recursive: true, force: true }); + console.log(`Directory ${path} has been deleted successfully.`); + } catch (error) { + console.error(`Error while deleting directory ${path}:`, error); + } +} + +function copyFilesToGitRepoDir(srcDir: string, destDir: string): void { + // Ensure destination directory exists + if (!fs.existsSync(destDir)) { + fs.mkdirSync(destDir, { recursive: true }); + } + + // Read files from source directory + const files = fs.readdirSync(srcDir); + + // Copy each file + files.forEach(file => { + const srcFile = path.join(srcDir, file); + const destFile = path.join(destDir, file); + + if (fs.lstatSync(srcFile).isFile()) { + fs.copyFileSync(srcFile, destFile); + } + }); +} \ No newline at end of file diff --git a/tests/journey/pipeline-run-kitteh.test.ts b/tests/journey/pipeline-run-kitteh.test.ts new file mode 100644 index 0000000..4ae15d8 --- /dev/null +++ b/tests/journey/pipeline-run-kitteh.test.ts @@ -0,0 +1,54 @@ +import { expect, test} from '@jest/globals'; +import * as common from "../common"; +import * as path from 'path'; + +// source directory from 'journey/repo-sources' that will be used to +// populate a new git repo and upload contents to gitlab as a new project +const sourceRepoName = 'kitteh' + +var nowMillis:number; +var tokenName:string; +var gitProjectName:string; +var gitRepoDir:string; +var sourceDir:string; + +beforeAll(() => { + // millis is used through the tests to have a unique id + // this is handy so you can rerun the tests against an existing + // insance of gitlab and it will continue to make new projects + // and you don't have to clean up or redeploy when iterating on local testing + nowMillis = Date.now(); + + tokenName = `if-you-see-me-in-production-something-is-horribly-wrong-${nowMillis}` + gitProjectName = `tmp-${sourceRepoName}-${nowMillis}` + + gitRepoDir = path.join(__dirname, 'tmp-repos', gitProjectName) + sourceDir = path.join(__dirname, 'repo-sources', sourceRepoName) +}); + +afterAll(async () => { + await common.deleteDirectory(gitRepoDir) // delete the temp dir so it doesn't accumulate locally +}); + + +test('hello kitteh succeeds', async () => { + + // Get the toolbox pod and add a token to the root GitLab user + await common.createToken(nowMillis, tokenName); + common.createNewGitlabProject(gitRepoDir, sourceDir, tokenName, gitProjectName); + + const headers: HeadersInit = [["PRIVATE-TOKEN", tokenName]] + + // get the project id using the project name + const projectId = await common.getGitlabProjectId(gitProjectName, headers); + + console.log(`Found now project id [${projectId}]`) + + await common.unprotectRunner(headers, tokenName); + + // Check that the pipeline actually ran successfully + const expectedStatus = "success" + const expectedJobLogOutputs: string[] = ['Hello Kitteh']; + await common.checkJobResults(projectId, headers, expectedJobLogOutputs, expectedStatus); + +}, 90000); diff --git a/tests/journey/pipeline-run-podman-fail.test.ts b/tests/journey/pipeline-run-podman-fail.test.ts new file mode 100644 index 0000000..7892a54 --- /dev/null +++ b/tests/journey/pipeline-run-podman-fail.test.ts @@ -0,0 +1,54 @@ +import { expect, test} from '@jest/globals'; +import * as common from "../common"; +import * as path from 'path'; + +// source directory from 'journey/repo-sources' that will be used to +// populate a new git repo and upload contents to gitlab as a new project +const sourceRepoName = 'podman' + +var nowMillis:number; +var tokenName:string; +var gitProjectName:string; +var gitRepoDir:string; +var sourceDir:string; + +beforeAll(() => { + // millis is used through the tests to have a unique id + // this is handy so you can rerun the tests against an existing + // insance of gitlab and it will continue to make new projects + // and you don't have to clean up or redeploy when iterating on local testing + nowMillis = Date.now(); + + tokenName = `if-you-see-me-in-production-something-is-horribly-wrong-${nowMillis}` + gitProjectName = `tmp-${sourceRepoName}-${nowMillis}` + + gitRepoDir = path.join(__dirname, 'tmp-repos', gitProjectName) + sourceDir = path.join(__dirname, 'repo-sources', sourceRepoName) +}); + +afterAll(async () => { + await common.deleteDirectory(gitRepoDir) // delete the temp dir so it doesn't accumulate locally +}); + + +test('podman fails', async () => { + + // Get the toolbox pod and add a token to the root GitLab user + await common.createToken(nowMillis, tokenName); + common.createNewGitlabProject(gitRepoDir, sourceDir, tokenName, gitProjectName); + + const headers: HeadersInit = [["PRIVATE-TOKEN", tokenName]] + + // get the project id using the project name + const projectId = await common.getGitlabProjectId(gitProjectName, headers); + + console.log(`Found now project id [${projectId}]`) + + await common.unprotectRunner(headers, tokenName); + + // Check that the pipeline actually ran successfully + const expectedStatus = "failed" + const expectedJobLogOutputs: string[] = []; // nothing expected on this one, just looking for a failure + await common.checkJobResults(projectId, headers, expectedJobLogOutputs, expectedStatus); + +}, 90000); diff --git a/tests/journey/pipeline-run-podman-success.test.ts b/tests/journey/pipeline-run-podman-success.test.ts new file mode 100644 index 0000000..dc522f7 --- /dev/null +++ b/tests/journey/pipeline-run-podman-success.test.ts @@ -0,0 +1,54 @@ +import { expect, test} from '@jest/globals'; +import * as common from "../common"; +import * as path from 'path'; + +// source directory from 'journey/repo-sources' that will be used to +// populate a new git repo and upload contents to gitlab as a new project +const sourceRepoName = 'podman' + +var nowMillis:number; +var tokenName:string; +var gitProjectName:string; +var gitRepoDir:string; +var sourceDir:string; + +beforeAll(() => { + // millis is used through the tests to have a unique id + // this is handy so you can rerun the tests against an existing + // insance of gitlab and it will continue to make new projects + // and you don't have to clean up or redeploy when iterating on local testing + nowMillis = Date.now(); + + tokenName = `if-you-see-me-in-production-something-is-horribly-wrong-${nowMillis}` + gitProjectName = `tmp-${sourceRepoName}-${nowMillis}` + + gitRepoDir = path.join(__dirname, 'tmp-repos', gitProjectName) + sourceDir = path.join(__dirname, 'repo-sources', sourceRepoName) +}); + +afterAll(async () => { + await common.deleteDirectory(gitRepoDir) // delete the temp dir so it doesn't accumulate locally +}); + + +test('podman succeeds', async () => { + + // Get the toolbox pod and add a token to the root GitLab user + await common.createToken(nowMillis, tokenName); + common.createNewGitlabProject(gitRepoDir, sourceDir, tokenName, gitProjectName); + + const headers: HeadersInit = [["PRIVATE-TOKEN", tokenName]] + + // get the project id using the project name + const projectId = await common.getGitlabProjectId(gitProjectName, headers); + + console.log(`Found now project id [${projectId}]`) + + await common.unprotectRunner(headers, tokenName); + + // Check that the pipeline actually ran successfully + const expectedStatus = "success" + const expectedJobLogOutputs: string[] = ['STEP 1/2: FROM scratch', 'STEP 2/2: ADD test.txt /', 'COMMIT']; + await common.checkJobResults(projectId, headers, expectedJobLogOutputs, expectedStatus); + +}, 90000); diff --git a/tests/journey/pipeline-run.test.ts b/tests/journey/pipeline-run.test.ts index d39526e..eca4d60 100644 --- a/tests/journey/pipeline-run.test.ts +++ b/tests/journey/pipeline-run.test.ts @@ -1,70 +1,107 @@ import { expect, test} from '@jest/globals'; -import { K8s, kind } from "kubernetes-fluent-client"; -import { zarfExec, retry } from "../common"; +import * as common from "../common"; +import * as path from 'path'; + + +test('podman fails', async () => { + // millis is used through the tests to have a unique id + // this is handy so you can rerun the tests against an existing + // insance of gitlab and it will continue to make new projects + // and you don't have to clean up or redeploy when iterating on local testing + const nowMillis = Date.now(); -test('test kicking off a pipeline run', async () => { // Get the toolbox pod and add a token to the root GitLab user - const tokenName = `if-you-see-me-in-production-something-is-horribly-wrong-${new Date()}` - const toolboxPods = await K8s(kind.Pod).InNamespace("gitlab").WithLabel("app", "toolbox").Get() - const toolboxPod = toolboxPods.items.at(0) - zarfExec(["tools", - "kubectl", - "--namespace", "gitlab", - "exec", - "-i", - toolboxPod?.metadata?.name!, - "--", - `gitlab-rails runner "token = User.find_by_username('root').personal_access_tokens.create(scopes: ['api', 'admin_mode', 'read_repository', 'write_repository'], name: 'Root Test Token', expires_at: 1.days.from_now); token.set_token('${tokenName}'); token.save!"` - ]); - - const arch = process.env.UDS_ARCH - // Create a test repository in GitLab using Zarf - zarfExec(["package", "create", "package", "--confirm"]); - zarfExec([ - "package", - "mirror-resources", - `zarf-package-gitlab-runner-test-${arch}-0.0.1.tar.zst`, - "--git-url", "https://gitlab.uds.dev/", - "--git-push-username", "root", - "--git-push-password", `"${tokenName}"`, - "--confirm" - ]); - + const tokenName = `if-you-see-me-in-production-something-is-horribly-wrong-${nowMillis}` + + await common.createToken(nowMillis, tokenName); + + const sourceRepoName = 'podman' + const gitProjectName = `${sourceRepoName}-${nowMillis}` + const gitRepoDir = path.join(__dirname, 'tmp-repos', gitProjectName) + const sourceDir = path.join(__dirname, 'repo-sources', sourceRepoName) + + common.createNewGitlabProject(gitRepoDir, sourceDir, tokenName, gitProjectName); + const headers: HeadersInit = [["PRIVATE-TOKEN", tokenName]] - // Un-protect the runner so that it picks up jobs from the `zarf-` branches - const runnerIDResp = await (await fetch(`https://gitlab.uds.dev/api/v4/runners/all`, { headers })).json() - const runnerID = runnerIDResp[0].id - const runnerResp = await fetch(`https://gitlab.uds.dev/api/v4/runners/${runnerID}`, { - headers: [ - ["PRIVATE-TOKEN", tokenName], - ["Content-Type", "application/x-www-form-urlencoded"] - ], - body: "access_level=not_protected", - method: "put" - }) - expect(runnerResp.status).toBe(200) + // get the project id using the project name + const projectId = await common.getGitlabProjectId(gitProjectName, headers); + + console.log(`Found now project id [${projectId}]`) + + await common.unprotectRunner(headers, tokenName); + + // Check that the pipeline failed as expected + const expectedStatus = "failed" + const expectedJobLogOutputs: string[] = []; // nothing expected on this one, just looking for a failure + await common.checkJobResults(projectId, headers, expectedJobLogOutputs, expectedStatus); +}, 90000); + +test('podman succeeds', async () => { + // millis is used through the tests to have a unique id + // this is handy so you can rerun the tests against an existing + // insance of gitlab and it will continue to make new projects + // and you don't have to clean up or redeploy when iterating on local testing + const nowMillis = Date.now(); + + // Get the toolbox pod and add a token to the root GitLab user + const tokenName = `if-you-see-me-in-production-something-is-horribly-wrong-${nowMillis}` + + await common.createToken(nowMillis, tokenName); + + const sourceRepoName = 'podman' + const gitProjectName = `${sourceRepoName}-${nowMillis}` + const gitRepoDir = path.join(__dirname, 'tmp-repos', gitProjectName) + const sourceDir = path.join(__dirname, 'repo-sources', sourceRepoName) + + common.createNewGitlabProject(gitRepoDir, sourceDir, tokenName, gitProjectName); + + const headers: HeadersInit = [["PRIVATE-TOKEN", tokenName]] + + // get the project id using the project name + const projectId = await common.getGitlabProjectId(gitProjectName, headers); + + console.log(`Found now project id [${projectId}]`) + + await common.unprotectRunner(headers, tokenName); + + // Check that the pipeline failed as expected + const expectedStatus = "success" + const expectedJobLogOutputs: string[] = ['STEP 1/2: FROM scratch', 'STEP 2/2: ADD test.txt /', 'COMMIT']; + await common.checkJobResults(projectId, headers, expectedJobLogOutputs, expectedStatus); +}, 90000); + +test('hello kitteh succeeds', async () => { + // millis is used through the tests to have a unique id + // this is handy so you can rerun the tests against an existing + // insance of gitlab and it will continue to make new projects + // and you don't have to clean up or redeploy when iterating on local testing + const nowMillis = Date.now(); + + // Get the toolbox pod and add a token to the root GitLab user + const tokenName = `if-you-see-me-in-production-something-is-horribly-wrong-${nowMillis}` + + await common.createToken(nowMillis, tokenName); + + const sourceRepoName = 'kitteh' + const gitProjectName = `${sourceRepoName}-${nowMillis}` + const gitRepoDir = path.join(__dirname, 'tmp-repos', gitProjectName) + const sourceDir = path.join(__dirname, 'repo-sources', sourceRepoName) + + common.createNewGitlabProject(gitRepoDir, sourceDir, tokenName, gitProjectName); + + const headers: HeadersInit = [["PRIVATE-TOKEN", tokenName]] + + // get the project id using the project name + const projectId = await common.getGitlabProjectId(gitProjectName, headers); + + console.log(`Found now project id [${projectId}]`) + + await common.unprotectRunner(headers, tokenName); // Check that the pipeline actually ran successfully - let foundTheKitteh = await retry(async () => { - const jobIDResp = await (await fetch(`https://gitlab.uds.dev/api/v4/projects/1/jobs`, { headers })).json() - - // Print the job response (useful for debugging) - console.log(jobIDResp) - - if (jobIDResp.length > 0 && jobIDResp[0].status === "success") { - const jobID = jobIDResp[0].id - const jobLog = await (await fetch(`https://gitlab.uds.dev/api/v4/projects/1/jobs/${jobID}/trace`, { headers })).text() - - // Print the job log (useful for debugging) - console.log(jobLog) - - if (jobLog.indexOf("Hello Kitteh") > -1) { - return true - } - } - return false - }, 7, 7000); - expect(foundTheKitteh).toBe(true) + const expectedStatus = "success" + const expectedJobLogOutputs: string[] = ['Hello Kitteh']; + await common.checkJobResults(projectId, headers, expectedJobLogOutputs, expectedStatus); }, 90000); diff --git a/.gitlab-ci.yml b/tests/journey/repo-sources/kitteh/.gitlab-ci.yml similarity index 100% rename from .gitlab-ci.yml rename to tests/journey/repo-sources/kitteh/.gitlab-ci.yml diff --git a/tests/journey/repo-sources/podman/.gitlab-ci.yml b/tests/journey/repo-sources/podman/.gitlab-ci.yml new file mode 100644 index 0000000..d873c06 --- /dev/null +++ b/tests/journey/repo-sources/podman/.gitlab-ci.yml @@ -0,0 +1,6 @@ +build-image-podman: + stage: build + image: quay.io/podman/stable:latest + script: | + podman build . + \ No newline at end of file diff --git a/tests/journey/repo-sources/podman/Dockerfile b/tests/journey/repo-sources/podman/Dockerfile new file mode 100644 index 0000000..3c317ee --- /dev/null +++ b/tests/journey/repo-sources/podman/Dockerfile @@ -0,0 +1,2 @@ +FROM scratch +ADD test.txt / \ No newline at end of file diff --git a/tests/journey/repo-sources/podman/test.txt b/tests/journey/repo-sources/podman/test.txt new file mode 100644 index 0000000..2ed667c --- /dev/null +++ b/tests/journey/repo-sources/podman/test.txt @@ -0,0 +1 @@ +text file that will get added to the container, referenced in Dockerfile \ No newline at end of file diff --git a/tests/package/zarf.yaml b/tests/package/zarf.yaml deleted file mode 100644 index 2e156f4..0000000 --- a/tests/package/zarf.yaml +++ /dev/null @@ -1,11 +0,0 @@ -kind: ZarfPackageConfig -metadata: - name: gitlab-runner-test - version: 0.0.1 - description: A test package with a git repo containing a gitlab runner config - -components: - - name: full-repo - repos: - # This references a commit that has a .gitlab-ci.yml in it - to update this push a PR and a new commit. - - https://github.com/defenseunicorns/uds-package-gitlab-runner.git@112875cfd0b05ca7c0486258afa40f5fe80d4bdf From 1e06033647c12fd16ab304e2976b50067cc96e0d Mon Sep 17 00:00:00 2001 From: Eric Wyles <23637493+ericwyles@users.noreply.github.com> Date: Fri, 23 Aug 2024 13:21:39 -0500 Subject: [PATCH 14/25] lint --- tests/journey/repo-sources/podman/.gitlab-ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/journey/repo-sources/podman/.gitlab-ci.yml b/tests/journey/repo-sources/podman/.gitlab-ci.yml index d873c06..fe5f2dd 100644 --- a/tests/journey/repo-sources/podman/.gitlab-ci.yml +++ b/tests/journey/repo-sources/podman/.gitlab-ci.yml @@ -3,4 +3,3 @@ build-image-podman: image: quay.io/podman/stable:latest script: | podman build . - \ No newline at end of file From 87cd20e7e7d7c8a1dbae813c27de04e67ccd6007 Mon Sep 17 00:00:00 2001 From: Eric Wyles <23637493+ericwyles@users.noreply.github.com> Date: Fri, 23 Aug 2024 15:13:21 -0500 Subject: [PATCH 15/25] make it simpler --- .gitignore | 4 +- tasks/test.yaml | 11 +- tests/common.ts | 107 --------- tests/journey/pipeline-run-kitteh.test.ts | 54 ----- .../journey/pipeline-run-podman-fail.test.ts | 54 ----- .../pipeline-run-podman-success.test.ts | 54 ----- tests/journey/pipeline-run.test.ts | 208 ++++++++++-------- 7 files changed, 130 insertions(+), 362 deletions(-) delete mode 100644 tests/journey/pipeline-run-kitteh.test.ts delete mode 100644 tests/journey/pipeline-run-podman-fail.test.ts delete mode 100644 tests/journey/pipeline-run-podman-success.test.ts diff --git a/.gitignore b/.gitignore index f91aa23..145c016 100644 --- a/.gitignore +++ b/.gitignore @@ -23,5 +23,5 @@ overlay-values-* # Dependency files uds-config-gitlab.yaml -#place where temporary git repos are created -**tmp-repos +# Temporary .git dirs made for temp repos that are pushed to gitlab during testing +**/repo-sources/**/.git diff --git a/tasks/test.yaml b/tasks/test.yaml index 67e0e9c..8c2b57d 100644 --- a/tasks/test.yaml +++ b/tasks/test.yaml @@ -18,6 +18,8 @@ tasks: cmd: cat bundle/uds-bundle.yaml | ./uds zarf tools yq .metadata.version setVariables: - name: BUNDLE_VERSION + # Remove the GLR package and redeploy with additional capabilities enabled + - task: remove:test-bundle - description: Deploy GitLab runner with SETUID and SETGID capabilities cmd: UDS_CONFIG=bundle/uds-config.yaml ./uds deploy bundle/uds-bundle-${BUNDLE_NAME}-${UDS_ARCH}-${BUNDLE_VERSION}.tar.zst --confirm --no-progress --set ENABLE_SECURITY_CAPABILITIES=true - task: glr-run-check-elevated-security-capabilities @@ -67,8 +69,8 @@ tasks: - description: Setup a repository and trigger a pipeline job dir: tests cmd: | - npm test -- journey/pipeline-run-kitteh.test.ts - npm test -- journey/pipeline-run-podman-fail.test.ts + npm test -- journey/pipeline-run.test.ts -t 'hello kitteh succeeds' + npm test -- journey/pipeline-run.test.ts -t 'podman fails' - name: glr-run-check-elevated-security-capabilities description: Check that a GitLab repository can trigger a gitlab runner to run @@ -76,8 +78,9 @@ tasks: - description: Setup a repository and trigger a pipeline job dir: tests cmd: | - npm test -- journey/pipeline-run-kitteh.test.ts - npm test -- journey/pipeline-run-podman-success.test.ts + npm test -- journey/pipeline-run.test.ts -t 'hello kitteh succeeds' + npm test -- journey/pipeline-run.test.ts -t 'podman succeeds' + - name: glr-create-runner-token description: Create a runner auth token and set the variable RUNNER_AUTH_TOKEN diff --git a/tests/common.ts b/tests/common.ts index 7d5d53a..e266e95 100644 --- a/tests/common.ts +++ b/tests/common.ts @@ -1,9 +1,4 @@ import { spawnSync } from "child_process"; -import { execSync } from 'child_process'; -import { K8s, kind } from "kubernetes-fluent-client"; -import { rm } from 'fs/promises'; -import * as fs from 'fs'; -import * as path from 'path'; export function zarfExec(args: string[], captureOutput = false) { const argString = args.join(" ") @@ -27,105 +22,3 @@ export async function retry(funcCb: Function, retries = 3, timeout = 3000) { } return result } - -export async function createToken(nowMillis: number, tokenName: string) { - const toolboxPods = await K8s(kind.Pod).InNamespace("gitlab").WithLabel("app", "toolbox").Get(); - const toolboxPod = toolboxPods.items.at(0); - console.log('Using gitlab-rails runner to configure root token'); - zarfExec(["tools", - "kubectl", - "--namespace", "gitlab", - "exec", - "-i", - toolboxPod?.metadata?.name!, - "--", - `gitlab-rails runner "token = User.find_by_username('root').personal_access_tokens.create(scopes: ['api', 'admin_mode', 'read_repository', 'write_repository'], name: 'Root Test Token ${nowMillis}', expires_at: 1.days.from_now); token.set_token('${tokenName}'); token.save!"` - ]); -} - -export function createNewGitlabProject(gitRepoDir: string, sourceDir: string, tokenName: string, gitProjectName: string) { - console.log(`Setting up new git repo at ${gitRepoDir}`); - copyFilesToGitRepoDir(sourceDir, gitRepoDir); - execSync('git init', { cwd: gitRepoDir }); - execSync('git add . ', { cwd: gitRepoDir }); - execSync('git config commit.gpgsign false', { cwd: gitRepoDir }); // need this so that gpg signing doesn't attempt to happen locally when running tests - execSync('git commit -m "Initial commit" ', { cwd: gitRepoDir }); - execSync(`git remote add origin https://root:${tokenName}@gitlab.uds.dev/root/${gitProjectName}.git`, { cwd: gitRepoDir }); - execSync('git push -u origin --all', { cwd: gitRepoDir }); -} - -export async function getGitlabProjectId(gitProjectName: string, headers: HeadersInit) { - const projectResp = await fetch(`https://gitlab.uds.dev/api/v4/projects?search=${encodeURIComponent(gitProjectName)}`, { headers }); - const projects = await projectResp.json(); - - const project = projects.find((p: { name: string; }) => p.name === gitProjectName); - const projectId = project?.id; - return projectId; -} - -export async function unprotectRunner(headers: HeadersInit, tokenName: string) { - const runnerIDResp = await (await fetch(`https://gitlab.uds.dev/api/v4/runners/all`, { headers })).json(); - const runnerID = runnerIDResp[0].id; - const runnerResp = await fetch(`https://gitlab.uds.dev/api/v4/runners/${runnerID}`, { - headers: [ - ["PRIVATE-TOKEN", tokenName], - ["Content-Type", "application/x-www-form-urlencoded"] - ], - body: "access_level=not_protected", - method: "put" - }); - expect(runnerResp.status).toBe(200); -} - -export async function checkJobResults(projectId: any, headers: HeadersInit, expectedJobLogOutputs: string[], expectedStatus: string) { - let status = await retry(async () => { - const jobIDResp = await (await fetch(`https://gitlab.uds.dev/api/v4/projects/${projectId}/jobs`, { headers })).json(); - - // Print the job response (useful for debugging) - console.log(jobIDResp); - - if (jobIDResp.length > 0 && (jobIDResp[0].status === "success" || jobIDResp[0].status === "failed")) { - const jobID = jobIDResp[0].id; - const jobLog = await (await fetch(`https://gitlab.uds.dev/api/v4/projects/${projectId}/jobs/${jobID}/trace`, { headers })).text(); - - // Print the job log (useful for debugging) - console.log(jobLog); - - expectedJobLogOutputs.forEach( expectedOutput => { - expect(jobLog).toContain(expectedOutput); - }); - return jobIDResp[0].status; - } - return false; - }, 7, 7000); - expect(status).toBe(expectedStatus); -} - -export async function deleteDirectory(path: string) { - try { - await rm(path, { recursive: true, force: true }); - console.log(`Directory ${path} has been deleted successfully.`); - } catch (error) { - console.error(`Error while deleting directory ${path}:`, error); - } -} - -function copyFilesToGitRepoDir(srcDir: string, destDir: string): void { - // Ensure destination directory exists - if (!fs.existsSync(destDir)) { - fs.mkdirSync(destDir, { recursive: true }); - } - - // Read files from source directory - const files = fs.readdirSync(srcDir); - - // Copy each file - files.forEach(file => { - const srcFile = path.join(srcDir, file); - const destFile = path.join(destDir, file); - - if (fs.lstatSync(srcFile).isFile()) { - fs.copyFileSync(srcFile, destFile); - } - }); -} \ No newline at end of file diff --git a/tests/journey/pipeline-run-kitteh.test.ts b/tests/journey/pipeline-run-kitteh.test.ts deleted file mode 100644 index 4ae15d8..0000000 --- a/tests/journey/pipeline-run-kitteh.test.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { expect, test} from '@jest/globals'; -import * as common from "../common"; -import * as path from 'path'; - -// source directory from 'journey/repo-sources' that will be used to -// populate a new git repo and upload contents to gitlab as a new project -const sourceRepoName = 'kitteh' - -var nowMillis:number; -var tokenName:string; -var gitProjectName:string; -var gitRepoDir:string; -var sourceDir:string; - -beforeAll(() => { - // millis is used through the tests to have a unique id - // this is handy so you can rerun the tests against an existing - // insance of gitlab and it will continue to make new projects - // and you don't have to clean up or redeploy when iterating on local testing - nowMillis = Date.now(); - - tokenName = `if-you-see-me-in-production-something-is-horribly-wrong-${nowMillis}` - gitProjectName = `tmp-${sourceRepoName}-${nowMillis}` - - gitRepoDir = path.join(__dirname, 'tmp-repos', gitProjectName) - sourceDir = path.join(__dirname, 'repo-sources', sourceRepoName) -}); - -afterAll(async () => { - await common.deleteDirectory(gitRepoDir) // delete the temp dir so it doesn't accumulate locally -}); - - -test('hello kitteh succeeds', async () => { - - // Get the toolbox pod and add a token to the root GitLab user - await common.createToken(nowMillis, tokenName); - common.createNewGitlabProject(gitRepoDir, sourceDir, tokenName, gitProjectName); - - const headers: HeadersInit = [["PRIVATE-TOKEN", tokenName]] - - // get the project id using the project name - const projectId = await common.getGitlabProjectId(gitProjectName, headers); - - console.log(`Found now project id [${projectId}]`) - - await common.unprotectRunner(headers, tokenName); - - // Check that the pipeline actually ran successfully - const expectedStatus = "success" - const expectedJobLogOutputs: string[] = ['Hello Kitteh']; - await common.checkJobResults(projectId, headers, expectedJobLogOutputs, expectedStatus); - -}, 90000); diff --git a/tests/journey/pipeline-run-podman-fail.test.ts b/tests/journey/pipeline-run-podman-fail.test.ts deleted file mode 100644 index 7892a54..0000000 --- a/tests/journey/pipeline-run-podman-fail.test.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { expect, test} from '@jest/globals'; -import * as common from "../common"; -import * as path from 'path'; - -// source directory from 'journey/repo-sources' that will be used to -// populate a new git repo and upload contents to gitlab as a new project -const sourceRepoName = 'podman' - -var nowMillis:number; -var tokenName:string; -var gitProjectName:string; -var gitRepoDir:string; -var sourceDir:string; - -beforeAll(() => { - // millis is used through the tests to have a unique id - // this is handy so you can rerun the tests against an existing - // insance of gitlab and it will continue to make new projects - // and you don't have to clean up or redeploy when iterating on local testing - nowMillis = Date.now(); - - tokenName = `if-you-see-me-in-production-something-is-horribly-wrong-${nowMillis}` - gitProjectName = `tmp-${sourceRepoName}-${nowMillis}` - - gitRepoDir = path.join(__dirname, 'tmp-repos', gitProjectName) - sourceDir = path.join(__dirname, 'repo-sources', sourceRepoName) -}); - -afterAll(async () => { - await common.deleteDirectory(gitRepoDir) // delete the temp dir so it doesn't accumulate locally -}); - - -test('podman fails', async () => { - - // Get the toolbox pod and add a token to the root GitLab user - await common.createToken(nowMillis, tokenName); - common.createNewGitlabProject(gitRepoDir, sourceDir, tokenName, gitProjectName); - - const headers: HeadersInit = [["PRIVATE-TOKEN", tokenName]] - - // get the project id using the project name - const projectId = await common.getGitlabProjectId(gitProjectName, headers); - - console.log(`Found now project id [${projectId}]`) - - await common.unprotectRunner(headers, tokenName); - - // Check that the pipeline actually ran successfully - const expectedStatus = "failed" - const expectedJobLogOutputs: string[] = []; // nothing expected on this one, just looking for a failure - await common.checkJobResults(projectId, headers, expectedJobLogOutputs, expectedStatus); - -}, 90000); diff --git a/tests/journey/pipeline-run-podman-success.test.ts b/tests/journey/pipeline-run-podman-success.test.ts deleted file mode 100644 index dc522f7..0000000 --- a/tests/journey/pipeline-run-podman-success.test.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { expect, test} from '@jest/globals'; -import * as common from "../common"; -import * as path from 'path'; - -// source directory from 'journey/repo-sources' that will be used to -// populate a new git repo and upload contents to gitlab as a new project -const sourceRepoName = 'podman' - -var nowMillis:number; -var tokenName:string; -var gitProjectName:string; -var gitRepoDir:string; -var sourceDir:string; - -beforeAll(() => { - // millis is used through the tests to have a unique id - // this is handy so you can rerun the tests against an existing - // insance of gitlab and it will continue to make new projects - // and you don't have to clean up or redeploy when iterating on local testing - nowMillis = Date.now(); - - tokenName = `if-you-see-me-in-production-something-is-horribly-wrong-${nowMillis}` - gitProjectName = `tmp-${sourceRepoName}-${nowMillis}` - - gitRepoDir = path.join(__dirname, 'tmp-repos', gitProjectName) - sourceDir = path.join(__dirname, 'repo-sources', sourceRepoName) -}); - -afterAll(async () => { - await common.deleteDirectory(gitRepoDir) // delete the temp dir so it doesn't accumulate locally -}); - - -test('podman succeeds', async () => { - - // Get the toolbox pod and add a token to the root GitLab user - await common.createToken(nowMillis, tokenName); - common.createNewGitlabProject(gitRepoDir, sourceDir, tokenName, gitProjectName); - - const headers: HeadersInit = [["PRIVATE-TOKEN", tokenName]] - - // get the project id using the project name - const projectId = await common.getGitlabProjectId(gitProjectName, headers); - - console.log(`Found now project id [${projectId}]`) - - await common.unprotectRunner(headers, tokenName); - - // Check that the pipeline actually ran successfully - const expectedStatus = "success" - const expectedJobLogOutputs: string[] = ['STEP 1/2: FROM scratch', 'STEP 2/2: ADD test.txt /', 'COMMIT']; - await common.checkJobResults(projectId, headers, expectedJobLogOutputs, expectedStatus); - -}, 90000); diff --git a/tests/journey/pipeline-run.test.ts b/tests/journey/pipeline-run.test.ts index eca4d60..e117c9d 100644 --- a/tests/journey/pipeline-run.test.ts +++ b/tests/journey/pipeline-run.test.ts @@ -1,107 +1,141 @@ import { expect, test} from '@jest/globals'; -import * as common from "../common"; +import {zarfExec, retry} from "../common"; import * as path from 'path'; +import { execSync } from 'child_process'; +import { K8s, kind } from "kubernetes-fluent-client"; +import { rm } from 'fs/promises'; +test('hello kitteh succeeds', async () => { + const sourceRepoName = 'kitteh' + const expectedStatus = "success" + const expectedJobLogOutputs: string[] = ['Hello Kitteh']; -test('podman fails', async () => { - // millis is used through the tests to have a unique id - // this is handy so you can rerun the tests against an existing - // insance of gitlab and it will continue to make new projects - // and you don't have to clean up or redeploy when iterating on local testing - const nowMillis = Date.now(); + await executeTest(sourceRepoName, expectedJobLogOutputs, expectedStatus); - // Get the toolbox pod and add a token to the root GitLab user - const tokenName = `if-you-see-me-in-production-something-is-horribly-wrong-${nowMillis}` +}, 90000); - await common.createToken(nowMillis, tokenName); +test('podman succeeds', async () => { const sourceRepoName = 'podman' - const gitProjectName = `${sourceRepoName}-${nowMillis}` - const gitRepoDir = path.join(__dirname, 'tmp-repos', gitProjectName) - const sourceDir = path.join(__dirname, 'repo-sources', sourceRepoName) - - common.createNewGitlabProject(gitRepoDir, sourceDir, tokenName, gitProjectName); - - const headers: HeadersInit = [["PRIVATE-TOKEN", tokenName]] - - // get the project id using the project name - const projectId = await common.getGitlabProjectId(gitProjectName, headers); - - console.log(`Found now project id [${projectId}]`) - - await common.unprotectRunner(headers, tokenName); + const expectedStatus = "success" + const expectedJobLogOutputs: string[] = ['STEP 1/2: FROM scratch', 'STEP 2/2: ADD test.txt /', 'COMMIT']; - // Check that the pipeline failed as expected - const expectedStatus = "failed" - const expectedJobLogOutputs: string[] = []; // nothing expected on this one, just looking for a failure - await common.checkJobResults(projectId, headers, expectedJobLogOutputs, expectedStatus); + await executeTest(sourceRepoName, expectedJobLogOutputs, expectedStatus); }, 90000); -test('podman succeeds', async () => { - // millis is used through the tests to have a unique id - // this is handy so you can rerun the tests against an existing - // insance of gitlab and it will continue to make new projects - // and you don't have to clean up or redeploy when iterating on local testing - const nowMillis = Date.now(); - // Get the toolbox pod and add a token to the root GitLab user - const tokenName = `if-you-see-me-in-production-something-is-horribly-wrong-${nowMillis}` - - await common.createToken(nowMillis, tokenName); +test('podman fails', async () => { const sourceRepoName = 'podman' - const gitProjectName = `${sourceRepoName}-${nowMillis}` - const gitRepoDir = path.join(__dirname, 'tmp-repos', gitProjectName) - const sourceDir = path.join(__dirname, 'repo-sources', sourceRepoName) - - common.createNewGitlabProject(gitRepoDir, sourceDir, tokenName, gitProjectName); - - const headers: HeadersInit = [["PRIVATE-TOKEN", tokenName]] - - // get the project id using the project name - const projectId = await common.getGitlabProjectId(gitProjectName, headers); - - console.log(`Found now project id [${projectId}]`) - - await common.unprotectRunner(headers, tokenName); + const expectedStatus = "failed" + const expectedJobLogOutputs: string[] = []; - // Check that the pipeline failed as expected - const expectedStatus = "success" - const expectedJobLogOutputs: string[] = ['STEP 1/2: FROM scratch', 'STEP 2/2: ADD test.txt /', 'COMMIT']; - await common.checkJobResults(projectId, headers, expectedJobLogOutputs, expectedStatus); + await executeTest(sourceRepoName, expectedJobLogOutputs, expectedStatus); }, 90000); -test('hello kitteh succeeds', async () => { - // millis is used through the tests to have a unique id - // this is handy so you can rerun the tests against an existing - // insance of gitlab and it will continue to make new projects - // and you don't have to clean up or redeploy when iterating on local testing + +async function executeTest(sourceRepoName: string, expectedJobLogOutputs: string[], expectedStatus: string) { const nowMillis = Date.now(); + const tokenName = `if-you-see-me-in-production-something-is-horribly-wrong-${nowMillis}` + + var sourceDir = path.join(__dirname, 'repo-sources', sourceRepoName); // Get the toolbox pod and add a token to the root GitLab user - const tokenName = `if-you-see-me-in-production-something-is-horribly-wrong-${nowMillis}` - - await common.createToken(nowMillis, tokenName); - - const sourceRepoName = 'kitteh' - const gitProjectName = `${sourceRepoName}-${nowMillis}` - const gitRepoDir = path.join(__dirname, 'tmp-repos', gitProjectName) - const sourceDir = path.join(__dirname, 'repo-sources', sourceRepoName) - - common.createNewGitlabProject(gitRepoDir, sourceDir, tokenName, gitProjectName); - - const headers: HeadersInit = [["PRIVATE-TOKEN", tokenName]] - - // get the project id using the project name - const projectId = await common.getGitlabProjectId(gitProjectName, headers); - - console.log(`Found now project id [${projectId}]`) - - await common.unprotectRunner(headers, tokenName); - - // Check that the pipeline actually ran successfully - const expectedStatus = "success" - const expectedJobLogOutputs: string[] = ['Hello Kitteh']; - await common.checkJobResults(projectId, headers, expectedJobLogOutputs, expectedStatus); - -}, 90000); + await createToken(tokenName); + const headers: HeadersInit = [["PRIVATE-TOKEN", tokenName]]; + + const gitLabProjectName = `${sourceRepoName}-${nowMillis}`; + const projectId = await createNewGitlabProject(sourceDir, tokenName, gitLabProjectName, headers); + + await unprotectRunner(headers, tokenName); + + // Check that the pipeline actually ran as expected + await checkJobResults(projectId, headers, expectedJobLogOutputs, expectedStatus); +} + + +async function createToken(tokenName: string) { + var nowMillis = Date.now(); + const toolboxPods = await K8s(kind.Pod).InNamespace("gitlab").WithLabel("app", "toolbox").Get(); + const toolboxPod = toolboxPods.items.at(0); + console.log('Using gitlab-rails runner to configure root token'); + zarfExec(["tools", + "kubectl", + "--namespace", "gitlab", + "exec", + "-i", + toolboxPod?.metadata?.name!, + "--", + `gitlab-rails runner "token = User.find_by_username('root').personal_access_tokens.create(scopes: ['api', 'admin_mode', 'read_repository', 'write_repository'], name: 'Root Test Token ${nowMillis}', expires_at: 1.days.from_now); token.set_token('${tokenName}'); token.save!"` + ]); +} + +async function createNewGitlabProject(sourceDir: string, tokenName: string, gitLabProjectName: string, headers: HeadersInit) { + //console.log(`Setting up new git repo at ${gitRepoDir}`); + //copyFilesToGitRepoDir(sourceDir, gitRepoDir); + const millis = Date.now(); + await deleteDirectory(path.join(sourceDir, '.git')) + execSync('git init', { cwd: sourceDir }); + execSync('git add . ', { cwd: sourceDir }); + execSync('git config commit.gpgsign false', { cwd: sourceDir }); // need this so that gpg signing doesn't attempt to happen locally when running tests + execSync('git commit -m "Initial commit" ', { cwd: sourceDir }); + execSync(`git remote add origin https://root:${tokenName}@gitlab.uds.dev/root/${gitLabProjectName}.git`, { cwd: sourceDir }); + execSync('git push -u origin --all', { cwd: sourceDir }); + await deleteDirectory(path.join(sourceDir, '.git')) + + console.log(`Finding project id for project name [${encodeURIComponent(gitLabProjectName)}]`) + const projectResp = await fetch(`https://gitlab.uds.dev/api/v4/projects?search=${encodeURIComponent(gitLabProjectName)}`, { headers }); + const projects = await projectResp.json(); + + const project = projects.find((p: { name: string; }) => p.name === gitLabProjectName); + const projectId = project?.id; + console.log(`Found project id [${projectId}]`) + return projectId; +} + +async function unprotectRunner(headers: HeadersInit, tokenName: string) { + const runnerIDResp = await (await fetch(`https://gitlab.uds.dev/api/v4/runners/all`, { headers })).json(); + const runnerID = runnerIDResp[0].id; + const runnerResp = await fetch(`https://gitlab.uds.dev/api/v4/runners/${runnerID}`, { + headers: [ + ["PRIVATE-TOKEN", tokenName], + ["Content-Type", "application/x-www-form-urlencoded"] + ], + body: "access_level=not_protected", + method: "put" + }); + expect(runnerResp.status).toBe(200); +} + +async function checkJobResults(projectId: any, headers: HeadersInit, expectedJobLogOutputs: string[], expectedStatus: string) { + let status = await retry(async () => { + const jobIDResp = await (await fetch(`https://gitlab.uds.dev/api/v4/projects/${projectId}/jobs`, { headers })).json(); + + // Print the job response (useful for debugging) + console.log(jobIDResp); + + if (jobIDResp.length > 0 && (jobIDResp[0].status === "success" || jobIDResp[0].status === "failed")) { + const jobID = jobIDResp[0].id; + const jobLog = await (await fetch(`https://gitlab.uds.dev/api/v4/projects/${projectId}/jobs/${jobID}/trace`, { headers })).text(); + + // Print the job log (useful for debugging) + console.log(jobLog); + + expectedJobLogOutputs.forEach( expectedOutput => { + expect(jobLog).toContain(expectedOutput); + }); + return jobIDResp[0].status; + } + return false; + }, 7, 7000); + expect(status).toBe(expectedStatus); +} + +async function deleteDirectory(path: string) { + try { + await rm(path, { recursive: true, force: true }); + console.log(`Directory ${path} has been deleted successfully.`); + } catch (error) { + console.error(`Error while deleting directory ${path}:`, error); + } +} From 4c574e829de167e771d4627c34e208ca1c724f39 Mon Sep 17 00:00:00 2001 From: Eric Wyles <23637493+ericwyles@users.noreply.github.com> Date: Fri, 23 Aug 2024 15:15:18 -0500 Subject: [PATCH 16/25] lint --- tests/journey/pipeline-run.test.ts | 4 ++-- tests/journey/repo-sources/podman/Dockerfile | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/journey/pipeline-run.test.ts b/tests/journey/pipeline-run.test.ts index e117c9d..86e9962 100644 --- a/tests/journey/pipeline-run.test.ts +++ b/tests/journey/pipeline-run.test.ts @@ -1,5 +1,5 @@ -import { expect, test} from '@jest/globals'; -import {zarfExec, retry} from "../common"; +import { expect, test } from '@jest/globals'; +import { zarfExec, retry } from "../common"; import * as path from 'path'; import { execSync } from 'child_process'; import { K8s, kind } from "kubernetes-fluent-client"; diff --git a/tests/journey/repo-sources/podman/Dockerfile b/tests/journey/repo-sources/podman/Dockerfile index 3c317ee..8415543 100644 --- a/tests/journey/repo-sources/podman/Dockerfile +++ b/tests/journey/repo-sources/podman/Dockerfile @@ -1,2 +1,2 @@ FROM scratch -ADD test.txt / \ No newline at end of file +ADD test.txt / From 5d84cea91e8e7bd3522fab8e0cc83efdec7a45ab Mon Sep 17 00:00:00 2001 From: Eric Wyles <23637493+ericwyles@users.noreply.github.com> Date: Fri, 23 Aug 2024 15:45:23 -0500 Subject: [PATCH 17/25] prying the semicolons from my cold, dead hands --- tests/journey/pipeline-run.test.ts | 85 +++++++++++++++--------------- 1 file changed, 42 insertions(+), 43 deletions(-) diff --git a/tests/journey/pipeline-run.test.ts b/tests/journey/pipeline-run.test.ts index 86e9962..499b0ad 100644 --- a/tests/journey/pipeline-run.test.ts +++ b/tests/journey/pipeline-run.test.ts @@ -1,36 +1,36 @@ -import { expect, test } from '@jest/globals'; +import { expect, test} from '@jest/globals'; +import { K8s, kind } from "kubernetes-fluent-client"; import { zarfExec, retry } from "../common"; import * as path from 'path'; import { execSync } from 'child_process'; -import { K8s, kind } from "kubernetes-fluent-client"; import { rm } from 'fs/promises'; test('hello kitteh succeeds', async () => { const sourceRepoName = 'kitteh' - const expectedStatus = "success" - const expectedJobLogOutputs: string[] = ['Hello Kitteh']; + const expectedStatus = 'success' + const expectedJobLogOutputs: string[] = ['Hello Kitteh'] - await executeTest(sourceRepoName, expectedJobLogOutputs, expectedStatus); + await executeTest(sourceRepoName, expectedJobLogOutputs, expectedStatus) }, 90000); test('podman succeeds', async () => { const sourceRepoName = 'podman' - const expectedStatus = "success" - const expectedJobLogOutputs: string[] = ['STEP 1/2: FROM scratch', 'STEP 2/2: ADD test.txt /', 'COMMIT']; + const expectedStatus = 'success' + const expectedJobLogOutputs: string[] = ['STEP 1/2: FROM scratch', 'STEP 2/2: ADD test.txt /', 'COMMIT'] - await executeTest(sourceRepoName, expectedJobLogOutputs, expectedStatus); + await executeTest(sourceRepoName, expectedJobLogOutputs, expectedStatus) }, 90000); test('podman fails', async () => { const sourceRepoName = 'podman' - const expectedStatus = "failed" - const expectedJobLogOutputs: string[] = []; + const expectedStatus = 'failed' + const expectedJobLogOutputs: string[] = [] - await executeTest(sourceRepoName, expectedJobLogOutputs, expectedStatus); + await executeTest(sourceRepoName, expectedJobLogOutputs, expectedStatus) }, 90000); @@ -38,19 +38,19 @@ async function executeTest(sourceRepoName: string, expectedJobLogOutputs: string const nowMillis = Date.now(); const tokenName = `if-you-see-me-in-production-something-is-horribly-wrong-${nowMillis}` - var sourceDir = path.join(__dirname, 'repo-sources', sourceRepoName); + var sourceDir = path.join(__dirname, 'repo-sources', sourceRepoName) // Get the toolbox pod and add a token to the root GitLab user await createToken(tokenName); - const headers: HeadersInit = [["PRIVATE-TOKEN", tokenName]]; + const headers: HeadersInit = [["PRIVATE-TOKEN", tokenName]] - const gitLabProjectName = `${sourceRepoName}-${nowMillis}`; - const projectId = await createNewGitlabProject(sourceDir, tokenName, gitLabProjectName, headers); + const gitLabProjectName = `${sourceRepoName}-${nowMillis}` + const projectId = await createNewGitlabProject(sourceDir, tokenName, gitLabProjectName, headers) - await unprotectRunner(headers, tokenName); + await unprotectRunner(headers, tokenName) - // Check that the pipeline actually ran as expected - await checkJobResults(projectId, headers, expectedJobLogOutputs, expectedStatus); + // Check that the pipeline ran as expected + await checkJobResults(projectId, headers, expectedJobLogOutputs, expectedStatus) } @@ -58,7 +58,6 @@ async function createToken(tokenName: string) { var nowMillis = Date.now(); const toolboxPods = await K8s(kind.Pod).InNamespace("gitlab").WithLabel("app", "toolbox").Get(); const toolboxPod = toolboxPods.items.at(0); - console.log('Using gitlab-rails runner to configure root token'); zarfExec(["tools", "kubectl", "--namespace", "gitlab", @@ -73,29 +72,29 @@ async function createToken(tokenName: string) { async function createNewGitlabProject(sourceDir: string, tokenName: string, gitLabProjectName: string, headers: HeadersInit) { //console.log(`Setting up new git repo at ${gitRepoDir}`); //copyFilesToGitRepoDir(sourceDir, gitRepoDir); - const millis = Date.now(); + const millis = Date.now() await deleteDirectory(path.join(sourceDir, '.git')) - execSync('git init', { cwd: sourceDir }); - execSync('git add . ', { cwd: sourceDir }); - execSync('git config commit.gpgsign false', { cwd: sourceDir }); // need this so that gpg signing doesn't attempt to happen locally when running tests - execSync('git commit -m "Initial commit" ', { cwd: sourceDir }); - execSync(`git remote add origin https://root:${tokenName}@gitlab.uds.dev/root/${gitLabProjectName}.git`, { cwd: sourceDir }); - execSync('git push -u origin --all', { cwd: sourceDir }); + execSync('git init', { cwd: sourceDir }) + execSync('git add . ', { cwd: sourceDir }) + execSync('git config commit.gpgsign false', { cwd: sourceDir }) // need this so that gpg signing doesn't attempt to happen locally when running tests + execSync('git commit -m "Initial commit" ', { cwd: sourceDir }) + execSync(`git remote add origin https://root:${tokenName}@gitlab.uds.dev/root/${gitLabProjectName}.git`, { cwd: sourceDir }) + execSync('git push -u origin --all', { cwd: sourceDir }) await deleteDirectory(path.join(sourceDir, '.git')) console.log(`Finding project id for project name [${encodeURIComponent(gitLabProjectName)}]`) - const projectResp = await fetch(`https://gitlab.uds.dev/api/v4/projects?search=${encodeURIComponent(gitLabProjectName)}`, { headers }); - const projects = await projectResp.json(); + const projectResp = await fetch(`https://gitlab.uds.dev/api/v4/projects?search=${encodeURIComponent(gitLabProjectName)}`, { headers }) + const projects = await projectResp.json() - const project = projects.find((p: { name: string; }) => p.name === gitLabProjectName); - const projectId = project?.id; + const project = projects.find((p: { name: string; }) => p.name === gitLabProjectName) + const projectId = project?.id console.log(`Found project id [${projectId}]`) - return projectId; + return projectId } async function unprotectRunner(headers: HeadersInit, tokenName: string) { - const runnerIDResp = await (await fetch(`https://gitlab.uds.dev/api/v4/runners/all`, { headers })).json(); - const runnerID = runnerIDResp[0].id; + const runnerIDResp = await (await fetch(`https://gitlab.uds.dev/api/v4/runners/all`, { headers })).json() + const runnerID = runnerIDResp[0].id const runnerResp = await fetch(`https://gitlab.uds.dev/api/v4/runners/${runnerID}`, { headers: [ ["PRIVATE-TOKEN", tokenName], @@ -104,38 +103,38 @@ async function unprotectRunner(headers: HeadersInit, tokenName: string) { body: "access_level=not_protected", method: "put" }); - expect(runnerResp.status).toBe(200); + expect(runnerResp.status).toBe(200) } async function checkJobResults(projectId: any, headers: HeadersInit, expectedJobLogOutputs: string[], expectedStatus: string) { let status = await retry(async () => { - const jobIDResp = await (await fetch(`https://gitlab.uds.dev/api/v4/projects/${projectId}/jobs`, { headers })).json(); + const jobIDResp = await (await fetch(`https://gitlab.uds.dev/api/v4/projects/${projectId}/jobs`, { headers })).json() // Print the job response (useful for debugging) - console.log(jobIDResp); + console.log(jobIDResp) if (jobIDResp.length > 0 && (jobIDResp[0].status === "success" || jobIDResp[0].status === "failed")) { const jobID = jobIDResp[0].id; - const jobLog = await (await fetch(`https://gitlab.uds.dev/api/v4/projects/${projectId}/jobs/${jobID}/trace`, { headers })).text(); + const jobLog = await (await fetch(`https://gitlab.uds.dev/api/v4/projects/${projectId}/jobs/${jobID}/trace`, { headers })).text() // Print the job log (useful for debugging) console.log(jobLog); expectedJobLogOutputs.forEach( expectedOutput => { - expect(jobLog).toContain(expectedOutput); + expect(jobLog).toContain(expectedOutput) }); return jobIDResp[0].status; } - return false; + return false }, 7, 7000); - expect(status).toBe(expectedStatus); + expect(status).toBe(expectedStatus) } async function deleteDirectory(path: string) { try { - await rm(path, { recursive: true, force: true }); - console.log(`Directory ${path} has been deleted successfully.`); + await rm(path, { recursive: true, force: true }) + console.log(`Directory ${path} has been deleted successfully.`) } catch (error) { - console.error(`Error while deleting directory ${path}:`, error); + console.error(`Error while deleting directory ${path}:`, error) } } From c2ef3c72fb7e49a5cf3a1a1f86f989393606e2ae Mon Sep 17 00:00:00 2001 From: Eric Wyles <23637493+ericwyles@users.noreply.github.com> Date: Fri, 23 Aug 2024 15:49:37 -0500 Subject: [PATCH 18/25] moar --- tests/journey/pipeline-run.test.ts | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/tests/journey/pipeline-run.test.ts b/tests/journey/pipeline-run.test.ts index 499b0ad..f891eb7 100644 --- a/tests/journey/pipeline-run.test.ts +++ b/tests/journey/pipeline-run.test.ts @@ -35,13 +35,13 @@ test('podman fails', async () => { async function executeTest(sourceRepoName: string, expectedJobLogOutputs: string[], expectedStatus: string) { - const nowMillis = Date.now(); + const nowMillis = Date.now() const tokenName = `if-you-see-me-in-production-something-is-horribly-wrong-${nowMillis}` var sourceDir = path.join(__dirname, 'repo-sources', sourceRepoName) // Get the toolbox pod and add a token to the root GitLab user - await createToken(tokenName); + await createToken(tokenName, nowMillis) const headers: HeadersInit = [["PRIVATE-TOKEN", tokenName]] const gitLabProjectName = `${sourceRepoName}-${nowMillis}` @@ -54,10 +54,9 @@ async function executeTest(sourceRepoName: string, expectedJobLogOutputs: string } -async function createToken(tokenName: string) { - var nowMillis = Date.now(); - const toolboxPods = await K8s(kind.Pod).InNamespace("gitlab").WithLabel("app", "toolbox").Get(); - const toolboxPod = toolboxPods.items.at(0); +async function createToken(tokenName: string, nowMillis: number) { + const toolboxPods = await K8s(kind.Pod).InNamespace("gitlab").WithLabel("app", "toolbox").Get() + const toolboxPod = toolboxPods.items.at(0) zarfExec(["tools", "kubectl", "--namespace", "gitlab", @@ -70,9 +69,6 @@ async function createToken(tokenName: string) { } async function createNewGitlabProject(sourceDir: string, tokenName: string, gitLabProjectName: string, headers: HeadersInit) { - //console.log(`Setting up new git repo at ${gitRepoDir}`); - //copyFilesToGitRepoDir(sourceDir, gitRepoDir); - const millis = Date.now() await deleteDirectory(path.join(sourceDir, '.git')) execSync('git init', { cwd: sourceDir }) execSync('git add . ', { cwd: sourceDir }) @@ -118,12 +114,12 @@ async function checkJobResults(projectId: any, headers: HeadersInit, expectedJob const jobLog = await (await fetch(`https://gitlab.uds.dev/api/v4/projects/${projectId}/jobs/${jobID}/trace`, { headers })).text() // Print the job log (useful for debugging) - console.log(jobLog); + console.log(jobLog) expectedJobLogOutputs.forEach( expectedOutput => { expect(jobLog).toContain(expectedOutput) }); - return jobIDResp[0].status; + return jobIDResp[0].status } return false }, 7, 7000); From 47a6d49be6c87b231720ad414812966a208ee9e7 Mon Sep 17 00:00:00 2001 From: Eric Wyles <23637493+ericwyles@users.noreply.github.com> Date: Mon, 26 Aug 2024 10:57:02 -0500 Subject: [PATCH 19/25] refactoring tests a little to cut down one redeploy --- tasks/test.yaml | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/tasks/test.yaml b/tasks/test.yaml index 8c2b57d..1ffad06 100644 --- a/tasks/test.yaml +++ b/tasks/test.yaml @@ -9,7 +9,16 @@ tasks: - task: gitlab-ingress # Run checks on initial deployment - task: glr-registration-check - - task: glr-run-check-defaults + - task: glr-run-check-default-security-capabilities + # Remove the GLR package and redeploy with additional capabilities enabled + # - task: remove:test-bundle + # - description: Deploy GitLab runner with SETUID and SETGID capabilities + # cmd: UDS_CONFIG=bundle/uds-config.yaml ./uds deploy bundle/uds-bundle-${BUNDLE_NAME}-${UDS_ARCH}-${BUNDLE_VERSION}.tar.zst --confirm --no-progress + # Create a runner token and hide the secret from the GLR package + - task: glr-create-runner-token + - task: glr-backup-registration-secret + # Remove the GLR package and redeploy with the manual token + - task: remove:test-bundle - description: Get the current UDS Bundle name cmd: cat bundle/uds-bundle.yaml | ./uds zarf tools yq .metadata.name setVariables: @@ -18,22 +27,13 @@ tasks: cmd: cat bundle/uds-bundle.yaml | ./uds zarf tools yq .metadata.version setVariables: - name: BUNDLE_VERSION - # Remove the GLR package and redeploy with additional capabilities enabled - - task: remove:test-bundle - - description: Deploy GitLab runner with SETUID and SETGID capabilities - cmd: UDS_CONFIG=bundle/uds-config.yaml ./uds deploy bundle/uds-bundle-${BUNDLE_NAME}-${UDS_ARCH}-${BUNDLE_VERSION}.tar.zst --confirm --no-progress --set ENABLE_SECURITY_CAPABILITIES=true - - task: glr-run-check-elevated-security-capabilities - # Create a runner token and hide the secret from the GLR package - - task: glr-create-runner-token - - task: glr-backup-registration-secret - # Remove the GLR package and redeploy with the manual token - - task: remove:test-bundle # TODO: (@WSTARR) Maru will complain about "cyclical" task imports if this imports the deploy task from uds-common. This is a bug: https://github.com/defenseunicorns/maru-runner/issues/122 - description: Deploys the current GitLab runner package - cmd: UDS_CONFIG=bundle/uds-config.yaml ./uds deploy bundle/uds-bundle-${BUNDLE_NAME}-${UDS_ARCH}-${BUNDLE_VERSION}.tar.zst --confirm --no-progress --set RUNNER_AUTH_TOKEN=${RUNNER_AUTH_TOKEN} + cmd: UDS_CONFIG=bundle/uds-config.yaml ./uds deploy bundle/uds-bundle-${BUNDLE_NAME}-${UDS_ARCH}-${BUNDLE_VERSION}.tar.zst --confirm --no-progress --set RUNNER_AUTH_TOKEN=${RUNNER_AUTH_TOKEN} --set ENABLE_SECURITY_CAPABILITIES=true # Check that the runner registered and restore the secret - task: glr-registration-check - task: glr-restore-registration-secret + - task: glr-run-check-elevated-security-capabilities - name: gitlab-ingress actions: @@ -63,7 +63,7 @@ tasks: dir: tests cmd: npm test -- journey/registration.test.ts - - name: glr-run-check-defaults + - name: glr-run-check-default-security-capabilities description: Check that a GitLab repository can trigger a gitlab runner to run actions: - description: Setup a repository and trigger a pipeline job From fe27a9b8b6b3b585bbce07ea530a5e5f46bbf28f Mon Sep 17 00:00:00 2001 From: Eric Wyles <23637493+ericwyles@users.noreply.github.com> Date: Mon, 26 Aug 2024 10:58:25 -0500 Subject: [PATCH 20/25] refactoring tests a little to cut down one redeploy --- tasks/test.yaml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tasks/test.yaml b/tasks/test.yaml index 1ffad06..1855f6f 100644 --- a/tasks/test.yaml +++ b/tasks/test.yaml @@ -10,10 +10,6 @@ tasks: # Run checks on initial deployment - task: glr-registration-check - task: glr-run-check-default-security-capabilities - # Remove the GLR package and redeploy with additional capabilities enabled - # - task: remove:test-bundle - # - description: Deploy GitLab runner with SETUID and SETGID capabilities - # cmd: UDS_CONFIG=bundle/uds-config.yaml ./uds deploy bundle/uds-bundle-${BUNDLE_NAME}-${UDS_ARCH}-${BUNDLE_VERSION}.tar.zst --confirm --no-progress # Create a runner token and hide the secret from the GLR package - task: glr-create-runner-token - task: glr-backup-registration-secret From 74287c2b053dcbbcd4c8b2bf0e79af20857190d0 Mon Sep 17 00:00:00 2001 From: Eric Wyles <23637493+ericwyles@users.noreply.github.com> Date: Mon, 26 Aug 2024 10:59:48 -0500 Subject: [PATCH 21/25] don't need the gitignore --- .gitignore | 3 --- 1 file changed, 3 deletions(-) diff --git a/.gitignore b/.gitignore index 145c016..b5d753f 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,3 @@ overlay-values-* # Dependency files uds-config-gitlab.yaml - -# Temporary .git dirs made for temp repos that are pushed to gitlab during testing -**/repo-sources/**/.git From fe37570f85f63b9ff4210485b591731ca612f00f Mon Sep 17 00:00:00 2001 From: Eric Wyles <23637493+ericwyles@users.noreply.github.com> Date: Mon, 26 Aug 2024 16:08:02 -0500 Subject: [PATCH 22/25] docs --- docs/configuration.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/configuration.md b/docs/configuration.md index 0480d5e..1cf2410 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -49,6 +49,12 @@ By default the sandbox is excluded from being mutated by Zarf to allow external > [!TIP] > The default registry behavior relies on the `###ZARF_REGISTRY###` internal value as outlined in the [Zarf documentation](https://docs.zarf.dev/ref/values/#internal-values-zarf). This value is applied during Zarf deploy so cannot be used by GitLab when spawning pods. If you do know the address of the Zarf registry (`127.0.0.1:31999` by default) you can still pull from the Zarf registry however. +### Allow SETUID and SETGID security capabilities + +By default the runner build containers do not have `SETUID` and `SETGID` capabilities enabled, which means tools like [Buildah](https://buildah.io/) and [Podman](https://podman.io/) have limited functionality. Podman cannot run container image builds at all, and Buildah can build very simple images but anything that manipulates users or groups (e.g running `useradd` or `groupadd` within a Dockerfile) will fail. + +To enable `SETUID` and `SETGID` capabilities on the build containers, set the Zarf variable `ENABLE_SECURITY_CAPABILITIES` to `true`. This will (set a security policity for the build container)[https://docs.gitlab.com/runner/executors/kubernetes/#set-a-security-policy-for-the-container] to add `SETUID` and `SETGID` capabilities. It will also add a (UDS Policy Exemption)[https://uds.defenseunicorns.com/core/configuration/uds-configure-policy-exemptions/] to allow these capabilities. + ### Change the Runner Service Account By default the chart will create a service account named `gitlab-runner`. You can change the name of this service account by by overriding the `serviceAccountName` value in the `uds-gitlab-runner-config` chart along with the `rbac.generatedServiceAccountName` value in the `gitlab-runner` chart. From e4d440d3a0d54ecd3f0f1fe40f96a18a8a30c70e Mon Sep 17 00:00:00 2001 From: Eric Wyles <23637493+ericwyles@users.noreply.github.com> Date: Mon, 26 Aug 2024 16:14:12 -0500 Subject: [PATCH 23/25] doc formatting --- docs/configuration.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index 1cf2410..8b5d34d 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -51,9 +51,9 @@ By default the sandbox is excluded from being mutated by Zarf to allow external ### Allow SETUID and SETGID security capabilities -By default the runner build containers do not have `SETUID` and `SETGID` capabilities enabled, which means tools like [Buildah](https://buildah.io/) and [Podman](https://podman.io/) have limited functionality. Podman cannot run container image builds at all, and Buildah can build very simple images but anything that manipulates users or groups (e.g running `useradd` or `groupadd` within a Dockerfile) will fail. +By default, runner build containers do not have `SETUID` and `SETGID` capabilities enabled. This limits the functionality of tools like [Buildah](https://buildah.io/) and [Podman](https://podman.io/). Podman cannot build container images, and Buildah can only create very basic images. Any actions that involve user or group modifications (e.g., using useradd or groupadd in a Dockerfile) will fail. -To enable `SETUID` and `SETGID` capabilities on the build containers, set the Zarf variable `ENABLE_SECURITY_CAPABILITIES` to `true`. This will (set a security policity for the build container)[https://docs.gitlab.com/runner/executors/kubernetes/#set-a-security-policy-for-the-container] to add `SETUID` and `SETGID` capabilities. It will also add a (UDS Policy Exemption)[https://uds.defenseunicorns.com/core/configuration/uds-configure-policy-exemptions/] to allow these capabilities. +To enable `SETUID` and `SETGID` capabilities in the build containers, set the `ENABLE_SECURITY_CAPABILITIES` Zarf variable to `true`. This will [apply a security policy for the build container](https://docs.gitlab.com/runner/executors/kubernetes/#set-a-security-policy-for-the-container) to add SETUID and SETGID capabilities. Additionally, it will [add a UDS Policy Exemption](https://uds.defenseunicorns.com/core/configuration/uds-configure-policy-exemptions/) to permit these capabilities. ### Change the Runner Service Account From 667319133b9a7e916d6b7191455b5f1cade50f1d Mon Sep 17 00:00:00 2001 From: Eric Wyles <23637493+ericwyles@users.noreply.github.com> Date: Mon, 26 Aug 2024 17:36:10 -0500 Subject: [PATCH 24/25] pull domain suffix from env var --- tests/journey/pipeline-run.test.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/tests/journey/pipeline-run.test.ts b/tests/journey/pipeline-run.test.ts index f891eb7..1e47da2 100644 --- a/tests/journey/pipeline-run.test.ts +++ b/tests/journey/pipeline-run.test.ts @@ -5,12 +5,14 @@ import * as path from 'path'; import { execSync } from 'child_process'; import { rm } from 'fs/promises'; +const domainSuffix = process.env.DOMAIN_SUFFIX || ".uds.dev" + test('hello kitteh succeeds', async () => { const sourceRepoName = 'kitteh' const expectedStatus = 'success' const expectedJobLogOutputs: string[] = ['Hello Kitteh'] - await executeTest(sourceRepoName, expectedJobLogOutputs, expectedStatus) + //await executeTest(sourceRepoName, expectedJobLogOutputs, expectedStatus) }, 90000); @@ -74,12 +76,12 @@ async function createNewGitlabProject(sourceDir: string, tokenName: string, gitL execSync('git add . ', { cwd: sourceDir }) execSync('git config commit.gpgsign false', { cwd: sourceDir }) // need this so that gpg signing doesn't attempt to happen locally when running tests execSync('git commit -m "Initial commit" ', { cwd: sourceDir }) - execSync(`git remote add origin https://root:${tokenName}@gitlab.uds.dev/root/${gitLabProjectName}.git`, { cwd: sourceDir }) + execSync(`git remote add origin https://root:${tokenName}@gitlab${domainSuffix}/root/${gitLabProjectName}.git`, { cwd: sourceDir }) execSync('git push -u origin --all', { cwd: sourceDir }) await deleteDirectory(path.join(sourceDir, '.git')) console.log(`Finding project id for project name [${encodeURIComponent(gitLabProjectName)}]`) - const projectResp = await fetch(`https://gitlab.uds.dev/api/v4/projects?search=${encodeURIComponent(gitLabProjectName)}`, { headers }) + const projectResp = await fetch(`https://gitlab${domainSuffix}/api/v4/projects?search=${encodeURIComponent(gitLabProjectName)}`, { headers }) const projects = await projectResp.json() const project = projects.find((p: { name: string; }) => p.name === gitLabProjectName) @@ -89,9 +91,9 @@ async function createNewGitlabProject(sourceDir: string, tokenName: string, gitL } async function unprotectRunner(headers: HeadersInit, tokenName: string) { - const runnerIDResp = await (await fetch(`https://gitlab.uds.dev/api/v4/runners/all`, { headers })).json() + const runnerIDResp = await (await fetch(`https://gitlab${domainSuffix}/api/v4/runners/all`, { headers })).json() const runnerID = runnerIDResp[0].id - const runnerResp = await fetch(`https://gitlab.uds.dev/api/v4/runners/${runnerID}`, { + const runnerResp = await fetch(`https://gitlab${domainSuffix}/api/v4/runners/${runnerID}`, { headers: [ ["PRIVATE-TOKEN", tokenName], ["Content-Type", "application/x-www-form-urlencoded"] @@ -104,14 +106,14 @@ async function unprotectRunner(headers: HeadersInit, tokenName: string) { async function checkJobResults(projectId: any, headers: HeadersInit, expectedJobLogOutputs: string[], expectedStatus: string) { let status = await retry(async () => { - const jobIDResp = await (await fetch(`https://gitlab.uds.dev/api/v4/projects/${projectId}/jobs`, { headers })).json() + const jobIDResp = await (await fetch(`https://gitlab${domainSuffix}/api/v4/projects/${projectId}/jobs`, { headers })).json() // Print the job response (useful for debugging) console.log(jobIDResp) if (jobIDResp.length > 0 && (jobIDResp[0].status === "success" || jobIDResp[0].status === "failed")) { const jobID = jobIDResp[0].id; - const jobLog = await (await fetch(`https://gitlab.uds.dev/api/v4/projects/${projectId}/jobs/${jobID}/trace`, { headers })).text() + const jobLog = await (await fetch(`https://gitlab${domainSuffix}/api/v4/projects/${projectId}/jobs/${jobID}/trace`, { headers })).text() // Print the job log (useful for debugging) console.log(jobLog) From 7a0711256a32c2dc3308f0b130bbd1fa8e47a633 Mon Sep 17 00:00:00 2001 From: Eric Wyles <23637493+ericwyles@users.noreply.github.com> Date: Mon, 26 Aug 2024 17:58:17 -0500 Subject: [PATCH 25/25] shouldn't have been commented --- tests/journey/pipeline-run.test.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/journey/pipeline-run.test.ts b/tests/journey/pipeline-run.test.ts index 1e47da2..32f89ee 100644 --- a/tests/journey/pipeline-run.test.ts +++ b/tests/journey/pipeline-run.test.ts @@ -12,8 +12,7 @@ test('hello kitteh succeeds', async () => { const expectedStatus = 'success' const expectedJobLogOutputs: string[] = ['Hello Kitteh'] - //await executeTest(sourceRepoName, expectedJobLogOutputs, expectedStatus) - + await executeTest(sourceRepoName, expectedJobLogOutputs, expectedStatus) }, 90000);