Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
877e8dd
feat: conditional fips mode
cardoso Mar 4, 2026
4bc2d5a
ci: add fips lane
cardoso Mar 5, 2026
c53c5d4
ci: build fips image in advance
cardoso Mar 5, 2026
3c41c2a
ci: allow selecting test lanes to run
cardoso Mar 5, 2026
f505b62
fix: allow sha-1 for ws handshake
cardoso Mar 5, 2026
62b2cfa
Revert "ci: allow selecting test lanes to run"
cardoso Mar 5, 2026
406705f
chore: streamline fips env vars
cardoso Mar 5, 2026
cb1aef2
Revert "fix: allow sha-1 for ws handshake"
cardoso Mar 6, 2026
b7baa52
fix(fips): use js implementation for ws handshake
cardoso Mar 6, 2026
5e4cf35
refactor: improve fips init script
cardoso Mar 9, 2026
d0b0e2d
ci: guard against missing creds
cardoso Mar 9, 2026
2dc8517
feat(presence-service): fips mode
cardoso Mar 9, 2026
1bbd531
ci: reduce duplication of fips checks
cardoso Mar 9, 2026
5a42430
ci: fips docker compose overrides
cardoso Mar 9, 2026
aca2e1f
ci: specify targets
cardoso Mar 9, 2026
e448a93
ci: enhance naming and streamline service matrix
cardoso Mar 9, 2026
c450817
fix: set fips mode on start
cardoso Mar 9, 2026
54c4e7f
fix: update artifact pattern
cardoso Mar 9, 2026
12ec807
ci: matrix generation job
cardoso Mar 9, 2026
3178072
feat(authorization-service): fips
cardoso Mar 10, 2026
6764e08
fix(ddp-streamer): remove flaky check
cardoso Mar 10, 2026
2650858
feat(queue-worker): fips
cardoso Mar 10, 2026
d8dc0bf
feat(account-service): fips
cardoso Mar 10, 2026
d75e00a
fix(ci): compose build fallback creds
cardoso Mar 10, 2026
652b033
fix(ci): retry docker buildx with backoff
cardoso Mar 10, 2026
a3b305b
feat(ci): fips image pull step service readiness checks
cardoso Mar 10, 2026
b391466
feat(omnichannel-transcript): fips
cardoso Mar 11, 2026
050cc12
ci: improve readiness checks
cardoso Mar 11, 2026
8a31b91
fix(ci): update readiness check for omnichannel-transcript service
cardoso Mar 11, 2026
ae161b8
fix(ci): update image pull step to support both EE and FIPS releases
cardoso Mar 11, 2026
5f51175
ci: make readiness check more robust
cardoso Mar 11, 2026
ba886ea
ci: do not skip rocketchat image in fork runs
cardoso Mar 11, 2026
e6e3942
fix(fips): enhance SHA-1 handling in FIPS mode for WebSocket handshake
cardoso Mar 11, 2026
af0f8a1
fix(fips): enhance SHA-1 handling in FIPS mode with error handling fo…
cardoso Mar 11, 2026
12bfc5a
fix(ci): remove exclusion of rocketchat-cov service from promotion pr…
cardoso Mar 11, 2026
7ce95a2
fix(fips): improve SHA-1 handling in FIPS mode by storing updates for…
cardoso Mar 11, 2026
c6ebacf
chore: consistent fips checks
cardoso Mar 11, 2026
8855f9a
fix(fips): add WebSocket handshake validation for SHA-1 input in FIPS…
cardoso Mar 12, 2026
c396eeb
fix(fips): prevent multiple calls to digest in SHA-1 mock implementat…
cardoso Mar 12, 2026
a97d28a
fix(fips): add TEMP_DOCKERHUB_FIPS_USER and TEMP_DOCKERHUB_FIPS_PASS …
cardoso Mar 12, 2026
73b21e2
fix(ci): improve service wait logic by checking for running container…
cardoso Mar 12, 2026
36a257c
fix(ci): semgrep findings
cardoso Mar 13, 2026
4264535
chore: reduce logs
cardoso Mar 16, 2026
2c0be06
chore: use --force-fips
cardoso Mar 16, 2026
62d9275
chore: reduce diff
cardoso Mar 17, 2026
00810be
feat(ddp-streamer): use alpine for fips
cardoso Mar 27, 2026
60b6223
feat(omnichannel-transcript): use alpine for fips
cardoso Mar 27, 2026
8266648
feat(account-service): use alpine for fips
cardoso Mar 27, 2026
2a11fe0
feat(presence-service): use alpine for fips
cardoso Mar 27, 2026
69d4717
feat(queue-worker): use alpine for fips
cardoso Mar 27, 2026
f0788be
fix(ci): skip publish of rocketchat-cov
cardoso Mar 30, 2026
7e7b0b4
ci: fix retry loop
cardoso Mar 30, 2026
46c3db0
chore: normalize dockerfiles
cardoso May 5, 2026
599a142
ci(fips): build and publish rocketchat-fips image with temporary prod…
cardoso May 7, 2026
e0798a4
ci: hash pin docker/login-action
cardoso May 11, 2026
bfe4678
fix(fips): remove temporary DockerHub org
cardoso May 11, 2026
4100536
feat: use fips base image for rocketchat service
cardoso May 12, 2026
d9eb6e5
feat: force fips in monolith
cardoso May 13, 2026
e2112a5
feat: show fips mode in logs
cardoso May 14, 2026
6a881bc
feat: show fips mode in statistics
cardoso May 14, 2026
3bd03e1
chore(deps): update fips base images for node 22.22.3
cardoso May 19, 2026
abede3b
fix!(fips): use sha256 instead of md5 for 2fa fingerprint
cardoso May 21, 2026
baa3a31
fix(fips): use sha256 for meteor method rate limiting
cardoso May 21, 2026
b96e696
fix(fips): install deno in monolith image
cardoso May 22, 2026
2bf121e
fix(federation-matrix): change from md5 to sha256 for ETag for FIPS c…
cardoso May 22, 2026
3869643
chore(fips): reduce ci diff
cardoso May 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 31 additions & 5 deletions .github/actions/build-docker/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ inputs:
CR_PAT:
required: true
description: 'GitHub Container Registry Personal Access Token'
DOCKER_USER:
required: false
description: 'DockerHub username (required for FIPS builds to pull private base image)'
DOCKER_PASS:
required: false
description: 'DockerHub password (required for FIPS builds to pull private base image)'
deno-version:
required: true
description: 'Deno version'
Expand All @@ -28,7 +34,7 @@ inputs:
default: 'true'
type:
required: false
description: 'production or coverage'
description: 'production, coverage, or fips'
default: 'coverage'

