mirror of
https://github.com/element-hq/matrix-authentication-service.git
synced 2026-06-06 13:22:30 +00:00
Merge branch 'main' into madlittlemods/soft-limit-account-session-management
This commit is contained in:
@@ -11,11 +11,7 @@ updates:
|
||||
- "A-Dependencies"
|
||||
- "Z-Deps-Backend"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
ignore:
|
||||
# We plan to remove apalis soon, let's ignore it for now
|
||||
- dependency-name: "apalis"
|
||||
- dependency-name: "apalis-*"
|
||||
interval: "monthly"
|
||||
groups:
|
||||
axum:
|
||||
patterns:
|
||||
@@ -53,7 +49,7 @@ updates:
|
||||
- "A-Dependencies"
|
||||
- "Z-Deps-CI"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
cooldown:
|
||||
default-days: 14
|
||||
|
||||
@@ -63,7 +59,7 @@ updates:
|
||||
- "A-Dependencies"
|
||||
- "Z-Deps-Frontend"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "monthly"
|
||||
groups:
|
||||
storybook:
|
||||
patterns:
|
||||
|
||||
+333
-49
@@ -27,9 +27,12 @@ env:
|
||||
CARGO_NET_GIT_FETCH_WITH_CLI: "true"
|
||||
SCCACHE_GHA_ENABLED: "true"
|
||||
RUSTC_WRAPPER: "sccache"
|
||||
IMAGE: ghcr.io/element-hq/matrix-authentication-service
|
||||
BUILDCACHE: ghcr.io/element-hq/matrix-authentication-service/buildcache
|
||||
DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index
|
||||
# metadata-action defaults to `manifest`, which `docker buildx imagetools
|
||||
# create --annotation` refuses with "manifest annotations are not supported
|
||||
# yet". We only want annotations on the manifest list anyway, so narrow it
|
||||
# to `index`.
|
||||
DOCKER_METADATA_ANNOTATIONS_LEVELS: index
|
||||
|
||||
jobs:
|
||||
compute-version:
|
||||
@@ -208,32 +211,30 @@ jobs:
|
||||
name: mas-cli-x86_64-linux
|
||||
path: mas-cli-x86_64-linux.tar.gz
|
||||
|
||||
build-image:
|
||||
name: Build and push Docker image
|
||||
compute-image-meta:
|
||||
name: Compute Docker image metadata
|
||||
if: github.event_name == 'push' || github.event.label.name == 'Z-Build-Workflow'
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
outputs:
|
||||
metadata: ${{ steps.output.outputs.metadata }}
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
id-token: write
|
||||
|
||||
needs:
|
||||
- compute-version
|
||||
|
||||
env:
|
||||
VERGEN_GIT_DESCRIBE: ${{ needs.compute-version.outputs.describe }}
|
||||
SOURCE_DATE_EPOCH: ${{ needs.compute-version.outputs.timestamp }}
|
||||
outputs:
|
||||
regular-tags: ${{ steps.meta.outputs.tags }}
|
||||
regular-annotations: ${{ steps.meta.outputs.annotations }}
|
||||
debug-tags: ${{ steps.meta-debug.outputs.tags }}
|
||||
debug-annotations: ${{ steps.meta-debug.outputs.annotations }}
|
||||
|
||||
steps:
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0
|
||||
with:
|
||||
images: "${{ env.IMAGE }}"
|
||||
# The oci-push registry login requires Tailscale + Vault, which only
|
||||
# works for `push` events (PR-labelled runs lack the right OIDC token).
|
||||
images: |
|
||||
ghcr.io/element-hq/matrix-authentication-service
|
||||
${{ github.event_name == 'push' && 'oci-push.vpn.infra.element.io/matrix-authentication-service' || '' }}
|
||||
bake-target: docker-metadata-action
|
||||
flavor: |
|
||||
latest=auto
|
||||
@@ -244,12 +245,23 @@ jobs:
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=semver,pattern={{major}}
|
||||
type=sha
|
||||
# GitHub's license detection (via Licensee) can only report a single
|
||||
# SPDX identifier and still emits the legacy `AGPL-3.0` form, which
|
||||
# `metadata-action` would otherwise propagate as-is. Override it with
|
||||
# the project's actual dual-license SPDX expression so the image
|
||||
# advertises both halves of the dual licensing.
|
||||
labels: |
|
||||
org.opencontainers.image.licenses=AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
annotations: |
|
||||
org.opencontainers.image.licenses=AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
|
||||
- name: Docker meta (debug variant)
|
||||
id: meta-debug
|
||||
uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0
|
||||
with:
|
||||
images: "${{ env.IMAGE }}"
|
||||
images: |
|
||||
ghcr.io/element-hq/matrix-authentication-service
|
||||
${{ github.event_name == 'push' && 'oci-push.vpn.infra.element.io/matrix-authentication-service' || '' }}
|
||||
bake-target: docker-metadata-action-debug
|
||||
flavor: |
|
||||
latest=auto
|
||||
@@ -261,10 +273,63 @@ jobs:
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=semver,pattern={{major}}
|
||||
type=sha
|
||||
labels: |
|
||||
org.opencontainers.image.licenses=AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
annotations: |
|
||||
org.opencontainers.image.licenses=AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
|
||||
- name: Setup Cosign
|
||||
uses: sigstore/cosign-installer@cad07c2e89fa2edd6e2d7bab4c1aa38e53f76003 # v4.1.1
|
||||
# Stage the labels bake files under predictable names (the metadata-action
|
||||
# writes them under a random temp dir with the same base name) and ship
|
||||
# them to `build-image` as an artifact. We deliberately only pass through
|
||||
# `bake-file-labels` (not `bake-file-annotations`): the per-arch images
|
||||
# then carry the same config labels as today, while annotations are only
|
||||
# applied at the index level in `finalize-image` — matching `:latest`'s
|
||||
# shape and sidestepping `metadata-action`'s empty-value annotations
|
||||
# which would otherwise trip `docker buildx imagetools create`.
|
||||
- name: Stage bake files
|
||||
env:
|
||||
REGULAR_FILE: ${{ steps.meta.outputs.bake-file-labels }}
|
||||
DEBUG_FILE: ${{ steps.meta-debug.outputs.bake-file-labels }}
|
||||
run: |
|
||||
mkdir -p /tmp/bake
|
||||
cp "$REGULAR_FILE" /tmp/bake/regular.json
|
||||
cp "$DEBUG_FILE" /tmp/bake/debug.json
|
||||
|
||||
- name: Upload bake files
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: bake-files
|
||||
path: /tmp/bake/
|
||||
retention-days: 1
|
||||
|
||||
build-image:
|
||||
name: Build Docker image (${{ matrix.arch }})
|
||||
if: github.event_name == 'push' || github.event.label.name == 'Z-Build-Workflow'
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
id-token: write
|
||||
|
||||
needs:
|
||||
- compute-version
|
||||
- compute-image-meta
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
arch: [amd64, arm64]
|
||||
|
||||
env:
|
||||
VERGEN_GIT_DESCRIBE: ${{ needs.compute-version.outputs.describe }}
|
||||
SOURCE_DATE_EPOCH: ${{ needs.compute-version.outputs.timestamp }}
|
||||
# Comma-separated list of registries to push each per-arch image to.
|
||||
# The oci-push registry is only included on `push` events because the
|
||||
# Tailscale + Vault login below requires the right OIDC token.
|
||||
IMAGES: ghcr.io/element-hq/matrix-authentication-service${{ github.event_name == 'push' && ',oci-push.vpn.infra.element.io/matrix-authentication-service' || '' }}
|
||||
|
||||
steps:
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
||||
with:
|
||||
@@ -279,29 +344,218 @@ jobs:
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
# The Element OCI Registry is only reachable via Tailscale, and the Vault
|
||||
# JWT exchange relies on a GitHub OIDC token issued from a `push` event.
|
||||
# PR-labelled builds (`Z-Build-Workflow`) skip this and push only to ghcr.
|
||||
- name: Tailscale
|
||||
if: github.event_name == 'push'
|
||||
uses: tailscale/github-action@53acf823325fe9ca47f4cdaa951f90b4b0de5bb9 # v4.1.1
|
||||
with:
|
||||
oauth-client-id: ${{ secrets.TS_OAUTH_CLIENT_ID }}
|
||||
audience: ${{ secrets.TS_AUDIENCE }}
|
||||
tags: tag:github-actions
|
||||
|
||||
- name: Compute vault jwt role name
|
||||
id: vault-jwt-role
|
||||
if: github.event_name == 'push'
|
||||
run: |
|
||||
echo "role_name=github_service_management_$( echo "${{ github.repository }}" | sed -r 's|[/-]|_|g')" | tee -a "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Get team registry token
|
||||
id: import-secrets
|
||||
if: github.event_name == 'push'
|
||||
uses: hashicorp/vault-action@4c06c5ccf5c0761b6029f56cfb1dcf5565918a3b # v3.4.0
|
||||
with:
|
||||
url: https://vault.infra.ci.i.element.dev
|
||||
role: ${{ steps.vault-jwt-role.outputs.role_name }}
|
||||
path: service-management/github-actions
|
||||
jwtGithubAudience: https://vault.infra.ci.i.element.dev
|
||||
method: jwt
|
||||
secrets: |
|
||||
services/backend-repositories/secret/data/oci.element.io username | OCI_USERNAME ;
|
||||
services/backend-repositories/secret/data/oci.element.io password | OCI_PASSWORD ;
|
||||
|
||||
- name: Login to Element OCI Registry
|
||||
if: github.event_name == 'push'
|
||||
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
|
||||
with:
|
||||
registry: oci-push.vpn.infra.element.io
|
||||
username: ${{ steps.import-secrets.outputs.OCI_USERNAME }}
|
||||
password: ${{ steps.import-secrets.outputs.OCI_PASSWORD }}
|
||||
|
||||
- name: Download bake files
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
|
||||
with:
|
||||
name: bake-files
|
||||
path: /tmp/bake
|
||||
|
||||
- name: Build and push by digest
|
||||
id: bake
|
||||
uses: docker/bake-action@a66e1c87e2eca0503c343edf1d208c716d54b8a8 # v7.1.0
|
||||
env:
|
||||
# By default, docker bake will add provenance information to the
|
||||
# metadata output. This makes the output larger and may exceed the
|
||||
# shell ARG_MAX limit. Disabling through this environment variable
|
||||
# disables provenance in the metadata while still attaching provenance
|
||||
# attestations to the image we push.
|
||||
# https://github.com/docker/bake-action/issues/239#issuecomment-3828170326
|
||||
BUILDX_METADATA_PROVENANCE: disabled
|
||||
with:
|
||||
files: |
|
||||
./docker-bake.hcl
|
||||
cwd://${{ steps.meta.outputs.bake-file }}
|
||||
cwd://${{ steps.meta-debug.outputs.bake-file }}
|
||||
cwd:///tmp/bake/regular.json
|
||||
cwd:///tmp/bake/debug.json
|
||||
set: |
|
||||
base.output=type=image,push=true
|
||||
base.cache-from=type=registry,ref=${{ env.BUILDCACHE }}:buildcache
|
||||
base.cache-to=type=registry,ref=${{ env.BUILDCACHE }}:buildcache,mode=max
|
||||
*.platform=linux/${{ matrix.arch }}
|
||||
*.output=type=image,"name=${{ env.IMAGES }}",push-by-digest=true,name-canonical=true,push=true
|
||||
*.cache-from=type=registry,ref=${{ env.BUILDCACHE }}:buildcache-${{ matrix.arch }}
|
||||
*.cache-to=type=registry,ref=${{ env.BUILDCACHE }}:buildcache-${{ matrix.arch }},mode=max
|
||||
|
||||
- name: Transform bake output
|
||||
# This transforms the ouput to an object which looks like this:
|
||||
# { reguar: { digest: "…", tags: ["…", "…"] }, debug: { digest: "…", tags: ["…"] }, … }
|
||||
id: output
|
||||
run: |
|
||||
echo 'metadata<<EOF' >> $GITHUB_OUTPUT
|
||||
echo "$STEPS_BAKE_OUTPUTS_METADATA" | jq -c 'with_entries(select(.value | (type == "object" and has("containerimage.digest")))) | map_values({ digest: .["containerimage.digest"], tags: (.["image.name"] | split(",")) })' >> $GITHUB_OUTPUT
|
||||
echo 'EOF' >> $GITHUB_OUTPUT
|
||||
# We use github-script rather than shelling out to jq because the bake
|
||||
# metadata can exceed the shell ARG_MAX limit when inherited as an env
|
||||
# var by an exec'd jq.
|
||||
- name: Export digests
|
||||
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
|
||||
env:
|
||||
STEPS_BAKE_OUTPUTS_METADATA: ${{ steps.bake.outputs.metadata }}
|
||||
ARCH: ${{ matrix.arch }}
|
||||
with:
|
||||
script: |
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
const bakeOutput = JSON.parse(process.env.STEPS_BAKE_OUTPUTS_METADATA);
|
||||
const arch = process.env.ARCH;
|
||||
fs.mkdirSync('/tmp/digests', { recursive: true });
|
||||
for (const target of ['regular', 'debug']) {
|
||||
const digest = bakeOutput[target]?.['containerimage.digest'];
|
||||
if (!digest) {
|
||||
throw new Error(`Missing containerimage.digest for target ${target}`);
|
||||
}
|
||||
fs.writeFileSync(path.join('/tmp/digests', `${target}-${arch}`), digest);
|
||||
}
|
||||
|
||||
- name: Upload digests
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: digests-${{ matrix.arch }}
|
||||
path: /tmp/digests/*
|
||||
retention-days: 1
|
||||
|
||||
finalize-image:
|
||||
name: Create multi-arch manifests
|
||||
if: github.event_name == 'push' || github.event.label.name == 'Z-Build-Workflow'
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
needs:
|
||||
- build-image
|
||||
- compute-image-meta
|
||||
|
||||
outputs:
|
||||
metadata: ${{ steps.output.outputs.metadata }}
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
id-token: write
|
||||
|
||||
steps:
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
|
||||
with:
|
||||
pattern: digests-*
|
||||
path: /tmp/digests
|
||||
# Collect digests from both amd64 and arm64 builds
|
||||
merge-multiple: true
|
||||
|
||||
- name: Setup Cosign
|
||||
uses: sigstore/cosign-installer@cad07c2e89fa2edd6e2d7bab4c1aa38e53f76003 # v4.1.1
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# See `build-image` for why the Element OCI Registry login is gated on
|
||||
# `push` events.
|
||||
- name: Tailscale
|
||||
if: github.event_name == 'push'
|
||||
uses: tailscale/github-action@53acf823325fe9ca47f4cdaa951f90b4b0de5bb9 # v4.1.1
|
||||
with:
|
||||
oauth-client-id: ${{ secrets.TS_OAUTH_CLIENT_ID }}
|
||||
audience: ${{ secrets.TS_AUDIENCE }}
|
||||
tags: tag:github-actions
|
||||
|
||||
- name: Compute vault jwt role name
|
||||
id: vault-jwt-role
|
||||
if: github.event_name == 'push'
|
||||
run: |
|
||||
echo "role_name=github_service_management_$( echo "${{ github.repository }}" | sed -r 's|[/-]|_|g')" | tee -a "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Get team registry token
|
||||
id: import-secrets
|
||||
if: github.event_name == 'push'
|
||||
uses: hashicorp/vault-action@4c06c5ccf5c0761b6029f56cfb1dcf5565918a3b # v3.4.0
|
||||
with:
|
||||
url: https://vault.infra.ci.i.element.dev
|
||||
role: ${{ steps.vault-jwt-role.outputs.role_name }}
|
||||
path: service-management/github-actions
|
||||
jwtGithubAudience: https://vault.infra.ci.i.element.dev
|
||||
method: jwt
|
||||
secrets: |
|
||||
services/backend-repositories/secret/data/oci.element.io username | OCI_USERNAME ;
|
||||
services/backend-repositories/secret/data/oci.element.io password | OCI_PASSWORD ;
|
||||
|
||||
- name: Login to Element OCI Registry
|
||||
if: github.event_name == 'push'
|
||||
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
|
||||
with:
|
||||
registry: oci-push.vpn.infra.element.io
|
||||
username: ${{ steps.import-secrets.outputs.OCI_USERNAME }}
|
||||
password: ${{ steps.import-secrets.outputs.OCI_PASSWORD }}
|
||||
|
||||
- name: Create regular manifest
|
||||
id: regular
|
||||
env:
|
||||
TAGS: ${{ needs.compute-image-meta.outputs.regular-tags }}
|
||||
ANNOTATIONS: ${{ needs.compute-image-meta.outputs.regular-annotations }}
|
||||
run: |
|
||||
# Construct the `imagetools create` command line from the tag and annotation inputs.
|
||||
args=()
|
||||
|
||||
# Add a `-t <tag>` argument for each non-empty tag.
|
||||
while IFS= read -r t; do [[ -n $t ]] && args+=(-t "$t"); done <<< "$TAGS"
|
||||
|
||||
# Add a `--annotation <key>=<value>` argument for each non-empty annotation
|
||||
while IFS= read -r a; do [[ -n $a && $a != *= ]] && args+=(--annotation "$a"); done <<< "$ANNOTATIONS"
|
||||
|
||||
docker buildx imagetools create "${args[@]}" \
|
||||
"ghcr.io/element-hq/matrix-authentication-service@$(cat /tmp/digests/regular-amd64)" \
|
||||
"ghcr.io/element-hq/matrix-authentication-service@$(cat /tmp/digests/regular-arm64)" \
|
||||
--metadata-file regular-metadata.json
|
||||
|
||||
# `imagetools create` wrote the digest to regular-metadata.json
|
||||
echo "digest=$(jq -r '.["containerimage.descriptor"].digest' regular-metadata.json)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Create debug manifest
|
||||
id: debug
|
||||
env:
|
||||
TAGS: ${{ needs.compute-image-meta.outputs.debug-tags }}
|
||||
ANNOTATIONS: ${{ needs.compute-image-meta.outputs.debug-annotations }}
|
||||
run: |
|
||||
# See comments in regular manifest creation for argument construction.
|
||||
args=()
|
||||
while IFS= read -r t; do [[ -n $t ]] && args+=(-t "$t"); done <<< "$TAGS"
|
||||
while IFS= read -r a; do [[ -n $a && $a != *= ]] && args+=(--annotation "$a"); done <<< "$ANNOTATIONS"
|
||||
docker buildx imagetools create "${args[@]}" \
|
||||
"ghcr.io/element-hq/matrix-authentication-service@$(cat /tmp/digests/debug-amd64)" \
|
||||
"ghcr.io/element-hq/matrix-authentication-service@$(cat /tmp/digests/debug-arm64)" \
|
||||
--metadata-file debug-metadata.json
|
||||
echo "digest=$(jq -r '.["containerimage.descriptor"].digest' debug-metadata.json)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Sign the images with GitHub Actions provided token
|
||||
# Only sign on tags and on commits on main branch
|
||||
@@ -310,13 +564,38 @@ jobs:
|
||||
&& (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main')
|
||||
|
||||
env:
|
||||
REGULAR_DIGEST: ${{ steps.output.outputs.metadata && fromJSON(steps.output.outputs.metadata).regular.digest }}
|
||||
DEBUG_DIGEST: ${{ steps.output.outputs.metadata && fromJSON(steps.output.outputs.metadata).debug.digest }}
|
||||
REGULAR_DIGEST: ${{ steps.regular.outputs.digest }}
|
||||
DEBUG_DIGEST: ${{ steps.debug.outputs.digest }}
|
||||
|
||||
run: |-
|
||||
cosign sign --yes \
|
||||
"$IMAGE@$REGULAR_DIGEST" \
|
||||
"$IMAGE@$DEBUG_DIGEST" \
|
||||
"ghcr.io/element-hq/matrix-authentication-service@$REGULAR_DIGEST" \
|
||||
"ghcr.io/element-hq/matrix-authentication-service@$DEBUG_DIGEST"
|
||||
cosign sign --yes \
|
||||
"oci-push.vpn.infra.element.io/matrix-authentication-service@$REGULAR_DIGEST" \
|
||||
"oci-push.vpn.infra.element.io/matrix-authentication-service@$DEBUG_DIGEST"
|
||||
|
||||
- name: Output metadata
|
||||
id: output
|
||||
env:
|
||||
REGULAR_DIGEST: ${{ steps.regular.outputs.digest }}
|
||||
DEBUG_DIGEST: ${{ steps.debug.outputs.digest }}
|
||||
REGULAR_TAGS: ${{ needs.compute-image-meta.outputs.regular-tags }}
|
||||
DEBUG_TAGS: ${{ needs.compute-image-meta.outputs.debug-tags }}
|
||||
run: |
|
||||
# Convert the newline-separated tag lists into JSON arrays.
|
||||
regular_tags=$(jq -Rnc '[inputs | select(length > 0)]' <<< "$REGULAR_TAGS")
|
||||
debug_tags=$(jq -Rnc '[inputs | select(length > 0)]' <<< "$DEBUG_TAGS")
|
||||
{
|
||||
echo 'metadata<<EOF'
|
||||
jq -nc \
|
||||
--arg regular_digest "$REGULAR_DIGEST" \
|
||||
--arg debug_digest "$DEBUG_DIGEST" \
|
||||
--argjson regular_tags "$regular_tags" \
|
||||
--argjson debug_tags "$debug_tags" \
|
||||
'{regular: {digest: $regular_digest, tags: $regular_tags}, debug: {digest: $debug_digest, tags: $debug_tags}}'
|
||||
echo 'EOF'
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
|
||||
release:
|
||||
name: Release
|
||||
@@ -324,7 +603,8 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
needs:
|
||||
- assemble-archives
|
||||
- build-image
|
||||
- finalize-image
|
||||
|
||||
steps:
|
||||
- name: Download the artifacts from the previous job
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
|
||||
@@ -344,11 +624,12 @@ jobs:
|
||||
|
||||
- Digest:
|
||||
```
|
||||
${{ env.IMAGE }}@${{ fromJSON(needs.build-image.outputs.metadata).regular.digest }}
|
||||
ghcr.io/element-hq/matrix-authentication-service@${{ fromJSON(needs.finalize-image.outputs.metadata).regular.digest }}
|
||||
oci.element.io/matrix-authentication-service@${{ fromJSON(needs.finalize-image.outputs.metadata).regular.digest }}
|
||||
```
|
||||
- Tags:
|
||||
```
|
||||
${{ join(fromJSON(needs.build-image.outputs.metadata).regular.tags, '
|
||||
${{ join(fromJSON(needs.finalize-image.outputs.metadata).regular.tags, '
|
||||
') }}
|
||||
```
|
||||
|
||||
@@ -356,11 +637,12 @@ jobs:
|
||||
|
||||
- Digest:
|
||||
```
|
||||
${{ env.IMAGE }}@${{ fromJSON(needs.build-image.outputs.metadata).debug.digest }}
|
||||
ghcr.io/element-hq/matrix-authentication-service@${{ fromJSON(needs.finalize-image.outputs.metadata).debug.digest }}
|
||||
oci.element.io/matrix-authentication-service@${{ fromJSON(needs.finalize-image.outputs.metadata).debug.digest }}
|
||||
```
|
||||
- Tags:
|
||||
```
|
||||
${{ join(fromJSON(needs.build-image.outputs.metadata).debug.tags, '
|
||||
${{ join(fromJSON(needs.finalize-image.outputs.metadata).debug.tags, '
|
||||
') }}
|
||||
```
|
||||
|
||||
@@ -376,7 +658,7 @@ jobs:
|
||||
|
||||
needs:
|
||||
- assemble-archives
|
||||
- build-image
|
||||
- finalize-image
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
@@ -422,11 +704,12 @@ jobs:
|
||||
|
||||
- Digest:
|
||||
```
|
||||
${{ env.IMAGE }}@${{ fromJSON(needs.build-image.outputs.metadata).regular.digest }}
|
||||
ghcr.io/element-hq/matrix-authentication-service@${{ fromJSON(needs.finalize-image.outputs.metadata).regular.digest }}
|
||||
oci.element.io/matrix-authentication-service@${{ fromJSON(needs.finalize-image.outputs.metadata).regular.digest }}
|
||||
```
|
||||
- Tags:
|
||||
```
|
||||
${{ join(fromJSON(needs.build-image.outputs.metadata).regular.tags, '
|
||||
${{ join(fromJSON(needs.finalize-image.outputs.metadata).regular.tags, '
|
||||
') }}
|
||||
```
|
||||
|
||||
@@ -434,11 +717,12 @@ jobs:
|
||||
|
||||
- Digest:
|
||||
```
|
||||
${{ env.IMAGE }}@${{ fromJSON(needs.build-image.outputs.metadata).debug.digest }}
|
||||
ghcr.io/element-hq/matrix-authentication-service@${{ fromJSON(needs.finalize-image.outputs.metadata).debug.digest }}
|
||||
oci.element.io/matrix-authentication-service@${{ fromJSON(needs.finalize-image.outputs.metadata).debug.digest }}
|
||||
```
|
||||
- Tags:
|
||||
```
|
||||
${{ join(fromJSON(needs.build-image.outputs.metadata).debug.tags, '
|
||||
${{ join(fromJSON(needs.finalize-image.outputs.metadata).debug.tags, '
|
||||
') }}
|
||||
```
|
||||
|
||||
@@ -454,7 +738,7 @@ jobs:
|
||||
if: github.event_name == 'pull_request' && github.event.label.name == 'Z-Build-Workflow'
|
||||
|
||||
needs:
|
||||
- build-image
|
||||
- finalize-image
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -471,7 +755,7 @@ jobs:
|
||||
- name: Remove label and comment
|
||||
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
|
||||
env:
|
||||
BUILD_IMAGE_MANIFEST: ${{ needs.build-image.outputs.metadata }}
|
||||
BUILD_IMAGE_MANIFEST: ${{ needs.finalize-image.outputs.metadata }}
|
||||
with:
|
||||
script: |
|
||||
const script = require('./.github/scripts/cleanup-pr.cjs');
|
||||
|
||||
Generated
+28
-28
@@ -3092,7 +3092,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-axum-utils"
|
||||
version = "1.17.0-rc.0"
|
||||
version = "1.17.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"axum",
|
||||
@@ -3126,7 +3126,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-cli"
|
||||
version = "1.17.0-rc.0"
|
||||
version = "1.17.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"axum",
|
||||
@@ -3201,7 +3201,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-config"
|
||||
version = "1.17.0-rc.0"
|
||||
version = "1.17.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"camino",
|
||||
@@ -3232,7 +3232,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-context"
|
||||
version = "1.17.0-rc.0"
|
||||
version = "1.17.0"
|
||||
dependencies = [
|
||||
"console",
|
||||
"opentelemetry",
|
||||
@@ -3248,7 +3248,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-data-model"
|
||||
version = "1.17.0-rc.0"
|
||||
version = "1.17.0"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
"chrono",
|
||||
@@ -3270,7 +3270,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-email"
|
||||
version = "1.17.0-rc.0"
|
||||
version = "1.17.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"lettre",
|
||||
@@ -3281,7 +3281,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-handlers"
|
||||
version = "1.17.0-rc.0"
|
||||
version = "1.17.0"
|
||||
dependencies = [
|
||||
"aide",
|
||||
"anyhow",
|
||||
@@ -3362,7 +3362,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-http"
|
||||
version = "1.17.0-rc.0"
|
||||
version = "1.17.0"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"headers",
|
||||
@@ -3383,7 +3383,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-i18n"
|
||||
version = "1.17.0-rc.0"
|
||||
version = "1.17.0"
|
||||
dependencies = [
|
||||
"camino",
|
||||
"icu_calendar",
|
||||
@@ -3405,7 +3405,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-i18n-scan"
|
||||
version = "1.17.0-rc.0"
|
||||
version = "1.17.0"
|
||||
dependencies = [
|
||||
"camino",
|
||||
"clap",
|
||||
@@ -3419,7 +3419,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-iana"
|
||||
version = "1.17.0-rc.0"
|
||||
version = "1.17.0"
|
||||
dependencies = [
|
||||
"schemars 0.9.0",
|
||||
"serde",
|
||||
@@ -3427,7 +3427,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-iana-codegen"
|
||||
version = "1.17.0-rc.0"
|
||||
version = "1.17.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@@ -3444,7 +3444,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-jose"
|
||||
version = "1.17.0-rc.0"
|
||||
version = "1.17.0"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
"chrono",
|
||||
@@ -3474,7 +3474,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-keystore"
|
||||
version = "1.17.0-rc.0"
|
||||
version = "1.17.0"
|
||||
dependencies = [
|
||||
"aead",
|
||||
"base64ct",
|
||||
@@ -3502,7 +3502,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-listener"
|
||||
version = "1.17.0-rc.0"
|
||||
version = "1.17.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
@@ -3526,7 +3526,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-matrix"
|
||||
version = "1.17.0-rc.0"
|
||||
version = "1.17.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@@ -3536,7 +3536,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-matrix-synapse"
|
||||
version = "1.17.0-rc.0"
|
||||
version = "1.17.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@@ -3553,7 +3553,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-oidc-client"
|
||||
version = "1.17.0-rc.0"
|
||||
version = "1.17.0"
|
||||
dependencies = [
|
||||
"assert_matches",
|
||||
"async-trait",
|
||||
@@ -3589,7 +3589,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-policy"
|
||||
version = "1.17.0-rc.0"
|
||||
version = "1.17.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"arc-swap",
|
||||
@@ -3606,7 +3606,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-router"
|
||||
version = "1.17.0-rc.0"
|
||||
version = "1.17.0"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"serde",
|
||||
@@ -3617,7 +3617,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-spa"
|
||||
version = "1.17.0-rc.0"
|
||||
version = "1.17.0"
|
||||
dependencies = [
|
||||
"camino",
|
||||
"serde",
|
||||
@@ -3626,7 +3626,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-storage"
|
||||
version = "1.17.0-rc.0"
|
||||
version = "1.17.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"chrono",
|
||||
@@ -3648,7 +3648,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-storage-pg"
|
||||
version = "1.17.0-rc.0"
|
||||
version = "1.17.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"chrono",
|
||||
@@ -3678,7 +3678,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-tasks"
|
||||
version = "1.17.0-rc.0"
|
||||
version = "1.17.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@@ -3710,7 +3710,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-templates"
|
||||
version = "1.17.0-rc.0"
|
||||
version = "1.17.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"arc-swap",
|
||||
@@ -3742,7 +3742,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-tower"
|
||||
version = "1.17.0-rc.0"
|
||||
version = "1.17.0"
|
||||
dependencies = [
|
||||
"http",
|
||||
"opentelemetry",
|
||||
@@ -3995,7 +3995,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oauth2-types"
|
||||
version = "1.17.0-rc.0"
|
||||
version = "1.17.0"
|
||||
dependencies = [
|
||||
"assert_matches",
|
||||
"base64ct",
|
||||
@@ -6094,7 +6094,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn2mas"
|
||||
version = "1.17.0-rc.0"
|
||||
version = "1.17.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"arc-swap",
|
||||
|
||||
+30
-30
@@ -9,7 +9,7 @@ members = ["crates/*"]
|
||||
resolver = "2"
|
||||
|
||||
# Updated in the CI with a `sed` command
|
||||
package.version = "1.17.0-rc.0"
|
||||
package.version = "1.17.0"
|
||||
package.license = "AGPL-3.0-only OR LicenseRef-Element-Commercial"
|
||||
package.authors = ["Element Backend Team"]
|
||||
package.edition = "2024"
|
||||
@@ -39,35 +39,35 @@ broken_intra_doc_links = "deny"
|
||||
[workspace.dependencies]
|
||||
|
||||
# Workspace crates
|
||||
mas-axum-utils = { path = "./crates/axum-utils/", version = "=1.17.0-rc.0" }
|
||||
mas-cli = { path = "./crates/cli/", version = "=1.17.0-rc.0" }
|
||||
mas-config = { path = "./crates/config/", version = "=1.17.0-rc.0" }
|
||||
mas-context = { path = "./crates/context/", version = "=1.17.0-rc.0" }
|
||||
mas-data-model = { path = "./crates/data-model/", version = "=1.17.0-rc.0" }
|
||||
mas-email = { path = "./crates/email/", version = "=1.17.0-rc.0" }
|
||||
mas-graphql = { path = "./crates/graphql/", version = "=1.17.0-rc.0" }
|
||||
mas-handlers = { path = "./crates/handlers/", version = "=1.17.0-rc.0" }
|
||||
mas-http = { path = "./crates/http/", version = "=1.17.0-rc.0" }
|
||||
mas-i18n = { path = "./crates/i18n/", version = "=1.17.0-rc.0" }
|
||||
mas-i18n-scan = { path = "./crates/i18n-scan/", version = "=1.17.0-rc.0" }
|
||||
mas-iana = { path = "./crates/iana/", version = "=1.17.0-rc.0" }
|
||||
mas-iana-codegen = { path = "./crates/iana-codegen/", version = "=1.17.0-rc.0" }
|
||||
mas-jose = { path = "./crates/jose/", version = "=1.17.0-rc.0" }
|
||||
mas-keystore = { path = "./crates/keystore/", version = "=1.17.0-rc.0" }
|
||||
mas-listener = { path = "./crates/listener/", version = "=1.17.0-rc.0" }
|
||||
mas-matrix = { path = "./crates/matrix/", version = "=1.17.0-rc.0" }
|
||||
mas-matrix-synapse = { path = "./crates/matrix-synapse/", version = "=1.17.0-rc.0" }
|
||||
mas-oidc-client = { path = "./crates/oidc-client/", version = "=1.17.0-rc.0" }
|
||||
mas-policy = { path = "./crates/policy/", version = "=1.17.0-rc.0" }
|
||||
mas-router = { path = "./crates/router/", version = "=1.17.0-rc.0" }
|
||||
mas-spa = { path = "./crates/spa/", version = "=1.17.0-rc.0" }
|
||||
mas-storage = { path = "./crates/storage/", version = "=1.17.0-rc.0" }
|
||||
mas-storage-pg = { path = "./crates/storage-pg/", version = "=1.17.0-rc.0" }
|
||||
mas-tasks = { path = "./crates/tasks/", version = "=1.17.0-rc.0" }
|
||||
mas-templates = { path = "./crates/templates/", version = "=1.17.0-rc.0" }
|
||||
mas-tower = { path = "./crates/tower/", version = "=1.17.0-rc.0" }
|
||||
oauth2-types = { path = "./crates/oauth2-types/", version = "=1.17.0-rc.0" }
|
||||
syn2mas = { path = "./crates/syn2mas", version = "=1.17.0-rc.0" }
|
||||
mas-axum-utils = { path = "./crates/axum-utils/", version = "=1.17.0" }
|
||||
mas-cli = { path = "./crates/cli/", version = "=1.17.0" }
|
||||
mas-config = { path = "./crates/config/", version = "=1.17.0" }
|
||||
mas-context = { path = "./crates/context/", version = "=1.17.0" }
|
||||
mas-data-model = { path = "./crates/data-model/", version = "=1.17.0" }
|
||||
mas-email = { path = "./crates/email/", version = "=1.17.0" }
|
||||
mas-graphql = { path = "./crates/graphql/", version = "=1.17.0" }
|
||||
mas-handlers = { path = "./crates/handlers/", version = "=1.17.0" }
|
||||
mas-http = { path = "./crates/http/", version = "=1.17.0" }
|
||||
mas-i18n = { path = "./crates/i18n/", version = "=1.17.0" }
|
||||
mas-i18n-scan = { path = "./crates/i18n-scan/", version = "=1.17.0" }
|
||||
mas-iana = { path = "./crates/iana/", version = "=1.17.0" }
|
||||
mas-iana-codegen = { path = "./crates/iana-codegen/", version = "=1.17.0" }
|
||||
mas-jose = { path = "./crates/jose/", version = "=1.17.0" }
|
||||
mas-keystore = { path = "./crates/keystore/", version = "=1.17.0" }
|
||||
mas-listener = { path = "./crates/listener/", version = "=1.17.0" }
|
||||
mas-matrix = { path = "./crates/matrix/", version = "=1.17.0" }
|
||||
mas-matrix-synapse = { path = "./crates/matrix-synapse/", version = "=1.17.0" }
|
||||
mas-oidc-client = { path = "./crates/oidc-client/", version = "=1.17.0" }
|
||||
mas-policy = { path = "./crates/policy/", version = "=1.17.0" }
|
||||
mas-router = { path = "./crates/router/", version = "=1.17.0" }
|
||||
mas-spa = { path = "./crates/spa/", version = "=1.17.0" }
|
||||
mas-storage = { path = "./crates/storage/", version = "=1.17.0" }
|
||||
mas-storage-pg = { path = "./crates/storage-pg/", version = "=1.17.0" }
|
||||
mas-tasks = { path = "./crates/tasks/", version = "=1.17.0" }
|
||||
mas-templates = { path = "./crates/templates/", version = "=1.17.0" }
|
||||
mas-tower = { path = "./crates/tower/", version = "=1.17.0" }
|
||||
oauth2-types = { path = "./crates/oauth2-types/", version = "=1.17.0" }
|
||||
syn2mas = { path = "./crates/syn2mas", version = "=1.17.0" }
|
||||
|
||||
# OpenAPI schema generation and validation
|
||||
[workspace.dependencies.aide]
|
||||
|
||||
+13
-10
@@ -6,9 +6,9 @@
|
||||
# Please see LICENSE files in the repository root for full details.
|
||||
|
||||
# Builds a minimal image with the binary only. It is multi-arch capable,
|
||||
# cross-building to aarch64 and x86_64. When cross-compiling, Docker sets two
|
||||
# cross-building to aarch64 or x86_64. When cross-compiling, Docker sets two
|
||||
# implicit BUILDARG: BUILDPLATFORM being the host platform and TARGETPLATFORM
|
||||
# being the platform being built.
|
||||
# being the platform being built. Each architecture is built separately.
|
||||
|
||||
# The Debian version and version name must be in sync
|
||||
ARG DEBIAN_VERSION=13
|
||||
@@ -119,20 +119,25 @@ ENV SQLX_OFFLINE=true
|
||||
ARG VERGEN_GIT_DESCRIBE
|
||||
ENV VERGEN_GIT_DESCRIBE=${VERGEN_GIT_DESCRIBE}
|
||||
|
||||
ARG TARGETARCH
|
||||
|
||||
# Network access: cargo auditable needs it
|
||||
RUN --network=default \
|
||||
--mount=type=cache,target=/root/.cargo/registry \
|
||||
--mount=type=cache,target=/app/target \
|
||||
RUST_TARGET=$(case "${TARGETARCH}" in \
|
||||
amd64) echo "x86_64-unknown-linux-gnu" ;; \
|
||||
arm64) echo "aarch64-unknown-linux-gnu" ;; \
|
||||
*) echo "unsupported architecture: ${TARGETARCH}" >&2; exit 1 ;; \
|
||||
esac) && \
|
||||
cargo auditable build \
|
||||
--locked \
|
||||
--release \
|
||||
--bin mas-cli \
|
||||
--no-default-features \
|
||||
--features docker \
|
||||
--target x86_64-unknown-linux-gnu \
|
||||
--target aarch64-unknown-linux-gnu \
|
||||
&& mv "target/x86_64-unknown-linux-gnu/release/mas-cli" /usr/local/bin/mas-cli-amd64 \
|
||||
&& mv "target/aarch64-unknown-linux-gnu/release/mas-cli" /usr/local/bin/mas-cli-arm64
|
||||
--target "${RUST_TARGET}" \
|
||||
&& mv "target/${RUST_TARGET}/release/mas-cli" /usr/local/bin/mas-cli
|
||||
|
||||
#######################################
|
||||
## Prepare /usr/local/share/mas-cli/ ##
|
||||
@@ -149,8 +154,7 @@ COPY ./translations/ /share/translations
|
||||
##################################
|
||||
FROM gcr.io/distroless/cc-debian${DEBIAN_VERSION}:debug-nonroot AS debug
|
||||
|
||||
ARG TARGETARCH
|
||||
COPY --from=builder /usr/local/bin/mas-cli-${TARGETARCH} /usr/local/bin/mas-cli
|
||||
COPY --from=builder /usr/local/bin/mas-cli /usr/local/bin/mas-cli
|
||||
COPY --from=share /share /usr/local/share/mas-cli
|
||||
|
||||
WORKDIR /
|
||||
@@ -161,8 +165,7 @@ ENTRYPOINT ["/usr/local/bin/mas-cli"]
|
||||
###################
|
||||
FROM gcr.io/distroless/cc-debian${DEBIAN_VERSION}:nonroot
|
||||
|
||||
ARG TARGETARCH
|
||||
COPY --from=builder /usr/local/bin/mas-cli-${TARGETARCH} /usr/local/bin/mas-cli
|
||||
COPY --from=builder /usr/local/bin/mas-cli /usr/local/bin/mas-cli
|
||||
COPY --from=share /share /usr/local/share/mas-cli
|
||||
|
||||
WORKDIR /
|
||||
|
||||
@@ -457,6 +457,17 @@ pub(crate) async fn post(
|
||||
|
||||
// Now we can create the device on the homeserver, without holding the
|
||||
// transaction
|
||||
//
|
||||
// Normally, devices get synced to the homeserver in a `SyncDevicesJob` but we
|
||||
// want the device to be created synchronously on the homeserver, so that
|
||||
// when we respond, the access token works completely. If the device doesn't
|
||||
// exist on the homeserver side, token introspection from Synapse to MAS
|
||||
// will work but Synapse will return a 401 because it doesn't see the
|
||||
// device.
|
||||
//
|
||||
// We're using an upsert so if the device already exists for some reason (like
|
||||
// when we're replacing it, or a concurrent device sync happening) it won't
|
||||
// have any effect.
|
||||
if let Err(err) = homeserver
|
||||
.upsert_device(
|
||||
&user.username,
|
||||
@@ -499,28 +510,33 @@ pub(crate) async fn post(
|
||||
}))
|
||||
}
|
||||
|
||||
/// Given the violations from [`Policy::evaluate_compat_login`], return the
|
||||
/// appropriate `RouteError` response.
|
||||
/// Given the evaluation result/violations from
|
||||
/// [`Policy::evaluate_compat_login`], return the appropriate `RouteError`
|
||||
/// response.
|
||||
async fn process_violations_for_compat_login(
|
||||
rng: &mut (dyn RngCore + Send),
|
||||
clock: &dyn Clock,
|
||||
repo: &mut BoxRepository,
|
||||
session_limit_config: Option<&SessionLimitConfig>,
|
||||
user: &User,
|
||||
violations: Vec<Violation>,
|
||||
res: mas_policy::EvaluationResult,
|
||||
) -> Result<(), RouteError> {
|
||||
// We're using slice syntax here so we can match easily
|
||||
match &violations[..] {
|
||||
match (res.valid(), &res.violations[..]) {
|
||||
// If the only violation is having reached the session limit, we might be
|
||||
// able to resolve the situation.
|
||||
//
|
||||
// We don't trigger this if there was some other violation anyway, since
|
||||
// that means that removing a session wouldn't actually unblock the login.
|
||||
[
|
||||
Violation {
|
||||
variant: Some(ViolationVariant::TooManySessions { need_to_remove }),
|
||||
..
|
||||
},
|
||||
] => {
|
||||
(
|
||||
false,
|
||||
[
|
||||
Violation {
|
||||
variant: Some(ViolationVariant::TooManySessions { need_to_remove }),
|
||||
..
|
||||
},
|
||||
],
|
||||
) => {
|
||||
// Normally, if we are seeing a `TooManySessions` violation, we would
|
||||
// expect `session_limit_config` to be filled in but if someone created
|
||||
// their own policies which emit a `TooManySessions` violation that isn't
|
||||
@@ -596,6 +612,11 @@ async fn process_violations_for_compat_login(
|
||||
.finish(clock, compat_session.to_owned())
|
||||
.await?;
|
||||
}
|
||||
|
||||
// Schedule a device sync with the homeserver
|
||||
repo.queue_job()
|
||||
.schedule_job(rng, clock, SyncDevicesJob::new_for_id(user.id))
|
||||
.await?;
|
||||
} else {
|
||||
// Tell the user about the limit
|
||||
return Err(RouteError::PolicyHardSessionLimitReached);
|
||||
@@ -613,9 +634,9 @@ async fn process_violations_for_compat_login(
|
||||
}
|
||||
}
|
||||
// Nothing is wrong
|
||||
[] => return Ok(()),
|
||||
(true, _) => return Ok(()),
|
||||
// Just throw an error for any other violation
|
||||
_violations => {
|
||||
(false, _violations) => {
|
||||
// FIXME: We should be exposing the violations to the user
|
||||
return Err(RouteError::PolicyRejected);
|
||||
}
|
||||
@@ -840,11 +861,12 @@ async fn token_login(
|
||||
})
|
||||
.await?;
|
||||
process_violations_for_compat_login(
|
||||
rng,
|
||||
clock,
|
||||
repo,
|
||||
session_limit_config,
|
||||
&browser_session.user,
|
||||
res.violations,
|
||||
res,
|
||||
)
|
||||
.await?;
|
||||
|
||||
@@ -966,8 +988,7 @@ async fn user_password_login(
|
||||
requester: policy_requester,
|
||||
})
|
||||
.await?;
|
||||
process_violations_for_compat_login(clock, repo, session_limit_config, &user, res.violations)
|
||||
.await?;
|
||||
process_violations_for_compat_login(rng, clock, repo, session_limit_config, &user, res).await?;
|
||||
|
||||
let session = repo
|
||||
.compat_session()
|
||||
|
||||
@@ -117,13 +117,21 @@ pub(crate) async fn post(
|
||||
// XXX: this is probably not the right error
|
||||
.ok_or(RouteError::InvalidAuthorization)?;
|
||||
|
||||
// This will make the access token invalid
|
||||
repo.compat_session().finish(&clock, session).await?;
|
||||
|
||||
// Schedule a job to sync the devices of the user with the homeserver
|
||||
//
|
||||
// Doing this in a background job is ok as the access token will be invalid
|
||||
// right away (from the session being finished above) and we do actually
|
||||
// want to do a full device list sync (as opposed to
|
||||
// `homeserver.delete_device(...)`), because we're not sure whether we want
|
||||
// to delete the device (if there is for example a concurrent logout and
|
||||
// login with the same device ID).
|
||||
repo.queue_job()
|
||||
.schedule_job(&mut rng, &clock, SyncDevicesJob::new(&user))
|
||||
.await?;
|
||||
|
||||
repo.compat_session().finish(&clock, session).await?;
|
||||
|
||||
repo.save().await?;
|
||||
|
||||
LOGOUT_COUNTER.add(1, &[KeyValue::new(RESULT, "success")]);
|
||||
|
||||
@@ -573,6 +573,15 @@ async fn authorization_code_grant(
|
||||
// Look for device to provision
|
||||
for scope in &*session.scope {
|
||||
if let Some(device) = Device::from_scope_token(scope) {
|
||||
// Normally, devices get synced to the homeserver in a `SyncDevicesJob` but we
|
||||
// want the device to be created synchronously on the homeserver, so
|
||||
// that when we respond, the access token works completely. If the
|
||||
// device doesn't exist on the homeserver side, token introspection
|
||||
// from Synapse to MAS will work but Synapse will return a 401
|
||||
// because it doesn't see the device.
|
||||
//
|
||||
// We're using an upsert so if the device already exists for some reason
|
||||
// (like when a concurrent device sync happening) it won't have any effect.
|
||||
homeserver
|
||||
.upsert_device(
|
||||
&browser_session.user.username,
|
||||
@@ -977,6 +986,15 @@ async fn device_code_grant(
|
||||
// Look for device to provision
|
||||
for scope in &*session.scope {
|
||||
if let Some(device) = Device::from_scope_token(scope) {
|
||||
// Normally, devices get synced to the homeserver in a `SyncDevicesJob` but we
|
||||
// want the device to be created synchronously on the homeserver, so
|
||||
// that when we respond, the access token works completely. If the
|
||||
// device doesn't exist on the homeserver side, token introspection
|
||||
// from Synapse to MAS will work but Synapse will return a 401
|
||||
// because it doesn't see the device.
|
||||
//
|
||||
// We're using an upsert so if the device already exists for some reason
|
||||
// (like when a concurrent device sync happening) it won't have any effect.
|
||||
homeserver
|
||||
.upsert_device(&browser_session.user.username, device.as_str(), None)
|
||||
.await
|
||||
|
||||
+3
-7
@@ -1,3 +1,4 @@
|
||||
# Copyright 2025, 2026 Element Creations Ltd.
|
||||
# Copyright 2025 New Vector Ltd.
|
||||
#
|
||||
# SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
@@ -15,8 +16,8 @@ group "default" { targets = ["regular", "debug"] }
|
||||
target "docker-metadata-action" {}
|
||||
target "docker-metadata-action-debug" {}
|
||||
|
||||
// This sets the platforms and is further extended by GitHub Actions to set the
|
||||
// output and the cache locations
|
||||
// This is extended by GitHub Actions to set the output, cache locations,
|
||||
// and platforms (one architecture per job for parallel builds)
|
||||
target "base" {
|
||||
args = {
|
||||
// This is set so that when we use a git context, the .git directory is
|
||||
@@ -26,11 +27,6 @@ target "base" {
|
||||
// Pass down the version from an external git describe source
|
||||
VERGEN_GIT_DESCRIBE = "${VERGEN_GIT_DESCRIBE}"
|
||||
}
|
||||
|
||||
platforms = [
|
||||
"linux/amd64",
|
||||
"linux/arm64",
|
||||
]
|
||||
}
|
||||
|
||||
target "regular" {
|
||||
|
||||
@@ -27,7 +27,7 @@ export type LocalazyMetadata = {
|
||||
};
|
||||
|
||||
const localazyMetadata: LocalazyMetadata = {
|
||||
projectUrl: "https://localazy.com/p/matrix-authentication-service",
|
||||
projectUrl: "https://localazy.com/p/matrix-authentication-service!v1.17",
|
||||
baseLocale: "en",
|
||||
languages: [
|
||||
{
|
||||
@@ -208,25 +208,25 @@ const localazyMetadata: LocalazyMetadata = {
|
||||
file: "frontend.json",
|
||||
path: "",
|
||||
cdnFiles: {
|
||||
"cs": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/cs/frontend.json",
|
||||
"da": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/da/frontend.json",
|
||||
"de": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/de/frontend.json",
|
||||
"en": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/en/frontend.json",
|
||||
"et": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/et/frontend.json",
|
||||
"fi": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/fi/frontend.json",
|
||||
"fr": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/fr/frontend.json",
|
||||
"hu": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/hu/frontend.json",
|
||||
"nb_NO": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/nb-NO/frontend.json",
|
||||
"nl": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/nl/frontend.json",
|
||||
"pl": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/pl/frontend.json",
|
||||
"pt": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/pt/frontend.json",
|
||||
"pt_BR": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/pt-BR/frontend.json",
|
||||
"ru": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/ru/frontend.json",
|
||||
"sk": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/sk/frontend.json",
|
||||
"sv": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/sv/frontend.json",
|
||||
"uk": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/uk/frontend.json",
|
||||
"uz": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/uz/frontend.json",
|
||||
"zh#Hans": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/zh-Hans/frontend.json"
|
||||
"cs": "https://delivery.localazy.com/_a65347067752521597762935bd1b/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/cs/frontend.json",
|
||||
"da": "https://delivery.localazy.com/_a65347067752521597762935bd1b/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/da/frontend.json",
|
||||
"de": "https://delivery.localazy.com/_a65347067752521597762935bd1b/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/de/frontend.json",
|
||||
"en": "https://delivery.localazy.com/_a65347067752521597762935bd1b/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/en/frontend.json",
|
||||
"et": "https://delivery.localazy.com/_a65347067752521597762935bd1b/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/et/frontend.json",
|
||||
"fi": "https://delivery.localazy.com/_a65347067752521597762935bd1b/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/fi/frontend.json",
|
||||
"fr": "https://delivery.localazy.com/_a65347067752521597762935bd1b/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/fr/frontend.json",
|
||||
"hu": "https://delivery.localazy.com/_a65347067752521597762935bd1b/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/hu/frontend.json",
|
||||
"nb_NO": "https://delivery.localazy.com/_a65347067752521597762935bd1b/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/nb-NO/frontend.json",
|
||||
"nl": "https://delivery.localazy.com/_a65347067752521597762935bd1b/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/nl/frontend.json",
|
||||
"pl": "https://delivery.localazy.com/_a65347067752521597762935bd1b/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/pl/frontend.json",
|
||||
"pt": "https://delivery.localazy.com/_a65347067752521597762935bd1b/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/pt/frontend.json",
|
||||
"pt_BR": "https://delivery.localazy.com/_a65347067752521597762935bd1b/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/pt-BR/frontend.json",
|
||||
"ru": "https://delivery.localazy.com/_a65347067752521597762935bd1b/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/ru/frontend.json",
|
||||
"sk": "https://delivery.localazy.com/_a65347067752521597762935bd1b/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/sk/frontend.json",
|
||||
"sv": "https://delivery.localazy.com/_a65347067752521597762935bd1b/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/sv/frontend.json",
|
||||
"uk": "https://delivery.localazy.com/_a65347067752521597762935bd1b/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/uk/frontend.json",
|
||||
"uz": "https://delivery.localazy.com/_a65347067752521597762935bd1b/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/uz/frontend.json",
|
||||
"zh#Hans": "https://delivery.localazy.com/_a65347067752521597762935bd1b/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/zh-Hans/frontend.json"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -234,25 +234,25 @@ const localazyMetadata: LocalazyMetadata = {
|
||||
file: "file.json",
|
||||
path: "",
|
||||
cdnFiles: {
|
||||
"cs": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/cs/file.json",
|
||||
"da": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/da/file.json",
|
||||
"de": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/de/file.json",
|
||||
"en": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/en/file.json",
|
||||
"et": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/et/file.json",
|
||||
"fi": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/fi/file.json",
|
||||
"fr": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/fr/file.json",
|
||||
"hu": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/hu/file.json",
|
||||
"nb_NO": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/nb-NO/file.json",
|
||||
"nl": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/nl/file.json",
|
||||
"pl": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/pl/file.json",
|
||||
"pt": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/pt/file.json",
|
||||
"pt_BR": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/pt-BR/file.json",
|
||||
"ru": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/ru/file.json",
|
||||
"sk": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/sk/file.json",
|
||||
"sv": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/sv/file.json",
|
||||
"uk": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/uk/file.json",
|
||||
"uz": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/uz/file.json",
|
||||
"zh#Hans": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/zh-Hans/file.json"
|
||||
"cs": "https://delivery.localazy.com/_a65347067752521597762935bd1b/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/cs/file.json",
|
||||
"da": "https://delivery.localazy.com/_a65347067752521597762935bd1b/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/da/file.json",
|
||||
"de": "https://delivery.localazy.com/_a65347067752521597762935bd1b/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/de/file.json",
|
||||
"en": "https://delivery.localazy.com/_a65347067752521597762935bd1b/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/en/file.json",
|
||||
"et": "https://delivery.localazy.com/_a65347067752521597762935bd1b/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/et/file.json",
|
||||
"fi": "https://delivery.localazy.com/_a65347067752521597762935bd1b/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/fi/file.json",
|
||||
"fr": "https://delivery.localazy.com/_a65347067752521597762935bd1b/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/fr/file.json",
|
||||
"hu": "https://delivery.localazy.com/_a65347067752521597762935bd1b/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/hu/file.json",
|
||||
"nb_NO": "https://delivery.localazy.com/_a65347067752521597762935bd1b/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/nb-NO/file.json",
|
||||
"nl": "https://delivery.localazy.com/_a65347067752521597762935bd1b/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/nl/file.json",
|
||||
"pl": "https://delivery.localazy.com/_a65347067752521597762935bd1b/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/pl/file.json",
|
||||
"pt": "https://delivery.localazy.com/_a65347067752521597762935bd1b/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/pt/file.json",
|
||||
"pt_BR": "https://delivery.localazy.com/_a65347067752521597762935bd1b/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/pt-BR/file.json",
|
||||
"ru": "https://delivery.localazy.com/_a65347067752521597762935bd1b/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/ru/file.json",
|
||||
"sk": "https://delivery.localazy.com/_a65347067752521597762935bd1b/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/sk/file.json",
|
||||
"sv": "https://delivery.localazy.com/_a65347067752521597762935bd1b/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/sv/file.json",
|
||||
"uk": "https://delivery.localazy.com/_a65347067752521597762935bd1b/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/uk/file.json",
|
||||
"uz": "https://delivery.localazy.com/_a65347067752521597762935bd1b/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/uz/file.json",
|
||||
"zh#Hans": "https://delivery.localazy.com/_a65347067752521597762935bd1b/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/zh-Hans/file.json"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user