Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
15 changes: 8 additions & 7 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ name: Build
on:
push:
branches:
- main
- main_tchap
- "release/**"
- "test/**"
tags:
- "v*"

Expand All @@ -22,9 +23,9 @@ env:
CARGO_NET_GIT_FETCH_WITH_CLI: "true"
SCCACHE_GHA_ENABLED: "true"
RUSTC_WRAPPER: "sccache"
IMAGE: ghcr.io/element-hq/matrix-authentication-service
IMAGE_SYN2MAS: ghcr.io/element-hq/matrix-authentication-service/syn2mas
BUILDCACHE: ghcr.io/element-hq/matrix-authentication-service/buildcache
IMAGE: ghcr.io/tchapgouv/matrix-authentication-service
IMAGE_SYN2MAS: ghcr.io/tchapgouv/matrix-authentication-service/syn2mas
BUILDCACHE: ghcr.io/tchapgouv/matrix-authentication-service/buildcache
DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index

jobs:
Expand Down Expand Up @@ -313,7 +314,7 @@ jobs:
# Only sign on tags and on commits on main branch
if: |
github.event_name != 'pull_request'
&& (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main')
&& (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main_tchap')

env:
REGULAR_DIGEST: ${{ steps.output.outputs.metadata && fromJSON(steps.output.outputs.metadata).regular.digest }}
Expand All @@ -329,7 +330,7 @@ jobs:
syn2mas:
name: Release syn2mas on NPM
runs-on: ubuntu-24.04
if: github.event_name != 'pull_request'
if: 'false'

permissions:
contents: read
Expand Down Expand Up @@ -422,7 +423,7 @@ jobs:

unstable:
name: Update the unstable release
if: github.ref == 'refs/heads/main'
if: github.ref == 'refs/heads/main_tchap'
runs-on: ubuntu-24.04

needs:
Expand Down
17 changes: 17 additions & 0 deletions policies/register/identity.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package identity

headers = {
"Content-Type": "application/json",
"Accept": "application/json"
}

url = sprintf("%s?medium=%s&address=%s", [data.external_service.url, "email", input.email])


get_identity_info = http.send(
{
"method": "get",
"url": url,
"headers": headers
}
)
70 changes: 70 additions & 0 deletions policies/register/register.rego
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@
package register

import rego.v1
import data.identity

import data.common
import data.email as email_policy
import future.keywords.contains
import future.keywords.if
import future.keywords.in

default allow := false

Expand Down Expand Up @@ -92,3 +96,69 @@ violation contains object.union({"field": "email"}, v) if {
# Get the violation object from the email policy
some v in email_policy.violation
}


# Violation for email on wrong homeserver
violation contains {
"field": "email",
"code": "email-wrong-homeserver",
"msg": "email is registered on a different homeserver"
} if {
# Check if email is present
input.email

# Check if external service configuration exists
data.external_service

# Get API response
identity_info_json := identity.get_identity_info

# Check if "hs" is present in the response
"hs" in identity_info_json

# Check if the hs does NOT match the server_name
identity_info_json.hs != data.server_name
}

# Violation for email requiring invitation
violation contains {
"field": "email",
"code": "email-invitation-required",
"msg": "invitation required for this email"
} if {
# Check if email is present
input.email

# Check if external service configuration exists
data.external_service

# Get API response
identity_info_json := identity.get_identity_info

# Check if "hs" is present and matches server_name
"hs" in identity_info_json
identity_info_json.hs == data.server_name

# Check if requires_invite is true and invited is false
identity_info_json.requires_invite == true
identity_info_json.invited == false
}

# Violation for email with missing hs field
violation contains {
"field": "email",
"code": "email-invalid-response",
"msg": "invalid response from identity server"
} if {
# Check if email is present
input.email

# Check if external service configuration exists
data.external_service

# Get API response
identity_info_json := identity.get_identity_info

# Check if "hs" is NOT present in the response
not "hs" in identity_info_json
}
50 changes: 50 additions & 0 deletions policies/register/register_test.rego
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package register_test

import data.register
import rego.v1
import future.keywords.if
import future.keywords.in

mock_registration := {
"registration_method": "password",
Expand Down Expand Up @@ -111,3 +113,51 @@ test_ip_ban if {
}
with data.requester.banned_user_agents.substrings as ["Evil"]
}

# Test external service allowing registration
test_external_service_allowed if {
# Create a test input with only the necessary fields
test_input := {
"username": "hello",
"email": "[email protected]",
"registration_method": "password",
}

register.allow with input as test_input
with as {
"url": "https://matrix.agent.agriculture.tchap.gouv.fr/_matrix/identity/api/v1/info"
}
with data.server_name as "matrix.org"
}

mock_http_missing_hs_response(request) = response if {
response := {
"status_code": 200,
"body": {
"invited": true,
"requires_invite": false
}
}
}

mock_http_wrong_hs_response(request) = response if {
response := {
"status_code": 200,
"body": {
"hs": "wrong.org",
"invited": true,
"requires_invite": false
}
}
}

mock_http_requires_invite_response(request) = response if {
response := {
"status_code": 200,
"body": {
"hs": "matrix.org",
"invited": false,
"requires_invite": true
}
}
}
Loading