runs:
Expand All @@ -43,11 +49,21 @@ runs:
username: ${{ inputs.CR_USER }}
password: ${{ inputs.CR_PAT }}

- name: Login to DockerHub
# FIPS base image (rocketchat/dhi-node) lives in a private DockerHub repo and requires auth to pull.
if: inputs.type == 'fips' && github.actor != 'dependabot[bot]' && (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop')
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
with:
username: ${{ inputs.DOCKER_USER }}
password: ${{ inputs.DOCKER_PASS }}

- name: Restore meteor build
if: inputs.service == 'rocketchat'
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
name: build-${{ inputs.type }}
# Temporary: rocketchat fips reuses existing Meteor artifacts until build-fips exists.
# PR/merge queue runs only produce build-coverage, while release/develop produce build-production.
name: build-${{ inputs.type == 'fips' && ((github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production') || inputs.type }}
path: /tmp/build

- name: Unpack meteor build
Expand Down Expand Up @@ -85,6 +101,10 @@ runs:
GITHUB_REF: ${{ github.ref }}
run: |
set -o xtrace
compose_fips_override=''
if [[ "$INPUT_TYPE" == 'fips' ]]; then
compose_fips_override='-f docker-compose-ci.fips.yml'
fi

# Removes unnecessary swc cores and sharp binaries to reduce image size
swc_arch='x64'
Expand All @@ -109,10 +129,10 @@ runs:
fi

# Get image name from docker-compose-ci.yml since rocketchat image is different from service name (rocket.chat)
IMAGE=$(docker compose -f docker-compose-ci.yml config --format json 2>/dev/null | jq -r --arg s "$INPUT_SERVICE" '.services[$s].image')
IMAGE=$(docker compose -f docker-compose-ci.yml $compose_fips_override config --format json 2>/dev/null | jq -r --arg s "$INPUT_SERVICE" '.services[$s].image')

docker buildx bake \
-f docker-compose-ci.yml \
-f docker-compose-ci.yml $compose_fips_override \
${LOAD_OR_PUSH} \
--allow=fs.read=/tmp/build \
--set "*.tags+=${IMAGE}-gha-run-${GITHUB_RUN_ID}" \
Expand All @@ -133,6 +153,8 @@ runs:
SERVICE_SUFFIX=''
if [[ "$INPUT_SERVICE" == 'rocketchat' && "$INPUT_TYPE" == 'coverage' ]] && [[ "$GITHUB_EVENT_NAME" == 'release' || "$GITHUB_REF" == 'refs/heads/develop' ]]; then
SERVICE_SUFFIX='-cov'
elif [[ "$INPUT_TYPE" == 'fips' ]]; then
SERVICE_SUFFIX='-fips'
fi

mkdir -p "/tmp/manifests/${INPUT_SERVICE}${SERVICE_SUFFIX}/${INPUT_ARCH}"
Expand Down Expand Up @@ -160,9 +182,13 @@ runs:
TYPE: ${{ inputs.type }}
run: |
set -o xtrace
compose_fips_override=''
if [[ "$TYPE" == 'fips' ]]; then
compose_fips_override='-f docker-compose-ci.fips.yml'
fi

# Get image name from docker-compose-ci.yml
IMAGE=$(docker compose -f docker-compose-ci.yml config --format json 2>/dev/null | jq -r --arg s "$SERVICE" '.services[$s].image')
IMAGE=$(docker compose -f docker-compose-ci.yml $compose_fips_override config --format json 2>/dev/null | jq -r --arg s "$SERVICE" '.services[$s].image')

# Create directory for image archives
mkdir -p /tmp/docker-images
Expand Down
16 changes: 9 additions & 7 deletions .github/workflows/ci-test-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ jobs:
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
if: github.event.pull_request.head.repo.full_name != github.repository && github.event_name != 'release' && github.ref != 'refs/heads/develop'
with:
pattern: ${{ inputs.release == 'ce' && 'docker-image-rocketchat-amd64-coverage' || 'docker-image-*-amd64-coverage' }}
pattern: ${{ inputs.release == 'ce' && 'docker-image-rocketchat-amd64-coverage' || (inputs.release == 'fips' && 'docker-image-*-amd64-fips' || 'docker-image-*-amd64-coverage') }}
path: /tmp/docker-images
merge-multiple: true

Expand Down Expand Up @@ -187,20 +187,22 @@ jobs:
DEBUG_LOG_LEVEL=${DEBUG_LOG_LEVEL:-0} docker compose -f docker-compose-ci.yml up -d rocketchat --wait

- name: Start containers for EE
if: inputs.release == 'ee'
if: inputs.release == 'ee' || inputs.release == 'fips'
env:
ENTERPRISE_LICENSE: ${{ inputs.enterprise-license }}
TRANSPORTER: ${{ inputs.transporter }}
COMPOSE_PROFILES: ${{ inputs.type == 'api' && 'api' || '' }}
TEST_MODE: ${{ (inputs.type == 'api' || inputs.type == 'api-livechat') && 'api' || 'true' }}
FIPS_OVERRIDE: ${{ inputs.release == 'fips' && '-f docker-compose-ci.fips.yml' || '' }}
run: |
DEBUG_LOG_LEVEL=${DEBUG_LOG_LEVEL:-0} docker compose -f docker-compose-ci.yml up -d --wait
read -r -a fips_override <<< "$FIPS_OVERRIDE"
DEBUG_LOG_LEVEL=${DEBUG_LOG_LEVEL:-0} docker compose -f docker-compose-ci.yml "${fips_override[@]}" up -d --wait

- uses: ./.github/actions/setup-playwright
if: inputs.type == 'ui'

- name: Wait services to start up
if: inputs.release == 'ee'
if: inputs.release == 'ee' || inputs.release == 'fips'
run: |
docker ps

Expand All @@ -218,7 +220,7 @@ jobs:
working-directory: ./apps/meteor
env:
WEBHOOK_TEST_URL: 'http://httpbin'
IS_EE: ${{ inputs.release == 'ee' && 'true' || '' }}
IS_EE: ${{ (inputs.release == 'ee' || inputs.release == 'fips') && 'true' || '' }}
run: |
set -o xtrace

Expand All @@ -234,7 +236,7 @@ jobs:
working-directory: ./apps/meteor
env:
WEBHOOK_TEST_URL: 'http://httpbin'
IS_EE: ${{ inputs.release == 'ee' && 'true' || '' }}
IS_EE: ${{ (inputs.release == 'ee' || inputs.release == 'fips') && 'true' || '' }}
run: |
set -o xtrace

Expand All @@ -249,7 +251,7 @@ jobs:
if: inputs.type == 'ui'
env:
E2E_COVERAGE: ${{ inputs.coverage == matrix.mongodb-version && 'true' || '' }}
IS_EE: ${{ inputs.release == 'ee' && 'true' || '' }}
IS_EE: ${{ (inputs.release == 'ee' || inputs.release == 'fips') && 'true' || '' }}
REPORTER_ROCKETCHAT_API_KEY: ${{ secrets.REPORTER_ROCKETCHAT_API_KEY }}
REPORTER_ROCKETCHAT_URL: ${{ secrets.REPORTER_ROCKETCHAT_URL }}
REPORTER_JIRA_ROCKETCHAT_API_KEY: ${{ secrets.REPORTER_JIRA_ROCKETCHAT_API_KEY }}
Expand Down
123 changes: 121 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,28 @@ jobs:
- arch: arm64
service: [rocketchat]
type: coverage
# FIPS images: amd64 only, includes all microservices
- arch: amd64
service: [authorization-service]
type: fips
- arch: amd64
service: [queue-worker-service]
type: fips
- arch: amd64
service: [ddp-streamer-service]
type: fips
- arch: amd64
service: [account-service]
type: fips
- arch: amd64
service: [presence-service]
type: fips
- arch: amd64
service: [omnichannel-transcript-service]
type: fips
- arch: amd64
service: [rocketchat]
type: fips

steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
Expand All @@ -344,6 +366,8 @@ jobs:
with:
CR_USER: ${{ secrets.CR_USER }}
CR_PAT: ${{ secrets.CR_PAT }}
DOCKER_USER: ${{ secrets.DOCKER_USER }}
DOCKER_PASS: ${{ secrets.DOCKER_PASS }}
deno-version: ${{ needs.release-versions.outputs.deno-version }}
arch: ${{ matrix.arch }}
service: ${{ matrix.service[0] }}
Expand All @@ -358,6 +382,8 @@ jobs:
with:
CR_USER: ${{ secrets.CR_USER }}
CR_PAT: ${{ secrets.CR_PAT }}
DOCKER_USER: ${{ secrets.DOCKER_USER }}
DOCKER_PASS: ${{ secrets.DOCKER_PASS }}
deno-version: ${{ needs.release-versions.outputs.deno-version }}
arch: ${{ matrix.arch }}
service: ${{ matrix.service[1] }}
Expand All @@ -373,6 +399,8 @@ jobs:
with:
CR_USER: ${{ secrets.CR_USER }}
CR_PAT: ${{ secrets.CR_PAT }}
DOCKER_USER: ${{ secrets.DOCKER_USER }}
DOCKER_PASS: ${{ secrets.DOCKER_PASS }}
deno-version: ${{ needs.release-versions.outputs.deno-version }}
arch: ${{ matrix.arch }}
service: ${{ matrix.service[2] }}
Expand All @@ -388,6 +416,8 @@ jobs:
with:
CR_USER: ${{ secrets.CR_USER }}
CR_PAT: ${{ secrets.CR_PAT }}
DOCKER_USER: ${{ secrets.DOCKER_USER }}
DOCKER_PASS: ${{ secrets.DOCKER_PASS }}
deno-version: ${{ needs.release-versions.outputs.deno-version }}
arch: ${{ matrix.arch }}
service: ${{ matrix.service[3] }}
Expand All @@ -410,6 +440,7 @@ jobs:
with:
sparse-checkout: |
docker-compose-ci.yml
docker-compose-ci.fips.yml
sparse-checkout-cone-mode: false
ref: ${{ github.ref }}

Expand Down Expand Up @@ -452,6 +483,9 @@ jobs:
# Get image name from docker-compose-ci.yml since rocketchat image is different from service name (rocket.chat)
if [ "$service" == "rocketchat-cov" ]; then
IMAGE=$(docker compose -f docker-compose-ci.yml config --format json 2>/dev/null | jq -r --arg s "rocketchat" '.services[$s].image')-cov
elif [[ "$service" == *"-fips" ]]; then
base_service="${service%-fips}"
IMAGE=$(docker compose -f docker-compose-ci.yml config --format json 2>/dev/null | jq -r --arg s "$base_service" '.services[$s].image')-fips
else
IMAGE=$(docker compose -f docker-compose-ci.yml config --format json 2>/dev/null | jq -r --arg s "$service" '.services[$s].image')
fi
Expand Down Expand Up @@ -679,6 +713,73 @@ jobs:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
REPORTER_JIRA_ROCKETCHAT_API_KEY: ${{ secrets.REPORTER_JIRA_ROCKETCHAT_API_KEY }}

test-api-fips:
name: 🔨 Test API (FIPS)
needs: [checks, build-gh-docker-publish, release-versions]

uses: ./.github/workflows/ci-test-e2e.yml
with:
type: api
release: fips
transporter: 'nats://nats:4222'
enterprise-license: ${{ needs.release-versions.outputs.enterprise-license }}
mongodb-version: "['8.0']"
node-version: ${{ needs.release-versions.outputs.node-version }}
deno-version: ${{ needs.release-versions.outputs.deno-version }}
lowercase-repo: ${{ needs.release-versions.outputs.lowercase-repo }}
gh-docker-tag: ${{ needs.release-versions.outputs.gh-docker-tag }}
secrets:
CR_USER: ${{ secrets.CR_USER }}
CR_PAT: ${{ secrets.CR_PAT }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

test-api-livechat-fips:
name: 🔨 Test API Livechat (FIPS)
needs: [checks, build-gh-docker-publish, release-versions]

uses: ./.github/workflows/ci-test-e2e.yml
with:
type: api-livechat
release: fips
transporter: 'nats://nats:4222'
enterprise-license: ${{ needs.release-versions.outputs.enterprise-license }}
mongodb-version: "['8.0']"
node-version: ${{ needs.release-versions.outputs.node-version }}
deno-version: ${{ needs.release-versions.outputs.deno-version }}
lowercase-repo: ${{ needs.release-versions.outputs.lowercase-repo }}
gh-docker-tag: ${{ needs.release-versions.outputs.gh-docker-tag }}
secrets:
CR_USER: ${{ secrets.CR_USER }}
CR_PAT: ${{ secrets.CR_PAT }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

test-ui-fips:
name: 🔨 Test UI (FIPS)
needs: [checks, build-gh-docker-publish, release-versions]

uses: ./.github/workflows/ci-test-e2e.yml
with:
type: ui
release: fips
transporter: 'nats://nats:4222'
enterprise-license: ${{ needs.release-versions.outputs.enterprise-license }}
shard: '[1, 2, 3, 4, 5]'
total-shard: 5
mongodb-version: "['8.0']"
node-version: ${{ needs.release-versions.outputs.node-version }}
deno-version: ${{ needs.release-versions.outputs.deno-version }}
lowercase-repo: ${{ needs.release-versions.outputs.lowercase-repo }}
gh-docker-tag: ${{ needs.release-versions.outputs.gh-docker-tag }}
retries: ${{ (github.event_name == 'release' || github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/master') && 2 || 0 }}
secrets:
CR_USER: ${{ secrets.CR_USER }}
CR_PAT: ${{ secrets.CR_PAT }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
QASE_API_TOKEN: ${{ secrets.QASE_API_TOKEN }}
REPORTER_ROCKETCHAT_API_KEY: ${{ secrets.REPORTER_ROCKETCHAT_API_KEY }}
REPORTER_ROCKETCHAT_URL: ${{ secrets.REPORTER_ROCKETCHAT_URL }}
REPORTER_JIRA_ROCKETCHAT_API_KEY: ${{ secrets.REPORTER_JIRA_ROCKETCHAT_API_KEY }}

test-federation-matrix:
name: 🔨 Test Federation Matrix
needs: [checks, build-gh-docker-publish, packages-build, release-versions]
Expand Down Expand Up @@ -829,7 +930,7 @@ jobs:
tests-done:
name: ✅ Tests Done
runs-on: ubuntu-24.04-arm
needs: [checks, test-unit, test-api, test-ui, test-api-ee, test-ui-ee, test-api-livechat, test-api-livechat-ee, test-federation-matrix]
needs: [checks, test-unit, test-api, test-ui, test-api-ee, test-ui-ee, test-api-livechat, test-api-livechat-ee, test-api-fips, test-api-livechat-fips, test-ui-fips, test-federation-matrix]
if: always()
steps:
- name: Test finish aggregation
Expand Down Expand Up @@ -866,6 +967,18 @@ jobs:
exit 1
fi

if [[ '${{ needs.test-api-fips.result }}' != 'success' ]]; then
exit 1
fi

if [[ '${{ needs.test-api-livechat-fips.result }}' != 'success' ]]; then
exit 1
fi

if [[ '${{ needs.test-ui-fips.result }}' != 'success' ]]; then
exit 1
fi

if [[ '${{ needs.test-federation-matrix.result }}' != 'success' ]]; then
exit 1
fi
Expand Down Expand Up @@ -938,6 +1051,7 @@ jobs:
with:
sparse-checkout: |
docker-compose-ci.yml
docker-compose-ci.fips.yml
sparse-checkout-cone-mode: false
ref: ${{ github.ref }}

Expand Down Expand Up @@ -1021,7 +1135,12 @@ jobs:
fi

# Get image name from docker-compose-ci.yml since rocketchat image is different from service name (rocket.chat)
SRC=$(docker compose -f docker-compose-ci.yml config --format json 2>/dev/null | jq -r --arg s "${service}" '.services[$s].image')
if [[ "$service" == *"-fips" ]]; then
base_service="${service%-fips}"
SRC=$(docker compose -f docker-compose-ci.yml -f docker-compose-ci.fips.yml config --format json 2>/dev/null | jq -r --arg s "$base_service" '.services[$s].image')
else
SRC=$(docker compose -f docker-compose-ci.yml config --format json 2>/dev/null | jq -r --arg s "${service}" '.services[$s].image')
fi
DEST_REPO="docker.io/${IMAGE_NAME}"

echo "Copying $SRC to ${DEST_REPO}:${PRIMARY}"
Expand Down
Loading
Loading