From cdf3ef9a70796d47a6247ad1300d2e6bb7474cf5 Mon Sep 17 00:00:00 2001 From: Jacek Chmielewski Date: Mon, 10 Aug 2026 11:39:58 +0200 Subject: [PATCH 1/5] continue on postures step during network creation test (#3524) --- e2e/utils/controllers/vpn/createNetwork.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/e2e/utils/controllers/vpn/createNetwork.ts b/e2e/utils/controllers/vpn/createNetwork.ts index dfd295234c..29a32db95b 100644 --- a/e2e/utils/controllers/vpn/createNetwork.ts +++ b/e2e/utils/controllers/vpn/createNetwork.ts @@ -93,6 +93,7 @@ export const createServiceLocation = async (browser: Browser, network: NetworkFo await page.getByTestId('continue').click(); await page.getByTestId('continue').click(); await page.getByTestId('acl-continue').click(); + await page.getByTestId('posture-continue').click(); await page.getByTestId('create-location').click(); await page.locator('.icon-button .icon[data-kind="close"]').click(); From 760e78ad67f2e83d9bd04229f66936df16e413e5 Mon Sep 17 00:00:00 2001 From: Kuba <78603704+jakub-tldr@users.noreply.github.com> Date: Tue, 11 Aug 2026 14:33:02 +0200 Subject: [PATCH 2/5] prevent showing configuration for locations with posture checks (#3528) --- crates/defguard_core/src/handlers/network_devices.rs | 4 +++- crates/defguard_core/src/handlers/wireguard.rs | 3 ++- web/messages/en/profile.json | 1 + web/src/pages/UsersOverviewPage/UsersTable.tsx | 9 +++++++++ .../ProfileDevicesTable/ProfileDevicesTable.tsx | 9 +++++++++ web/src/shared/api/types.ts | 1 + .../ModalDeviceConfigSection.tsx | 9 +++++++-- 7 files changed, 32 insertions(+), 4 deletions(-) diff --git a/crates/defguard_core/src/handlers/network_devices.rs b/crates/defguard_core/src/handlers/network_devices.rs index 9df878f738..c473c0ee29 100644 --- a/crates/defguard_core/src/handlers/network_devices.rs +++ b/crates/defguard_core/src/handlers/network_devices.rs @@ -124,6 +124,7 @@ pub(crate) struct DeviceWireGuardConfig { pub(crate) network_name: String, pub(crate) config: String, pub(crate) location_mfa_mode: LocationMfaMode, + pub(crate) posture_check_required: bool, } /// Get the WireGuard configuration of a network device @@ -138,7 +139,7 @@ pub(crate) struct DeviceWireGuardConfig { ), responses( (status = 200, description = "Network device configuration for each location of the device.", body = [Object], example = json!([ - {"network_id": 1, "network_name": "office", "config": "[Interface]\n...", "location_mfa_mode": "disabled"} + {"network_id": 1, "network_name": "office", "config": "[Interface]\n...", "location_mfa_mode": "disabled", "posture_check_required": false} ])), (status = 401, description = "Session is missing or invalid.", body = ApiErrorResponse, example = json!({"msg": "Session is required"})), (status = 403, description = "Requires admin privileges or the request must target your own account.", body = ApiErrorResponse, example = json!({"msg": "requires privileged access"})), @@ -196,6 +197,7 @@ pub(crate) async fn network_device_configs( network_name: device_config.network_name, config: device_config.config, location_mfa_mode: device_config.location_mfa_mode, + posture_check_required: device_config.posture_check_required, }; result.push(device_config); } diff --git a/crates/defguard_core/src/handlers/wireguard.rs b/crates/defguard_core/src/handlers/wireguard.rs index ec4148c3fd..9d362ca18c 100644 --- a/crates/defguard_core/src/handlers/wireguard.rs +++ b/crates/defguard_core/src/handlers/wireguard.rs @@ -1499,7 +1499,7 @@ pub(crate) async fn download_config( ), responses( (status = 200, description = "Device configuration for each location.", body = [Object], example = json!([ - {"network_id": 1, "network_name": "office", "config": "[Interface]\n...", "location_mfa_mode": "disabled"} + {"network_id": 1, "network_name": "office", "config": "[Interface]\n...", "location_mfa_mode": "disabled", "posture_check_required": false} ])), (status = 401, description = "Session is missing or invalid.", body = ApiErrorResponse, example = json!({"msg": "Session is required"})), (status = 403, description = "Requires admin privileges or the request must target your own account.", body = ApiErrorResponse, example = json!({"msg": "requires privileged access"})), @@ -1556,6 +1556,7 @@ pub(crate) async fn user_device_configs( network_name: device_config.network_name, config: device_config.config, location_mfa_mode: device_config.location_mfa_mode, + posture_check_required: device_config.posture_check_required, }); } diff --git a/web/messages/en/profile.json b/web/messages/en/profile.json index 0ca9de3e3b..6e1de2eeb6 100644 --- a/web/messages/en/profile.json +++ b/web/messages/en/profile.json @@ -42,6 +42,7 @@ "profile_devices_menu_show_config": "Show configuration", "profile_devices_menu_ip_settings": "Device IP settings", "profile_devices_ip_settings_load_failed": "Failed to load device IP settings", + "profile_devices_config_no_locations": "Cannot show configuration, no location is available for this device", "profile_devices_tooltip_biometric": "Biometric is enabled for this device", "user_device_delete_success": "Device deleted", "user_device_delete_failed": "Failed to delete device", diff --git a/web/src/pages/UsersOverviewPage/UsersTable.tsx b/web/src/pages/UsersOverviewPage/UsersTable.tsx index e2f2c59ddc..81185e03d3 100644 --- a/web/src/pages/UsersOverviewPage/UsersTable.tsx +++ b/web/src/pages/UsersOverviewPage/UsersTable.tsx @@ -683,6 +683,15 @@ export const UsersTable = () => { text: m.profile_devices_menu_show_config(), onClick: () => { api.device.getDeviceConfigs(device).then((modalData) => { + const hasConfigs = modalData.configs.some( + (c) => + c.location_mfa_mode === LocationMfaMode.Disabled && + !c.posture_check_required, + ); + if (!hasConfigs) { + Snackbar.error(m.profile_devices_config_no_locations()); + return; + } openModal(ModalName.UserDeviceConfig, modalData); }); }, diff --git a/web/src/pages/user-profile/UserProfilePage/tabs/ProfileDevicesTab/components/ProfileDevicesTable/ProfileDevicesTable.tsx b/web/src/pages/user-profile/UserProfilePage/tabs/ProfileDevicesTab/components/ProfileDevicesTable/ProfileDevicesTable.tsx index 9b004a685b..93b3a697e5 100644 --- a/web/src/pages/user-profile/UserProfilePage/tabs/ProfileDevicesTab/components/ProfileDevicesTable/ProfileDevicesTable.tsx +++ b/web/src/pages/user-profile/UserProfilePage/tabs/ProfileDevicesTab/components/ProfileDevicesTable/ProfileDevicesTable.tsx @@ -177,6 +177,15 @@ const DevicesTable = ({ rowData }: { rowData: RowData[] }) => { text: m.profile_devices_menu_show_config(), onClick: () => { api.device.getDeviceConfigs(row).then((modalData) => { + const hasConfigs = modalData.configs.some( + (c) => + c.location_mfa_mode === LocationMfaMode.Disabled && + !c.posture_check_required, + ); + if (!hasConfigs) { + Snackbar.error(m.profile_devices_config_no_locations()); + return; + } openModal(ModalName.UserDeviceConfig, modalData); }); }, diff --git a/web/src/shared/api/types.ts b/web/src/shared/api/types.ts index 21dd88f285..73fed0c637 100644 --- a/web/src/shared/api/types.ts +++ b/web/src/shared/api/types.ts @@ -599,6 +599,7 @@ export interface AddDeviceResponseConfig { network_name: string; config: string; location_mfa_mode: LocationMfaModeValue; + posture_check_required: boolean; } export interface AddDeviceResponse { diff --git a/web/src/shared/components/ModalDeviceConfigSection/ModalDeviceConfigSection.tsx b/web/src/shared/components/ModalDeviceConfigSection/ModalDeviceConfigSection.tsx index 71d2e42121..a16bf7ed0d 100644 --- a/web/src/shared/components/ModalDeviceConfigSection/ModalDeviceConfigSection.tsx +++ b/web/src/shared/components/ModalDeviceConfigSection/ModalDeviceConfigSection.tsx @@ -38,7 +38,11 @@ export const ModalDeviceConfigSection = ({ data: response, privateKey }: Props) const selectOptions = useMemo( () => response.configs - .filter((item) => item.location_mfa_mode === LocationMfaMode.Disabled) + .filter( + (item) => + item.location_mfa_mode === LocationMfaMode.Disabled && + !item.posture_check_required, + ) .map((item): SelectOption => configToOption(item)), [response.configs], ); @@ -69,7 +73,8 @@ export const ModalDeviceConfigSection = ({ data: response, privateKey }: Props) const handleDownloadAll = useCallback(async () => { if (!response) return; const nonMfaConfigs = response.configs.filter( - (c) => c.location_mfa_mode === LocationMfaMode.Disabled, + (c) => + c.location_mfa_mode === LocationMfaMode.Disabled && !c.posture_check_required, ); let data: AddDeviceResponseConfig[] = []; if (isPresent(privateKey)) { From 2e3d3113c8a3b5a7388c4310c104ca18b24a327b Mon Sep 17 00:00:00 2001 From: Kuba <78603704+jakub-tldr@users.noreply.github.com> Date: Mon, 17 Aug 2026 09:05:44 +0200 Subject: [PATCH 3/5] fix location layout in rules (#3562) --- web/src/pages/CERulePage/style.scss | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/web/src/pages/CERulePage/style.scss b/web/src/pages/CERulePage/style.scss index c52f7ee7cb..43ab035793 100644 --- a/web/src/pages/CERulePage/style.scss +++ b/web/src/pages/CERulePage/style.scss @@ -83,10 +83,12 @@ } } -.selection-section .item .destination-selection-item { +.selection-section .item .destination-selection-item, +.selection-section .item .location-selection-item { display: grid; - grid-template-columns: auto 1fr; + grid-template-columns: auto 1fr auto; grid-template-rows: 1fr; + align-items: center; column-gap: var(--spacing-md); width: 100%; overflow: hidden; From aadc92fca4c481ef09f6d12d5183621485e0ad9f Mon Sep 17 00:00:00 2001 From: Kuba <78603704+jakub-tldr@users.noreply.github.com> Date: Mon, 17 Aug 2026 09:10:26 +0200 Subject: [PATCH 4/5] exclude posture gated locations (#3559) --- .../pages/NetworkDevicesPage/NetworkDevicesTable.tsx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/web/src/pages/NetworkDevicesPage/NetworkDevicesTable.tsx b/web/src/pages/NetworkDevicesPage/NetworkDevicesTable.tsx index 28c6289e65..69d98eefc0 100644 --- a/web/src/pages/NetworkDevicesPage/NetworkDevicesTable.tsx +++ b/web/src/pages/NetworkDevicesPage/NetworkDevicesTable.tsx @@ -56,9 +56,13 @@ export const NetworkDevicesTable = ({ networkDevices }: Props) => { mutationFn: async () => { const { data: locations } = await api.location.getLocations(); const availableLocations = orderBy( - locations.filter( - (location) => location.location_mfa_mode === LocationMfaMode.Disabled, - ), + locations.filter((location) => { + const withoutPostureChecks = (location.posture_checks?.length ?? 0) === 0; + return ( + location.location_mfa_mode === LocationMfaMode.Disabled && + withoutPostureChecks + ); + }), ['name'], ['asc'], ); From 0c0187afeb6a3bf4eab70beab72779348c301a15 Mon Sep 17 00:00:00 2001 From: jakub-tldr <78603704+jakub-tldr@users.noreply.github.com> Date: Mon, 17 Aug 2026 08:30:07 +0000 Subject: [PATCH 5/5] [create-pull-request] automated change --- .github/workflows/alert-e2e-failure.yml | 80 ----- .github/workflows/build-docker.yml | 152 ---------- .github/workflows/ci.yml | 153 +++++----- .github/workflows/current.yml | 51 ---- .github/workflows/dev-deployment.yml | 20 -- .github/workflows/e2e.yml | 320 -------------------- .github/workflows/lint-e2e.yml | 44 --- .github/workflows/lint-web.yml | 4 +- .github/workflows/publish-docker-latest.yml | 54 ---- .github/workflows/publish-openapi.yml | 58 ---- .github/workflows/release.yml | 314 +++++++++---------- .github/workflows/sbom-regenerate.yml | 39 --- .github/workflows/sbom.yml | 99 ------ .github/workflows/staging-deployment.yml | 22 -- .github/workflows/test-apt-repo.yml | 112 ------- .github/workflows/test-web.yml | 4 +- .github/workflows/update-repositories.yml | 149 --------- .github/workflows/upstream-sync.yml | 48 +++ 18 files changed, 287 insertions(+), 1436 deletions(-) delete mode 100644 .github/workflows/alert-e2e-failure.yml delete mode 100644 .github/workflows/build-docker.yml delete mode 100644 .github/workflows/current.yml delete mode 100644 .github/workflows/dev-deployment.yml delete mode 100644 .github/workflows/e2e.yml delete mode 100644 .github/workflows/lint-e2e.yml delete mode 100644 .github/workflows/publish-docker-latest.yml delete mode 100644 .github/workflows/publish-openapi.yml delete mode 100644 .github/workflows/sbom-regenerate.yml delete mode 100644 .github/workflows/sbom.yml delete mode 100644 .github/workflows/staging-deployment.yml delete mode 100644 .github/workflows/test-apt-repo.yml delete mode 100644 .github/workflows/update-repositories.yml create mode 100644 .github/workflows/upstream-sync.yml diff --git a/.github/workflows/alert-e2e-failure.yml b/.github/workflows/alert-e2e-failure.yml deleted file mode 100644 index e1f2916de3..0000000000 --- a/.github/workflows/alert-e2e-failure.yml +++ /dev/null @@ -1,80 +0,0 @@ -name: E2E failure alert -on: - workflow_call: - inputs: - source: - type: string - default: e2e - description: 'Alert source identifier (change only for test harnesses)' - extra_labels: - type: string - default: e2e - description: 'Additional labels beyond release-blocker' - secrets: - ALERT_TOKEN: - required: true - -permissions: - contents: read - -jobs: - alert: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - with: - fetch-depth: 0 - - - name: Find last green e2e run - id: last-green - run: | - LAST_GREEN=$(gh run list \ - --repo '${{ github.repository }}' \ - --branch '${{ github.ref_name }}' \ - --workflow e2e.yml \ - --status success \ - --limit 1 \ - --json headSha \ - --jq '.[0].headSha // ""') - echo "sha=$LAST_GREEN" >> $GITHUB_OUTPUT - env: - GH_TOKEN: ${{ github.token }} - - - name: Compute assignees - id: assignees - run: | - LAST_GREEN="${{ steps.last-green.outputs.sha }}" - - if [[ -n "$LAST_GREEN" ]]; then - SHAS=$(git log --format='%H' "$LAST_GREEN..HEAD" | head -20) - else - SHAS=$(git log -1 --format='%H' HEAD) - fi - - USERNAMES="" - for sha in $SHAS; do - USER=$(gh api "repos/${{ github.repository }}/commits/$sha" \ - --jq '.author.login // empty' 2>/dev/null || echo "") - [[ -z "$USER" ]] && continue - [[ ",$USERNAMES," == *",$USER,"* ]] && continue - USERNAMES="${USERNAMES}${USERNAMES:+,}${USER}" - done - USERNAMES=$(echo "$USERNAMES" | tr ',' '\n' | head -5 | tr '\n' ',' | sed 's/,$//') - - echo "usernames=$USERNAMES" >> $GITHUB_OUTPUT - env: - GH_TOKEN: ${{ github.token }} - - - name: File alert issue - uses: DefGuard/ci-workflows/actions/alert-issue@v1.0.0 - with: - source: ${{ inputs.source }} - repo: ${{ github.repository }} - branch: ${{ github.ref_name }} - failure_summary: e2e suite failed - run_link: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} - assignees: ${{ steps.assignees.outputs.usernames }} - extra_labels: ${{ inputs.extra_labels }} - env: - ALERT_TOKEN: ${{ secrets.ALERT_TOKEN }} - SPRINT_PROJECT_NUMBER: ${{ vars.SPRINT_PROJECT_NUMBER }} diff --git a/.github/workflows/build-docker.yml b/.github/workflows/build-docker.yml deleted file mode 100644 index 0d8dd4e1d6..0000000000 --- a/.github/workflows/build-docker.yml +++ /dev/null @@ -1,152 +0,0 @@ -name: Build Docker image - -on: - workflow_call: - inputs: - tags: - description: "List of tags as key-value pair attributes" - required: false - type: string - build-version: - description: "Optional version embedded into compiled Defguard binaries" - required: false - type: string - default: "" - flavor: - description: "List of flavors as key-value pair attributes" - required: false - type: string - trivy-exit-code: - description: "Exit code for Trivy when vulnerabilities are found (0 = warn only, 1 = fail)" - required: false - type: string - default: "1" - -env: - GHCR_REPO: ghcr.io/defguard/defguard - -jobs: - build-docker: - runs-on: - - codebuild-defguard-core-runner-${{ github.run_id }}-${{ github.run_attempt }} - image:${{ matrix.os }} - instance-size:${{ matrix.size }} - - strategy: - matrix: - cpu: [arm64, amd64] - include: - - os: arm-3.0 - size: xlarge - cpu: arm64 - tag: arm64 - - os: ubuntu-7.0 - size: xlarge - cpu: amd64 - tag: amd64 - - permissions: - contents: read - packages: write - - steps: - - name: Checkout - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - with: - submodules: recursive - - - name: Login to GitHub container registry - uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 - - - name: Sanitize branch name - run: echo "SAFE_REF=${GITHUB_REF_NAME//\//-}" >> $GITHUB_ENV - - - name: Resolve build version - id: build-version - env: - INPUT_BUILD_VERSION: ${{ inputs.build-version }} - run: echo "value=${INPUT_BUILD_VERSION#v}" >> "$GITHUB_OUTPUT" - - - name: Build container - uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0 - with: - context: . - build-args: DEFGUARD_BUILD_VERSION=${{ steps.build-version.outputs.value }} - platforms: linux/${{ matrix.cpu }} - provenance: false - push: true - tags: "${{ env.GHCR_REPO }}:${{ github.sha }}-${{ matrix.tag }}" - cache-from: | - type=registry,ref=${{ env.GHCR_REPO }}:cache-${{ matrix.tag }} - type=registry,ref=${{ env.GHCR_REPO }}:cache-${{ matrix.tag }}-${{ env.SAFE_REF }} - cache-to: type=registry,mode=max,ref=${{ env.GHCR_REPO }}:cache-${{ matrix.tag }}-${{ env.SAFE_REF }} - - - name: Scan image with Trivy - uses: aquasecurity/trivy-action@a9c7b0f06e461e9d4b4d1711f154ee024b8d7ab8 # v0.36.0 - env: - TRIVY_SHOW_SUPPRESSED: 1 - TRIVY_IGNOREFILE: "./.trivyignore.yaml" - with: - image-ref: "${{ env.GHCR_REPO }}:${{ github.sha }}-${{ matrix.tag }}" - format: "table" - exit-code: ${{ inputs.trivy-exit-code }} - ignore-unfixed: true - vuln-type: "os,library" - severity: "CRITICAL,HIGH,MEDIUM" - - docker-manifest: - runs-on: [self-hosted, Linux] - - permissions: - contents: read - packages: write - id-token: write # needed for signing the images with GitHub OIDC Token - - needs: [build-docker] - - steps: - - name: Install Cosign - uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 - - - name: Docker meta - id: meta - uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0 - with: - images: | - ${{ env.GHCR_REPO }} - flavor: ${{ inputs.flavor }} - tags: ${{ inputs.tags }} - - - name: Login to GitHub container registry - uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Create and push manifests - run: | - tags='${{ env.GHCR_REPO }}:${{ github.sha }} ${{ steps.meta.outputs.tags }}' - for tag in ${tags} - do - docker manifest rm ${tag} || true - docker manifest create ${tag} ${{ env.GHCR_REPO }}:${{ github.sha }}-amd64 ${{ env.GHCR_REPO }}:${{ github.sha }}-arm64 - docker manifest push ${tag} - done - - - name: Sign the images with GitHub OIDC Token - run: | - images='${{ env.GHCR_REPO }}:${{ github.sha }} ${{ steps.meta.outputs.tags }}' - cosign sign --yes ${images} - - - name: Verify image signatures - run: | - images='${{ env.GHCR_REPO }}:${{ github.sha }} ${{ steps.meta.outputs.tags }}' - cosign verify ${images} --certificate-oidc-issuer https://token.actions.githubusercontent.com --certificate-identity-regexp="https://github.com/DefGuard/defguard" -o text diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 154504ebce..f4bcb36482 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,19 +25,15 @@ permissions: jobs: lint: runs-on: - - codebuild-defguard-core-runner-${{ github.run_id }}-${{ github.run_attempt }} - - instance-size:large - + - self-hosted + - Linux + - X64 container: public.ecr.aws/docker/library/rust:1 env: CARGO_TERM_COLOR: always SQLX_OFFLINE: true RUSTC_WRAPPER: sccache - SCCACHE_BUCKET: defguard-gh-build-cache - SCCACHE_REGION: eu-central-1 - AWS_ACCESS_KEY_ID: ${{ secrets.S3_CACHE_ACCESS_KEY }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.S3_CACHE_SECRET_KEY }} steps: - name: Checkout @@ -76,6 +72,9 @@ jobs: severity: "CRITICAL,HIGH,MEDIUM" scanners: "vuln" + - name: Trust repository directory + run: git config --global --add safe.directory "$GITHUB_WORKSPACE" + - name: Install protoc run: apt-get update && apt-get -y install protobuf-compiler @@ -95,7 +94,7 @@ jobs: tool: cargo-deny - name: Run cargo deny - run: cargo deny check --hide-inclusion-graph + run: cargo deny check - name: Show sccache stats if: always() @@ -103,8 +102,9 @@ jobs: build: runs-on: - - codebuild-defguard-core-runner-${{ github.run_id }}-${{ github.run_attempt }} - - instance-size:2xlarge + - self-hosted + - Linux + - X64 container: public.ecr.aws/docker/library/rust:1 @@ -112,10 +112,6 @@ jobs: CARGO_TERM_COLOR: always SQLX_OFFLINE: true RUSTC_WRAPPER: sccache - SCCACHE_BUCKET: defguard-gh-build-cache - SCCACHE_REGION: eu-central-1 - AWS_ACCESS_KEY_ID: ${{ secrets.S3_CACHE_ACCESS_KEY }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.S3_CACHE_SECRET_KEY }} steps: - name: Checkout @@ -149,6 +145,9 @@ jobs: with: tool: cargo-nextest + - name: Mark workspace as safe for git + run: git config --global --add safe.directory "$GITHUB_WORKSPACE" + - name: Build and archive tests run: | cargo nextest archive \ @@ -171,10 +170,10 @@ jobs: test: needs: build - runs-on: - - codebuild-defguard-core-runner-${{ github.run_id }}-${{ github.run_attempt }} - - instance-size:large + - self-hosted + - Linux + - X64 container: public.ecr.aws/docker/library/rust:1 @@ -230,68 +229,68 @@ jobs: --no-fail-fast \ --archive-file nextest-archive.tar.zst \ --partition hash:${{ matrix.partition }}/8 - - test-ldap: - needs: build - - runs-on: - - codebuild-defguard-core-runner-${{ github.run_id }}-${{ github.run_attempt }} - - instance-size:large - - steps: - - name: Checkout - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - with: - submodules: recursive - fetch-depth: 1 - - - name: Download test archive - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - with: - name: nextest-archive - - - name: Download cargo-nextest binary - run: curl -LsSf https://get.nexte.st/latest/linux | tar zxf - - - - name: Log in to ghcr.io - uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Start Postgres and OpenLDAP - run: docker compose -p defguard-ldap -f docker-compose.ldap-test.yaml up -d --wait db openldap - - - name: Run LDAP integration tests - run: | - docker run --rm \ - --network defguard-ldap_default \ - -v "$PWD:/src" -w /src \ - -v "$PWD/cargo-nextest:/usr/local/cargo/bin/cargo-nextest:ro" \ - -e CARGO_TERM_COLOR=always \ - -e SQLX_OFFLINE=true \ - -e DATABASE_URL=postgres://defguard:defguard@db:5432/defguard \ - -e LDAP_URL=ldap://openldap:1389 \ - -e LDAP_BIND_USERNAME=cn=admin,dc=example,dc=org \ - -e LDAP_BIND_PASSWORD=pass123 \ - -e LDAP_USER_SEARCH_BASE=ou=users,dc=example,dc=org \ - -e LDAP_GROUP_SEARCH_BASE=ou=groups,dc=example,dc=org \ - -e LDAP_USER_CLASS=inetOrgPerson \ - -e LDAP_GROUP_CLASS=groupOfUniqueNames \ - -e LDAP_USERNAME_ATTR=cn \ - -e LDAP_GROUPNAME_ATTR=cn \ - -e LDAP_MEMBER_ATTR=memberOf \ - -e LDAP_GROUP_MEMBER_ATTR=uniqueMember \ - public.ecr.aws/docker/library/rust:1 \ - cargo nextest run --archive-file nextest-archive.tar.zst --workspace-remap . --run-ignored only -E 'package(defguard_core) and test(/^ldap::/)' - - - name: Stop compose - if: always() - run: docker compose -p defguard-ldap -f docker-compose.ldap-test.yaml down -v + # skip for defguard-demo + # test-ldap: + # needs: build + # runs-on: + # - self-hosted + # - Linux + # - X64 + + # steps: + # - name: Checkout + # uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + # with: + # submodules: recursive + # fetch-depth: 1 + + # - name: Download test archive + # uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + # with: + # name: nextest-archive + + # - name: Download cargo-nextest binary + # run: curl -LsSf https://get.nexte.st/latest/linux | tar zxf - + + # - name: Log in to ghcr.io + # uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3 + # with: + # registry: ghcr.io + # username: ${{ github.actor }} + # password: ${{ secrets.GITHUB_TOKEN }} + + # - name: Start Postgres and OpenLDAP + # run: docker compose -p defguard-ldap -f docker-compose.ldap-test.yaml up -d --wait db openldap + + # - name: Run LDAP integration tests + # run: | + # docker run --rm \ + # --network defguard-ldap_default \ + # -v "$PWD:/src" -w /src \ + # -v "$PWD/cargo-nextest:/usr/local/cargo/bin/cargo-nextest:ro" \ + # -e CARGO_TERM_COLOR=always \ + # -e SQLX_OFFLINE=true \ + # -e DATABASE_URL=postgres://defguard:defguard@db:5432/defguard \ + # -e LDAP_URL=ldap://openldap:1389 \ + # -e LDAP_BIND_USERNAME=cn=admin,dc=example,dc=org \ + # -e LDAP_BIND_PASSWORD=pass123 \ + # -e LDAP_USER_SEARCH_BASE=ou=users,dc=example,dc=org \ + # -e LDAP_GROUP_SEARCH_BASE=ou=groups,dc=example,dc=org \ + # -e LDAP_USER_CLASS=inetOrgPerson \ + # -e LDAP_GROUP_CLASS=groupOfUniqueNames \ + # -e LDAP_USERNAME_ATTR=cn \ + # -e LDAP_GROUPNAME_ATTR=cn \ + # -e LDAP_MEMBER_ATTR=memberOf \ + # -e LDAP_GROUP_MEMBER_ATTR=uniqueMember \ + # public.ecr.aws/docker/library/rust:1 \ + # cargo nextest run --archive-file nextest-archive.tar.zst --workspace-remap . --run-ignored only -E 'package(defguard_core) and test(/^ldap::/)' + + # - name: Stop compose + # if: always() + # run: docker compose -p defguard-ldap -f docker-compose.ldap-test.yaml down -v cleanup: - needs: [test, test-ldap] + needs: [test] if: needs.test.result == 'success' runs-on: ubuntu-latest permissions: diff --git a/.github/workflows/current.yml b/.github/workflows/current.yml deleted file mode 100644 index 209cdb5b84..0000000000 --- a/.github/workflows/current.yml +++ /dev/null @@ -1,51 +0,0 @@ -name: Build current image -permissions: - contents: read - id-token: write - packages: write -on: - push: - branches: - - dev - - "release/**" - - "stable/**" - paths-ignore: - - "*.md" - - "LICENSE" - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - build-current: - uses: ./.github/workflows/build-docker.yml - with: - tags: | - type=ref,event=branch - type=sha - trivy-exit-code: "0" - - trigger-e2e: - needs: build-current - uses: ./.github/workflows/e2e.yml - secrets: inherit - - trigger-dev-deploy: - needs: build-current - if: ${{ github.event_name != 'pull_request' && (github.ref_name == 'dev' || startsWith(github.ref_name, 'release/'))}} - uses: ./.github/workflows/dev-deployment.yml - secrets: inherit - - trigger-staging-deploy: - needs: build-current - if: ${{ github.event_name != 'pull_request' && startsWith(github.ref_name, 'release/') }} - uses: ./.github/workflows/staging-deployment.yml - secrets: inherit - - alert-e2e-failure: - needs: trigger-e2e - if: failure() - uses: ./.github/workflows/alert-e2e-failure.yml - secrets: - ALERT_TOKEN: ${{ secrets.ALERT_TOKEN }} diff --git a/.github/workflows/dev-deployment.yml b/.github/workflows/dev-deployment.yml deleted file mode 100644 index 6e2ee81264..0000000000 --- a/.github/workflows/dev-deployment.yml +++ /dev/null @@ -1,20 +0,0 @@ -name: Deploy to DEV environment -on: - workflow_call: - -jobs: - deploy-dev: - runs-on: [self-hosted, Linux, X64] - environment: DEV - if: ${{ github.event_name != 'pull_request' && (github.ref_name == 'dev' || startsWith(github.ref_name, 'release/'))}} - env: - KUBE_HOST: ${{ secrets.KUBE_HOST }} - KUBE_CERTIFICATE: ${{ secrets.KUBE_CERTIFICATE }} - KUBE_TOKEN: ${{ secrets.KUBE_TOKEN }} - steps: - - name: Add SHORT_SHA env variable - run: echo "SHORT_SHA=`echo ${GITHUB_SHA} | cut -c1-7`" >> $GITHUB_ENV - - name: Deploy new image version - uses: actions-hub/kubectl@2639090a038d46a3b9b98b220ae0837676ded8b7 # v1.34.3 - with: - args: --namespace defguard-dev set image deployment/defguard defguard=ghcr.io/defguard/defguard:sha-${{ env.SHORT_SHA }} diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml deleted file mode 100644 index 34425203e9..0000000000 --- a/.github/workflows/e2e.yml +++ /dev/null @@ -1,320 +0,0 @@ -name: E2E tests - -on: - workflow_call: - -permissions: - contents: read - packages: write - id-token: write - -jobs: - test: - runs-on: - - codebuild-defguard-core-runner-${{ github.run_id }}-${{ github.run_attempt }} - instance-size:medium - strategy: - fail-fast: false - matrix: - shard: [1, 2, 3, 4, 5, 6, 7, 8] - - steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 - - - name: Login to GitHub container registry - uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Export image tag - run: | - BRANCH=${GITHUB_REF#refs/heads/} - if [[ "$BRANCH" == release/* ]] || [[ "$BRANCH" == stable/* ]]; then - IMAGE_TAG=${BRANCH//\//-} - else - IMAGE_TAG=$BRANCH - fi - echo "IMAGE_TAG=$IMAGE_TAG" >> $GITHUB_ENV - echo "E2E tests will run on IMAGE_TAG=$IMAGE_TAG" - - - name: Set up Node - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 - with: - node-version-file: "./e2e/.nvmrc" - - - name: Install pnpm - id: pnpm-install - uses: pnpm/action-setup@008330803749db0355799c700092d9a85fd074e9 # v6.0.9 - with: - package_json_file: e2e/package.json - run_install: false - - - name: Get pnpm store directory - id: pnpm-cache - shell: bash - run: | - echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT - - - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 - name: Setup pnpm cache - with: - path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} - restore-keys: | - ${{ runner.os }}-pnpm-store- - - - name: Pull images - run: docker compose --file './docker-compose.e2e.yaml' pull - - - name: Install E2E dependencies - working-directory: ./e2e - run: pnpm install --frozen-lockfile - - - name: Cache Playwright browsers - id: playwright-cache - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 - with: - path: ~/.cache/ms-playwright - key: ${{ runner.os }}-playwright-${{ hashFiles('e2e/pnpm-lock.yaml') }} - restore-keys: | - ${{ runner.os }}-playwright- - - - name: Install playwright chromium - working-directory: ./e2e - run: | - if [[ "${{ steps.playwright-cache.outputs.cache-hit }}" == "true" ]]; then - # Browsers are cached; only install missing system dependencies. - npx playwright install-deps chromium - else - npx playwright install --with-deps chromium - fi - - - name: run tests - id: run-test - working-directory: ./e2e - env: - DEFGUARD_LICENSE_KEY: ${{ secrets.DEFGUARD_LICENSE_KEY }} - run: pnpm test --shard=${{ matrix.shard }}/8 - - - name: Stop compose - if: always() - run: docker compose --file './docker-compose.e2e.yaml' down - - - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - if: failure() - with: - name: playwright-report-shard-${{ matrix.shard }} - path: | - ./e2e/playwright-report - retention-days: 7 - - test-migration-wizard: - runs-on: - - codebuild-defguard-core-runner-${{ github.run_id }}-${{ github.run_attempt }} - instance-size:medium - - steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 - - - name: Login to GitHub container registry - uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Export image tag - run: | - BRANCH=${GITHUB_REF#refs/heads/} - if [[ "$BRANCH" == release/* ]] || [[ "$BRANCH" == stable/* ]]; then - IMAGE_TAG=${BRANCH//\//-} - else - IMAGE_TAG=$BRANCH - fi - echo "IMAGE_TAG=$IMAGE_TAG" >> $GITHUB_ENV - - - name: Set up Node - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 - with: - node-version-file: "./e2e/.nvmrc" - - - name: Install pnpm - uses: pnpm/action-setup@008330803749db0355799c700092d9a85fd074e9 # v6.0.9 - with: - package_json_file: e2e/package.json - run_install: false - - - name: Get pnpm store directory - id: pnpm-cache - shell: bash - run: | - echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT - - - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 - name: Setup pnpm cache - with: - path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} - restore-keys: | - ${{ runner.os }}-pnpm-store- - - - name: Pull images - run: docker compose --file './docker-compose.e2e.yaml' pull - - - name: Install E2E dependencies - working-directory: ./e2e - run: pnpm install --frozen-lockfile - - - name: Cache Playwright browsers - id: playwright-cache - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 - with: - path: ~/.cache/ms-playwright - key: ${{ runner.os }}-playwright-${{ hashFiles('e2e/pnpm-lock.yaml') }} - restore-keys: | - ${{ runner.os }}-playwright- - - - name: Install playwright chromium - working-directory: ./e2e - run: | - if [[ "${{ steps.playwright-cache.outputs.cache-hit }}" == "true" ]]; then - npx playwright install-deps chromium - else - npx playwright install --with-deps chromium - fi - - - name: Run migration wizard tests - working-directory: ./e2e - env: - DEFGUARD_LICENSE_KEY: ${{ secrets.DEFGUARD_LICENSE_KEY }} - run: pnpm playwright test --config playwright.config.migration.ts - - - name: Stop compose - if: always() - run: docker compose --file './docker-compose.e2e.yaml' down - - - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - if: failure() - with: - name: playwright-report-migration-wizard - path: | - ./e2e/playwright-report - retention-days: 7 - - test-auto-adoption-wizard: - runs-on: - - codebuild-defguard-core-runner-${{ github.run_id }}-${{ github.run_attempt }} - instance-size:medium - - steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 - - - name: Login to GitHub container registry - uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Export image tag - run: | - BRANCH=${GITHUB_REF#refs/heads/} - if [[ "$BRANCH" == release/* ]] || [[ "$BRANCH" == stable/* ]]; then - IMAGE_TAG=${BRANCH//\//-} - else - IMAGE_TAG=$BRANCH - fi - echo "IMAGE_TAG=$IMAGE_TAG" >> $GITHUB_ENV - - - name: Set up Node - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 - with: - node-version-file: "./e2e/.nvmrc" - - - name: Install pnpm - uses: pnpm/action-setup@008330803749db0355799c700092d9a85fd074e9 # v6.0.9 - with: - package_json_file: e2e/package.json - run_install: false - - - name: Get pnpm store directory - id: pnpm-cache - shell: bash - run: | - echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT - - - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 - name: Setup pnpm cache - with: - path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} - restore-keys: | - ${{ runner.os }}-pnpm-store- - - - name: Pull images - run: docker compose --file './docker-compose.e2e-auto-adoption.yaml' pull - - - name: Install E2E dependencies - working-directory: ./e2e - run: pnpm install --frozen-lockfile - - - name: Cache Playwright browsers - id: playwright-cache - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 - with: - path: ~/.cache/ms-playwright - key: ${{ runner.os }}-playwright-${{ hashFiles('e2e/pnpm-lock.yaml') }} - restore-keys: | - ${{ runner.os }}-playwright- - - - name: Install playwright chromium - working-directory: ./e2e - run: | - if [[ "${{ steps.playwright-cache.outputs.cache-hit }}" == "true" ]]; then - npx playwright install-deps chromium - else - npx playwright install --with-deps chromium - fi - - - name: Run auto-adoption wizard tests - working-directory: ./e2e - env: - DEFGUARD_LICENSE_KEY: ${{ secrets.DEFGUARD_LICENSE_KEY }} - run: pnpm playwright test --config playwright.config.auto-adoption.ts - - - name: Stop compose - if: always() - run: docker compose --file './docker-compose.e2e-auto-adoption.yaml' down - - - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - if: failure() - with: - name: playwright-report-auto-adoption-wizard - path: | - ./e2e/playwright-report - retention-days: 7 - - trigger-dev-deploy: - needs: [test, test-migration-wizard, test-auto-adoption-wizard] - if: ${{ github.event_name != 'pull_request' && github.ref_name == 'dev' && needs.test.result == 'success' && needs.test-migration-wizard.result == 'success' && needs.test-auto-adoption-wizard.result == 'success' }} - uses: ./.github/workflows/dev-deployment.yml - secrets: inherit - - trigger-staging-deploy: - needs: [test, test-migration-wizard, test-auto-adoption-wizard] - if: | - github.event_name != 'pull_request' && - startsWith(github.ref_name, 'release/') && - needs.test.result == 'success' && - needs.test-migration-wizard.result == 'success' && - needs.test-auto-adoption-wizard.result == 'success' - uses: ./.github/workflows/staging-deployment.yml - secrets: inherit diff --git a/.github/workflows/lint-e2e.yml b/.github/workflows/lint-e2e.yml deleted file mode 100644 index 16e25a6e93..0000000000 --- a/.github/workflows/lint-e2e.yml +++ /dev/null @@ -1,44 +0,0 @@ -on: - push: - branches: - - dev - - 'release/**' - - 'stable/**' - paths: - - "e2e/**" - pull_request: - branches: - - dev - - 'release/**' - - 'stable/**' - paths: - - "e2e/**" - -jobs: - lint-e2e: - runs-on: - - codebuild-defguard-core-runner-${{ github.run_id }}-${{ github.run_attempt }} - steps: - - name: Checkout - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - with: - submodules: recursive - - - name: Install NodeJS - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 - with: - node-version: 26 - - - name: Install pnpm - uses: pnpm/action-setup@008330803749db0355799c700092d9a85fd074e9 # v6.0.9 - with: - package_json_file: e2e/package.json - run_install: false - - - name: Install deps - working-directory: ./e2e - run: pnpm install --frozen-lockfile - - - name: Build and lint e2e - working-directory: e2e - run: pnpm lint diff --git a/.github/workflows/lint-web.yml b/.github/workflows/lint-web.yml index ccea87db38..d619f89bfb 100644 --- a/.github/workflows/lint-web.yml +++ b/.github/workflows/lint-web.yml @@ -19,7 +19,9 @@ on: jobs: lint-web: runs-on: - - codebuild-defguard-core-runner-${{ github.run_id }}-${{ github.run_attempt }} + - self-hosted + - Linux + - X64 steps: - name: Checkout uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 diff --git a/.github/workflows/publish-docker-latest.yml b/.github/workflows/publish-docker-latest.yml deleted file mode 100644 index 11cd0c5771..0000000000 --- a/.github/workflows/publish-docker-latest.yml +++ /dev/null @@ -1,54 +0,0 @@ -name: Publish Docker latest tag - -on: - release: - types: [published] - -jobs: - tag-docker-latest: - # Only run when the release is marked as "Latest release" in the GitHub UI - if: github.event.release.make_latest == 'true' - runs-on: [self-hosted, Linux] - - env: - GHCR_REPO: ghcr.io/defguard/defguard - - permissions: - packages: write - id-token: write # needed for Cosign keyless signing - - steps: - - name: Install Cosign - uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 - - - name: Login to GitHub container registry - uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 - - - name: Derive semver tag - run: | - # Strip the leading 'v' from the release tag name (e.g. v1.2.3 -> 1.2.3) - VERSION="${{ github.event.release.tag_name }}" - echo "VERSION=${VERSION#v}" >> $GITHUB_ENV - - - name: Tag image as latest - run: | - docker buildx imagetools create \ - --tag ${{ env.GHCR_REPO }}:latest \ - ${{ env.GHCR_REPO }}:${{ env.VERSION }} - - - name: Sign the latest tag with GitHub OIDC Token - run: cosign sign --yes ${{ env.GHCR_REPO }}:latest - - - name: Verify image signature - run: | - cosign verify ${{ env.GHCR_REPO }}:latest \ - --certificate-oidc-issuer https://token.actions.githubusercontent.com \ - --certificate-identity-regexp="https://github.com/DefGuard/defguard" \ - -o text diff --git a/.github/workflows/publish-openapi.yml b/.github/workflows/publish-openapi.yml deleted file mode 100644 index c8ddb74492..0000000000 --- a/.github/workflows/publish-openapi.yml +++ /dev/null @@ -1,58 +0,0 @@ -name: Publish OpenAPI spec to GitBook - -on: - push: - branches: - - 'release/2.1' - -permissions: - contents: read - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - publish-openapi: - runs-on: - - self-hosted - - Linux - - X64 - - env: - CARGO_TERM_COLOR: always - SQLX_OFFLINE: true - RUSTUP_TOOLCHAIN: "stable" - GITBOOK_SPEC: defguard-2-1 - GITBOOK_ORGANIZATION: Z3mGSAbEj9iLdZ7cNFlL - - steps: - - name: Checkout - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - with: - submodules: recursive - - - name: Install Rust stable - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable - with: - toolchain: stable - - - name: Generate openapi.json - run: cargo run --locked -p defguard_core --example openapi - - - name: Install NodeJS - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 - with: - node-version: 26 - - - name: Install GitBook CLI - run: npm install -g @gitbook/cli - - - name: Publish spec to GitBook - env: - GITBOOK_TOKEN: ${{ secrets.GITBOOK_TOKEN }} - run: | - gitbook openapi publish \ - --spec "$GITBOOK_SPEC" \ - --organization "$GITBOOK_ORGANIZATION" \ - openapi.json diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fae0f968c6..0cb3f16c8e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,42 +13,7 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true - - jobs: - build-docker-release: - # Ignore tags with -, like v1.0.0-alpha - # This job will build the docker container with the "latest" tag which - # is a tag used in production, thus it should only be run for full releases. - if: startsWith(github.ref, 'refs/tags/') && !contains(github.ref, '-') - name: Build Release Docker image - uses: ./.github/workflows/build-docker.yml - with: - build-version: ${{ github.ref_name }} - tags: | - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=semver,pattern={{major}} - type=sha - # Explicitly disable latest tag. It will be added otherwise. - flavor: | - latest=false - - build-docker-prerelease: - # Only build tags with -, like v1.0.0-alpha - if: startsWith(github.ref, 'refs/tags/') && contains(github.ref, '-') - name: Build Pre-release Docker image - uses: ./.github/workflows/build-docker.yml - with: - build-version: ${{ github.ref_name }} - tags: | - type=raw,value=pre-release - type=semver,pattern={{version}} - type=sha - # Explicitly disable latest tag. It will be added otherwise. - flavor: | - latest=false - create-release: name: create-release runs-on: self-hosted @@ -62,14 +27,6 @@ jobs: draft: true generate_release_notes: true - create-sbom: - needs: - - create-release - - build-docker-release - uses: ./.github/workflows/sbom.yml - with: - upload_url: ${{ needs.create-release.outputs.upload_url }} - build-binaries: needs: - create-release @@ -107,10 +64,7 @@ jobs: - name: Install pnpm uses: pnpm/action-setup@008330803749db0355799c700092d9a85fd074e9 # v6.0.9 with: - cache: true - cache_dependency_path: web/pnpm-lock.yaml package_json_file: web/package.json - run_install: false - name: Build frontend working-directory: web @@ -118,19 +72,6 @@ jobs: pnpm install --ignore-scripts --frozen-lockfile pnpm build - - name: Build source code archive - run: tar --exclude='.github' --exclude-vcs --exclude-vcs-ignores --xform='s|^\./|defguard-${{ env.VERSION }}/|' --xz -cf ${{ runner.temp }}/defguard-${{ env.VERSION }}.tar.xz . - - - name: Upload source code archive - uses: shogo82148/actions-upload-release-asset@394b3c11c3cfc038b5396ad265c074065cf875c3 # v1.10.2 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ needs.create-release.outputs.upload_url }} - asset_path: ${{ runner.temp }}/defguard-${{ env.VERSION }}.tar.xz - asset_content_type: application/x-xz - overwrite: true - - name: Install Rust stable uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable with: @@ -157,13 +98,13 @@ jobs: tar -zcf defguard-${{ env.VERSION }}-aarch64-unknown-linux-gnu.tar.gz \ defguard-${{ env.VERSION }}-aarch64-unknown-linux-gnu - - name: Build FreeBSD binary - run: | - rsync -rlptxzH -e 'ssh -l root' --del ./ freebsd:work/defguard/ - ssh root@freebsd "cd work/defguard && env DEFGUARD_BUILD_VERSION='${DEFGUARD_BUILD_VERSION}' cargo build --locked --release" - scp root@freebsd:work/defguard/target/release/defguard defguard-${{ env.VERSION }}-x86_64-unknown-freebsd - tar -zcf defguard-${{ env.VERSION }}-x86_64-unknown-freebsd.tar.gz \ - defguard-${{ env.VERSION }}-x86_64-unknown-freebsd + # - name: Build FreeBSD binary + # run: | + # rsync -rlptxzH -e 'ssh -l root' --del ./ freebsd:work/defguard/ + # ssh root@freebsd 'cd work/defguard && cargo build --locked --release' + # scp root@freebsd:work/defguard/target/release/defguard defguard-${{ env.VERSION }}-x86_64-unknown-freebsd + # tar -zcf defguard-${{ env.VERSION }}-x86_64-unknown-freebsd.tar.gz \ + # defguard-${{ env.VERSION }}-x86_64-unknown-freebsd - name: Build x86_64 DEB package uses: defGuard/fpm-action@ebb2575fbb892876fbdd326bb6d12524fbd7398c # main @@ -172,8 +113,7 @@ jobs: "defguard-${{ env.VERSION }}-x86_64-unknown-linux-gnu=/usr/bin/defguard linux/defguard.service=/usr/lib/systemd/system/defguard.service .env.example=/etc/defguard/core.conf" - fpm_opts: - "--architecture amd64 + fpm_opts: "--architecture amd64 --output-type deb --version ${{ env.VERSION }} --package defguard-${{ env.VERSION }}-x86_64-unknown-linux-gnu.deb @@ -189,8 +129,7 @@ jobs: "defguard-${{ env.VERSION }}-aarch64-unknown-linux-gnu=/usr/bin/defguard linux/defguard.service=/usr/lib/systemd/system/defguard.service .env.example=/etc/defguard/core.conf" - fpm_opts: - "--architecture arm64 + fpm_opts: "--architecture arm64 --output-type deb --version ${{ env.VERSION }} --package defguard-${{ env.VERSION }}-aarch64-unknown-linux-gnu.deb @@ -199,55 +138,51 @@ jobs: --before-remove linux/prerm --after-remove linux/postrm" - - name: Build x86_64 RPM package - uses: defGuard/fpm-action@ebb2575fbb892876fbdd326bb6d12524fbd7398c # main - with: - fpm_args: - "defguard-${{ env.VERSION }}-x86_64-unknown-linux-gnu=/usr/bin/defguard - linux/defguard.service=/usr/lib/systemd/system/defguard.service - .env.example=/etc/defguard/core.conf" - fpm_opts: - "--architecture amd64 - --output-type rpm - --version ${{ env.VERSION }} - --package defguard-${{ env.VERSION }}-x86_64-unknown-linux-gnu.rpm - --before-install linux/preinst - --after-install linux/postinst - --before-remove linux/prerm - --after-remove linux/postrm" - - - name: Build aarch64 RPM package - uses: defGuard/fpm-action@ebb2575fbb892876fbdd326bb6d12524fbd7398c # main - with: - fpm_args: - "defguard-${{ env.VERSION }}-aarch64-unknown-linux-gnu=/usr/bin/defguard - linux/defguard.service=/usr/lib/systemd/system/defguard.service - .env.example=/etc/defguard/core.conf" - fpm_opts: - "--architecture arm64 - --output-type rpm - --version ${{ env.VERSION }} - --package defguard-${{ env.VERSION }}-aarch64-unknown-linux-gnu.rpm - --before-install linux/preinst - --after-install linux/postinst - --before-remove linux/prerm - --after-remove linux/postrm" - - - name: Build FreeBSD package - uses: defGuard/fpm-action@ebb2575fbb892876fbdd326bb6d12524fbd7398c # main - with: - fpm_args: - "defguard-${{ env.VERSION }}-x86_64-unknown-freebsd=/usr/local/bin/defguard - freebsd/defguard=/usr/local/etc/rc.d/defguard - .env.example=/etc/defguard/core.conf.sample" - fpm_opts: - "--architecture amd64 - --output-type freebsd - --version ${{ env.VERSION }} - --package defguard-${{ env.VERSION }}_x86_64-unknown-freebsd.pkg - --freebsd-osversion '*' - --depends openssl - --after-install freebsd/post-install.sh" + # - name: Build x86_64 RPM package + # uses: defGuard/fpm-action@ebb2575fbb892876fbdd326bb6d12524fbd7398c # main + # with: + # fpm_args: + # "defguard-${{ env.VERSION }}-x86_64-unknown-linux-gnu=/usr/bin/defguard + # linux/defguard.service=/usr/lib/systemd/system/defguard.service + # .env.example=/etc/defguard/core.conf" + # fpm_opts: "--architecture amd64 + # --output-type rpm + # --version ${{ env.VERSION }} + # --package defguard-${{ env.VERSION }}-x86_64-unknown-linux-gnu.rpm + # --before-install linux/preinst + # --after-install linux/postinst + # --before-remove linux/prerm + # --after-remove linux/postrm" + + # - name: Build aarch64 RPM package + # uses: defGuard/fpm-action@ebb2575fbb892876fbdd326bb6d12524fbd7398c # main + # with: + # fpm_args: + # "defguard-${{ env.VERSION }}-aarch64-unknown-linux-gnu=/usr/bin/defguard + # linux/defguard.service=/usr/lib/systemd/system/defguard.service + # .env.example=/etc/defguard/core.conf" + # fpm_opts: "--architecture arm64 + # --output-type rpm + # --version ${{ env.VERSION }} + # --package defguard-${{ env.VERSION }}-aarch64-unknown-linux-gnu.rpm + # --before-install linux/preinst + # --after-install linux/postinst + # --before-remove linux/prerm + # --after-remove linux/postrm" + + # - name: Build FreeBSD package + # uses: defGuard/fpm-action@ebb2575fbb892876fbdd326bb6d12524fbd7398c # main + # with: + # fpm_args: + # "defguard-${{ env.VERSION }}-x86_64-unknown-freebsd=/usr/local/bin/defguard + # freebsd/defguard=/usr/local/etc/rc.d/defguard + # .env.example=/etc/defguard/core.conf" + # fpm_opts: "--architecture amd64 + # --output-type freebsd + # --version ${{ env.VERSION }} + # --package defguard-${{ env.VERSION }}_x86_64-unknown-freebsd.pkg + # --freebsd-osversion '*' + # --depends openssl" - name: Upload Linux x86_64 archive uses: shogo82148/actions-upload-release-asset@394b3c11c3cfc038b5396ad265c074065cf875c3 # v1.10.2 @@ -269,15 +204,15 @@ jobs: asset_content_type: application/gzip overwrite: true - - name: Upload FreeBSD x86_64 archive - uses: shogo82148/actions-upload-release-asset@394b3c11c3cfc038b5396ad265c074065cf875c3 # v1.10.2 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ needs.create-release.outputs.upload_url }} - asset_path: defguard-${{ env.VERSION }}-x86_64-unknown-freebsd.tar.gz - asset_content_type: application/gzip - overwrite: true + # - name: Upload FreeBSD x86_64 archive + # uses: shogo82148/actions-upload-release-asset@ee2ae851dc5d938b90075b3ef12c540abfd1ee72 # v1 + # env: + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # with: + # upload_url: ${{ needs.create-release.outputs.upload_url }} + # asset_path: defguard-${{ env.VERSION }}-x86_64-unknown-freebsd.tar.gz + # asset_content_type: application/gzip + # overwrite: true - name: Upload Linux x86_64 DEB uses: shogo82148/actions-upload-release-asset@394b3c11c3cfc038b5396ad265c074065cf875c3 # v1.10.2 @@ -299,35 +234,35 @@ jobs: asset_content_type: application/gzip overwrite: true - - name: Upload Linux x86_64 RPM - uses: shogo82148/actions-upload-release-asset@394b3c11c3cfc038b5396ad265c074065cf875c3 # v1.10.2 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ needs.create-release.outputs.upload_url }} - asset_path: defguard-${{ env.VERSION }}-x86_64-unknown-linux-gnu.rpm - asset_content_type: application/gzip - overwrite: true - - - name: Upload Linux aarch64 RPM - uses: shogo82148/actions-upload-release-asset@394b3c11c3cfc038b5396ad265c074065cf875c3 # v1.10.2 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ needs.create-release.outputs.upload_url }} - asset_path: defguard-${{ env.VERSION }}-aarch64-unknown-linux-gnu.rpm - asset_content_type: application/gzip - overwrite: true - - - name: Upload FreeBSD package - uses: shogo82148/actions-upload-release-asset@394b3c11c3cfc038b5396ad265c074065cf875c3 # v1.10.2 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ needs.create-release.outputs.upload_url }} - asset_path: defguard-${{ env.VERSION }}_x86_64-unknown-freebsd.pkg - asset_content_type: application/x-pkg - overwrite: true + # - name: Upload Linux x86_64 RPM + # uses: shogo82148/actions-upload-release-asset@ee2ae851dc5d938b90075b3ef12c540abfd1ee72 # v1 + # env: + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # with: + # upload_url: ${{ needs.create-release.outputs.upload_url }} + # asset_path: defguard-${{ env.VERSION }}-x86_64-unknown-linux-gnu.rpm + # asset_content_type: application/gzip + # overwrite: true + + # - name: Upload Linux aarch64 RPM + # uses: shogo82148/actions-upload-release-asset@ee2ae851dc5d938b90075b3ef12c540abfd1ee72 # v1 + # env: + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # with: + # upload_url: ${{ needs.create-release.outputs.upload_url }} + # asset_path: defguard-${{ env.VERSION }}-aarch64-unknown-linux-gnu.rpm + # asset_content_type: application/gzip + # overwrite: true + + # - name: Upload FreeBSD package + # uses: shogo82148/actions-upload-release-asset@ee2ae851dc5d938b90075b3ef12c540abfd1ee72 # v1 + # env: + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # with: + # upload_url: ${{ needs.create-release.outputs.upload_url }} + # asset_path: defguard-${{ env.VERSION }}_x86_64-unknown-freebsd.pkg + # asset_content_type: application/x-pkg + # overwrite: true ubuntu-22-04-build: needs: @@ -431,3 +366,68 @@ jobs: asset_path: defguard-${{ env.VERSION }}-${{ matrix.deb_arch }}_ubuntu-22-04-lts.deb asset_content_type: application/gzip overwrite: true + + build-generator-binaries: + needs: + - create-release + runs-on: + - self-hosted + - Linux + - X64 + env: + SQLX_OFFLINE: "1" + RUSTUP_TOOLCHAIN: "stable" + SCCACHE_GHA_ENABLED: "true" + RUSTC_WRAPPER: "sccache" + steps: + - name: Write release version + run: | + VERSION=${GITHUB_REF_NAME#v} + echo Version: $VERSION + echo "VERSION=$VERSION" >> $GITHUB_ENV + + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + submodules: recursive + + - name: Install Rust stable + uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable + with: + targets: "aarch64-unknown-linux-gnu" + + - name: Run sccache-cache + uses: mozilla-actions/sccache-action@7d986dd989559c6ecdb630a3fd2557667be217ad # v0.0.9 + + - name: Build Linux x86_64 binary + run: | + cargo build --locked --release -p defguard_generator --target x86_64-unknown-linux-gnu + mv target/x86_64-unknown-linux-gnu/release/defguard_generator defguard_generator-${{ env.VERSION }}-x86_64-unknown-linux-gnu + + - name: Build Linux aarch64 binary + env: + CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc + PKG_CONFIG_SYSROOT_DIR: /usr/lib/aarch64-linux-gnu + run: | + cargo build --locked --release -p defguard_generator --target aarch64-unknown-linux-gnu + mv target/aarch64-unknown-linux-gnu/release/defguard_generator defguard_generator-${{ env.VERSION }}-aarch64-unknown-linux-gnu + + - name: Upload Linux x86_64 binary + uses: shogo82148/actions-upload-release-asset@ee2ae851dc5d938b90075b3ef12c540abfd1ee72 # v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ needs.create-release.outputs.upload_url }} + asset_path: defguard_generator-${{ env.VERSION }}-x86_64-unknown-linux-gnu + asset_content_type: application/octet-stream + overwrite: true + + - name: Upload Linux aarch64 binary + uses: shogo82148/actions-upload-release-asset@ee2ae851dc5d938b90075b3ef12c540abfd1ee72 # v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ needs.create-release.outputs.upload_url }} + asset_path: defguard_generator-${{ env.VERSION }}-aarch64-unknown-linux-gnu + asset_content_type: application/octet-stream + overwrite: true diff --git a/.github/workflows/sbom-regenerate.yml b/.github/workflows/sbom-regenerate.yml deleted file mode 100644 index 9675a6ec69..0000000000 --- a/.github/workflows/sbom-regenerate.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: Periodic SBOM Regeneration -permissions: - contents: write - -on: - schedule: - - cron: '30 2 * * *' # 2:30 AM UTC - -jobs: - list-releases: - name: List releases - runs-on: ubuntu-latest - outputs: - releases: ${{ steps.get-releases.outputs.releases }} - steps: - - name: Get list of releases - id: get-releases - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - RELEASES_JSON=$(gh api repos/${{ github.repository }}/releases \ - --jq '[.[] - | select(.draft == false and (.tag_name | test("^v[0-9]+\\.[0-9]+\\.[0-9]+$"))) - | {tagName: .tag_name, uploadUrl: .upload_url}][:1]') - echo "releases=$RELEASES_JSON" >> $GITHUB_OUTPUT - regenerate-for-release: - name: Regenerate SBOM for release - needs: list-releases - # Don't run if no releases were found. - if: needs.list-releases.outputs.releases != '[]' - strategy: - fail-fast: false - matrix: - release: ${{ fromJson(needs.list-releases.outputs.releases) }} - uses: ./.github/workflows/sbom.yml - with: - upload_url: ${{ matrix.release.uploadUrl }} - tag: ${{ matrix.release.tagName }} - secrets: inherit diff --git a/.github/workflows/sbom.yml b/.github/workflows/sbom.yml deleted file mode 100644 index 7dacc20280..0000000000 --- a/.github/workflows/sbom.yml +++ /dev/null @@ -1,99 +0,0 @@ -name: Create SBOM files - -on: - workflow_call: - inputs: - upload_url: - description: "Release assets upload URL" - required: true - type: string - tag: - description: "The git tag to generate SBOM for - used in scheduled runs" - required: false - type: string - -jobs: - create-sbom: - permissions: - contents: write - runs-on: [self-hosted, Linux, X64] - - steps: - - name: Determine release tag and version - id: vars - # Uses inputs.tag for scheduled runs, otherwise github.ref_name. - run: | - TAG_NAME=${{ inputs.tag || github.ref_name }} - VERSION=${TAG_NAME#v} - echo "TAG_NAME=$TAG_NAME" >> $GITHUB_OUTPUT - echo "VERSION=$VERSION" >> $GITHUB_OUTPUT - - - name: Checkout - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - with: - ref: ${{ steps.vars.outputs.TAG_NAME }} - submodules: recursive - - - name: Create SBOM with Trivy - uses: aquasecurity/trivy-action@a9c7b0f06e461e9d4b4d1711f154ee024b8d7ab8 # v0.36.0 - env: - TRIVY_SHOW_SUPPRESSED: 1 - TRIVY_IGNOREFILE: "./.trivyignore.yaml" - with: - scan-type: 'fs' - format: 'spdx-json' - output: "defguard-${{ steps.vars.outputs.VERSION }}.sbom.json" - scan-ref: '.' - severity: "CRITICAL,HIGH,MEDIUM,LOW" - scanners: "vuln" - skip-dirs: "e2e" - - - name: Create Docker image SBOM with Trivy - uses: aquasecurity/trivy-action@a9c7b0f06e461e9d4b4d1711f154ee024b8d7ab8 # v0.36.0 - env: - TRIVY_SHOW_SUPPRESSED: 1 - TRIVY_IGNOREFILE: "./.trivyignore.yaml" - with: - image-ref: "ghcr.io/defguard/defguard:${{ steps.vars.outputs.VERSION }}" - scan-type: 'image' - format: 'spdx-json' - output: "defguard-${{ steps.vars.outputs.VERSION }}-docker.sbom.json" - severity: "CRITICAL,HIGH,MEDIUM,LOW" - scanners: "vuln" - - - name: Create security advisory file with Trivy - uses: aquasecurity/trivy-action@a9c7b0f06e461e9d4b4d1711f154ee024b8d7ab8 # v0.36.0 - env: - TRIVY_SHOW_SUPPRESSED: 1 - TRIVY_IGNOREFILE: "./.trivyignore.yaml" - with: - scan-type: 'fs' - format: 'json' - output: "defguard-${{ steps.vars.outputs.VERSION }}.advisories.json" - scan-ref: '.' - severity: "CRITICAL,HIGH,MEDIUM,LOW" - scanners: "vuln" - skip-dirs: "e2e" - - - name: Create docker image security advisory file with Trivy - uses: aquasecurity/trivy-action@a9c7b0f06e461e9d4b4d1711f154ee024b8d7ab8 # v0.36.0 - env: - TRIVY_SHOW_SUPPRESSED: 1 - TRIVY_IGNOREFILE: "./.trivyignore.yaml" - with: - image-ref: "ghcr.io/defguard/defguard:${{ steps.vars.outputs.VERSION }}" - scan-type: 'image' - format: 'json' - output: "defguard-${{ steps.vars.outputs.VERSION }}-docker.advisories.json" - severity: "CRITICAL,HIGH,MEDIUM,LOW" - scanners: "vuln" - - - name: Upload SBOMs and advisories - uses: shogo82148/actions-upload-release-asset@394b3c11c3cfc038b5396ad265c074065cf875c3 # v1.10.2 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ inputs.upload_url }} - asset_path: "defguard-*.json" - asset_content_type: application/json - overwrite: true diff --git a/.github/workflows/staging-deployment.yml b/.github/workflows/staging-deployment.yml deleted file mode 100644 index fbc67eb449..0000000000 --- a/.github/workflows/staging-deployment.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: Deploy to release staging environment -permissions: - contents: read -on: - workflow_call: - -jobs: - deploy-staging: - runs-on: [self-hosted, Linux, X64] - environment: STAGING - if: ${{ github.event_name != 'pull_request' && startsWith(github.ref_name, 'release/') }} - env: - KUBE_HOST: ${{ secrets.KUBE_HOST }} - KUBE_CERTIFICATE: ${{ secrets.KUBE_CERTIFICATE }} - KUBE_TOKEN: ${{ secrets.KUBE_TOKEN }} - steps: - - name: Add SHORT_SHA env variable - run: echo "SHORT_SHA=`echo ${GITHUB_SHA} | cut -c1-7`" >> $GITHUB_ENV - - name: Deploy new image version - uses: actions-hub/kubectl@2639090a038d46a3b9b98b220ae0837676ded8b7 # v1.34.3 - with: - args: --namespace defguard-staging set image deployment/defguard defguard=ghcr.io/defguard/defguard:sha-${{ env.SHORT_SHA }} diff --git a/.github/workflows/test-apt-repo.yml b/.github/workflows/test-apt-repo.yml deleted file mode 100644 index ccac6be803..0000000000 --- a/.github/workflows/test-apt-repo.yml +++ /dev/null @@ -1,112 +0,0 @@ -name: Test APT repository - -"on": - schedule: - - cron: "0 */6 * * *" - workflow_dispatch: - workflow_run: - workflows: ["Update repositories with packages"] - types: [completed] - -jobs: - test-apt-install: - name: "${{ matrix.package }} / ${{ matrix.component }}" - runs-on: - - codebuild-defguard-core-runner-${{ github.run_id }}-${{ github.run_attempt }} - - instance-size:small - - container: public.ecr.aws/docker/library/debian:trixie-slim - - strategy: - fail-fast: false - matrix: - package: [defguard, defguard-proxy, defguard-gateway] - component: [release, pre-release, release-2.0, pre-release-2.0] - include: - - package: defguard - github_repo: DefGuard/defguard - - package: defguard-proxy - github_repo: DefGuard/proxy - - package: defguard-gateway - github_repo: DefGuard/gateway - - steps: - - name: Install prerequisites - run: apt-get update -y && apt-get install -y ca-certificates curl jq libmnl0 libnftnl11 - - - name: Add Defguard GPG key - run: | - install -m 0755 -d /etc/apt/keyrings - curl -fsSL https://apt.defguard.net/defguard.asc -o /etc/apt/keyrings/defguard.asc - chmod a+r /etc/apt/keyrings/defguard.asc - - - name: Add Defguard APT repository - run: | - echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/defguard.asc] https://apt.defguard.net/ trixie ${{ matrix.component }}" \ - > /etc/apt/sources.list.d/defguard.list - - - name: Update APT cache - run: apt-get update -y - - - name: Check package availability in component - run: | - CANDIDATE=$(apt-cache policy ${{ matrix.package }} | awk '/Candidate:/ {print $2}') - if [ -z "$CANDIDATE" ] || [ "$CANDIDATE" = "(none)" ]; then - echo "::notice::${{ matrix.package }} not available in component ${{ matrix.component }}, skipping" - echo "SKIP=true" >> $GITHUB_ENV - else - echo "Candidate version: $CANDIDATE" - echo "SKIP=false" >> $GITHUB_ENV - fi - - - name: Get expected version from GitHub - if: env.SKIP != 'true' - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - case "${{ matrix.component }}" in - release-2.0) PRERELEASE=false; MAJOR=v2. ;; - pre-release-2.0) PRERELEASE=true; MAJOR=v2. ;; - release) PRERELEASE=false; MAJOR=v1. ;; - pre-release) PRERELEASE=true; MAJOR=v1. ;; - esac - VERSION=$(curl -sf \ - -H "Authorization: Bearer $GH_TOKEN" \ - https://api.github.com/repos/${{ matrix.github_repo }}/releases \ - | jq -r --argjson pre "$PRERELEASE" --arg major "$MAJOR" \ - '[.[] | select(.draft == false and .prerelease == $pre and (.tag_name | startswith($major)))][0].tag_name // empty') - if [ -z "$VERSION" ]; then - echo "::notice::no $MAJOR release (prerelease=$PRERELEASE) of ${{ matrix.package }} on GitHub, skipping" - echo "SKIP=true" >> $GITHUB_ENV - exit 0 - fi - VERSION="${VERSION#v}" - - # legacy pre-release still holds 2.0 betas published before the - # component split; accept them instead of expecting the latest v1.x - CANDIDATE=$(apt-cache policy ${{ matrix.package }} | awk '/Candidate:/ {print $2}') - if [ "${{ matrix.component }}" = "pre-release" ] && [ "${CANDIDATE%%.*}" != "1" ]; then - echo "::notice::candidate $CANDIDATE is from before the component split, skipping version comparison" - VERSION="" - fi - - echo "Expected version: $VERSION" - echo "EXPECTED_VERSION=$VERSION" >> $GITHUB_ENV - - - name: Install ${{ matrix.package }} - if: env.SKIP != 'true' - run: apt-get install -y ${{ matrix.package }} - - - name: Verify ${{ matrix.package }} version - if: env.SKIP != 'true' - run: | - INSTALLED=$(dpkg -s ${{ matrix.package }} | grep '^Version:' | awk '{print $2}') - echo "Installed version: $INSTALLED" - if [ -n "$EXPECTED_VERSION" ]; then - echo "Expected version: $EXPECTED_VERSION" - if [ "$INSTALLED" != "$EXPECTED_VERSION" ]; then - echo "Version mismatch!" - exit 1 - fi - fi - ${{ matrix.package }} -V diff --git a/.github/workflows/test-web.yml b/.github/workflows/test-web.yml index e459536247..20a3ada86b 100644 --- a/.github/workflows/test-web.yml +++ b/.github/workflows/test-web.yml @@ -15,7 +15,9 @@ permissions: jobs: test-web: runs-on: - - codebuild-defguard-core-runner-${{ github.run_id }}-${{ github.run_attempt }} + - self-hosted + - Linux + - X64 steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: diff --git a/.github/workflows/update-repositories.yml b/.github/workflows/update-repositories.yml deleted file mode 100644 index 7fa6af2e1c..0000000000 --- a/.github/workflows/update-repositories.yml +++ /dev/null @@ -1,149 +0,0 @@ -name: Update repositories with packages - -on: - release: - types: [published] - -permissions: - contents: read - -jobs: - update-apt: - runs-on: - - self-hosted - - Linux - - X64 - steps: - - name: Checkout - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - - - name: Install gh cli - run: | - sudo apt-get install -y gh - - - name: Download .deb assets from release - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - mkdir debs - gh release download "${{ github.event.release.tag_name }}" \ - --pattern "*.deb" \ - --dir debs - - - name: Install ruby with deb-s3 - run: | - sudo apt-get install -y ruby - gem install deb-s3 - echo "$(ruby -r rubygems -e 'puts Gem.user_dir')/bin" >> $GITHUB_PATH - - - name: Upload DEB to APT repository - run: | - if [[ "${{ github.event.release.prerelease }}" == "true" ]]; then - component="pre-release-2.0" - else - component="release-2.0" - fi - - for deb_file in debs/*.deb; do - if [[ "$deb_file" == *"ubuntu-22-04-lts"* ]]; then - codename="bookworm" - else - codename="trixie" - fi - - echo "Uploading $deb_file to $codename" - deb-s3 upload -p -l \ - --bucket=apt.defguard.net \ - --access-key-id=${{ secrets.AWS_ACCESS_KEY_APT }} \ - --secret-access-key=${{ secrets.AWS_SECRET_KEY_APT }} \ - --s3-region=eu-north-1 \ - --no-fail-if-exists \ - --codename="$codename" \ - --component="$component" \ - "$deb_file" - done - - apt-sign: - needs: - - update-apt - runs-on: - - self-hosted - - Linux - - X64 - steps: - - name: Sign APT repository - run: | - export AWS_ACCESS_KEY_ID=${{ secrets.AWS_ACCESS_KEY_APT }} - export AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_SECRET_KEY_APT }} - export AWS_REGION=eu-north-1 - sudo apt update -y - sudo apt install -y awscli curl jq - - for DIST in trixie bookworm; do - aws s3 cp s3://apt.defguard.net/dists/${DIST}/Release . - - curl -X POST "${{ secrets.DEFGUARD_SIGNING_URL }}?signature_type=both" \ - -H "Authorization: Bearer ${{ secrets.DEFGUARD_SIGNING_API_KEY }}" \ - -F "file=@Release" \ - -o response.json - - cat response.json | jq -r '.files["Release.gpg"].content' | base64 --decode > Release.gpg - cat response.json | jq -r '.files.Release.content' | base64 --decode > InRelease - - aws s3 cp Release.gpg s3://apt.defguard.net/dists/${DIST}/ --acl public-read - aws s3 cp InRelease s3://apt.defguard.net/dists/${DIST}/ --acl public-read - - done - (aws s3 ls s3://apt.defguard.net/dists/ --recursive; aws s3 ls s3://apt.defguard.net/pool/ --recursive) | awk '{print ""$4"
"}' > index.html - aws s3 cp index.html s3://apt.defguard.net/ --acl public-read - - verify-apt-repo: - needs: - - apt-sign - runs-on: - - self-hosted - - Linux - - X64 - steps: - - name: Verify published repository signatures and metadata - run: | - set -euo pipefail - sudo apt update -y - sudo apt install -y curl gpg - - WORKDIR=$(mktemp -d) - trap 'rm -rf "$WORKDIR"' EXIT - cd "$WORKDIR" - - curl -fsSL https://apt.defguard.net/defguard.asc | gpg --dearmor -o keyring.gpg - - for DIST in trixie bookworm; do - echo "=== Verifying $DIST ===" - curl -fsSL "https://apt.defguard.net/dists/${DIST}/Release" -o Release - curl -fsSL "https://apt.defguard.net/dists/${DIST}/Release.gpg" -o Release.gpg - curl -fsSL "https://apt.defguard.net/dists/${DIST}/InRelease" -o InRelease - - gpgv --keyring "$WORKDIR/keyring.gpg" Release.gpg Release - gpgv --keyring "$WORKDIR/keyring.gpg" InRelease - - for COMPONENT in $(awk '/^Components:/ {for (i=2; i<=NF; i++) print $i}' Release); do - PACKAGES_PATH="${COMPONENT}/binary-amd64/Packages" - EXPECTED_SHA=$(awk -v p="$PACKAGES_PATH" '/^SHA256:/{s=1; next} /^[A-Za-z]/{s=0} s && $3 == p {print $1; exit}' Release) - # InRelease must describe the same metadata as the detached-signed - # Release, otherwise apt clients see a signature/content mismatch - INRELEASE_SHA=$(awk -v p="$PACKAGES_PATH" '/^SHA256:/{s=1; next} /^[A-Za-z-]/{s=0} s && $3 == p {print $1; exit}' InRelease) - if [ -z "$EXPECTED_SHA" ] || [ "$EXPECTED_SHA" != "$INRELEASE_SHA" ]; then - echo "SHA256 entry for $PACKAGES_PATH missing or differs between Release and InRelease in $DIST" - exit 1 - fi - curl -fsSL "https://apt.defguard.net/dists/${DIST}/${PACKAGES_PATH}" -o Packages - ACTUAL_SHA=$(sha256sum Packages | awk '{print $1}') - if [ "$ACTUAL_SHA" != "$EXPECTED_SHA" ]; then - echo "Checksum mismatch for $DIST/$PACKAGES_PATH" - echo "expected: $EXPECTED_SHA" - echo "actual: $ACTUAL_SHA" - exit 1 - fi - echo "$DIST/$PACKAGES_PATH OK" - done - done diff --git a/.github/workflows/upstream-sync.yml b/.github/workflows/upstream-sync.yml new file mode 100644 index 0000000000..86c6581f2d --- /dev/null +++ b/.github/workflows/upstream-sync.yml @@ -0,0 +1,48 @@ +name: Weekly upstream sync + +on: + schedule: + - cron: "0 8 * * 1" + workflow_dispatch: + +permissions: + contents: write + pull-requests: write + +jobs: + sync: + runs-on: ubuntu-latest + env: + SYNC_BASE_BRANCH: release/2.1 + SYNC_UPSTREAM_BRANCH: release/2.1 + SYNC_PR_BRANCH: sync/upstream-release-2.1 + steps: + - name: Expose branch variables + id: branches + run: | + echo "base=$SYNC_BASE_BRANCH" >> "$GITHUB_OUTPUT" + echo "upstream=$SYNC_UPSTREAM_BRANCH" >> "$GITHUB_OUTPUT" + echo "pr_branch=$SYNC_PR_BRANCH" >> "$GITHUB_OUTPUT" + + - name: Checkout fork + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + ref: ${{ steps.branches.outputs.base }} + fetch-depth: 0 + + - name: Pull in upstream ${{ steps.branches.outputs.upstream }} + run: | + git remote add upstream https://github.com/defguard/defguard.git + git fetch upstream "$SYNC_UPSTREAM_BRANCH" + git reset --hard "upstream/$SYNC_UPSTREAM_BRANCH" + rm -rf .github/workflows + git checkout "origin/$SYNC_BASE_BRANCH" -- .github/workflows + + - name: Create or update pull request + uses: peter-evans/create-pull-request@v8 + with: + token: ${{ secrets.SYNC_PAT }} + branch: ${{ steps.branches.outputs.pr_branch }} + base: ${{ steps.branches.outputs.base }} + title: "Weekly upstream sync: ${{ steps.branches.outputs.upstream }}" + body: "Automated weekly sync from upstream defguard/defguard ${{ steps.branches.outputs.upstream }} (workflows excluded). Review and merge manually."