Skip to content

Commit e37456b

Browse files
authored
Only allow C-S device scopes when the C-S API scope has been requested (#5215)
2 parents 0f2b32c + 58ffe37 commit e37456b

File tree

4 files changed

+60
-14
lines changed

4 files changed

+60
-14
lines changed

docs/development/contributing.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ Make sure your code adheres to our Rust and TypeScript code style by running:
7272

7373
- `cargo +nightly fmt` (with the nightly toolchain installed)
7474
- `npm run format` in the `frontend` directory
75+
- `make fmt` in the `policies` directory (if changed)
7576

7677
When updating SQL queries in the `crates/storage-pg/` crate, you may need to update the `sqlx` introspection data. To do this, make sure to install `cargo-sqlx` (`cargo install sqlx-cli`) and:
7778

@@ -86,13 +87,18 @@ While you're developing and before submitting a patch, you'll want to test your
8687

8788
- Run `cargo clippy --workspace` to lint the Rust code.
8889
- Run `npm run lint` in the `frontend` directory to lint the frontend code.
90+
- Run `make fmt` and `make lint` in the `policies` directory to format and lint the included policy.
8991

9092
### Run the tests
9193

9294
If you haven't already, install [Cargo-Nextest](https://nexte.st/docs/installation/pre-built-binaries/).
9395

9496
- Run the tests to the backend by running `cargo nextest run --workspace`. This requires a connection to a PostgreSQL database, set via the `DATABASE_URL` environment variable.
9597
- Run the tests to the frontend by running `npm run test` in the `frontend` directory.
98+
- To run the tests for the included policy, change to the `policies` directory and run one of:
99+
- `make test` (needs Open Policy Agent installed)
100+
- `make PODMAN=1 test` (runs inside a container; needs Podman installed)
101+
- `make DOCKER=1 test` (runs inside a container; needs Docker installed)
96102

97103
## 8. Submit a pull request
98104

policies/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ ifeq ($(DOCKER), 1)
2424
REGAL := docker run -i -v $(shell pwd):/policies:ro -w /policies --rm $(REGAL_DOCKER_IMAGE)
2525
else ifeq ($(PODMAN), 1)
2626
# When running rootless, the volume directory may need to be given global write permissions on the host
27-
OPA := podman run -i -v $(shell pwd):/policies:ro:Z -w /policies --rm $(OPA_DOCKER_IMAGE)
27+
OPA := podman run -i -v $(shell pwd):/policies:ro,Z -w /policies --rm $(OPA_DOCKER_IMAGE)
2828
OPA_RW := podman run -i -v $(shell pwd):/policies:Z -w /policies --rm $(OPA_DOCKER_IMAGE)
29-
REGAL := podman run -i -v $(shell pwd):/policies:ro:Z -w /policies --rm $(REGAL_DOCKER_IMAGE)
29+
REGAL := podman run -i -v $(shell pwd):/policies:ro,Z -w /policies --rm $(REGAL_DOCKER_IMAGE)
3030
else
3131
OPA := opa
3232
OPA_RW := opa

policies/authorization_grant/authorization_grant.rego

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,26 @@ uses_stable_scopes if {
9898
count({scope | some scope in scope_list; startswith(scope, "urn:matrix:client:")}) > 0
9999
}
100100

101+
has_device_scope if {
102+
scope_list := split(input.scope, " ")
103+
count({scope | some scope in scope_list; startswith(scope, "urn:matrix:client:device:")}) > 0
104+
}
105+
106+
has_device_scope if {
107+
scope_list := split(input.scope, " ")
108+
count({scope | some scope in scope_list; startswith(scope, "urn:matrix:org.matrix.msc2967.client:device:")}) > 0
109+
}
110+
111+
has_cs_api_scope if {
112+
scope_list := split(input.scope, " ")
113+
count({scope | some scope in scope_list; startswith(scope, "urn:matrix:client:api:")}) > 0
114+
}
115+
116+
has_cs_api_scope if {
117+
scope_list := split(input.scope, " ")
118+
count({scope | some scope in scope_list; startswith(scope, "urn:matrix:org.matrix.msc2967.client:api:")}) > 0
119+
}
120+
101121
# METADATA
102122
# entrypoint: true
103123
violation contains {"msg": msg} if {
@@ -116,6 +136,12 @@ violation contains {"msg": "only one device scope is allowed at a time"} if {
116136
count({scope | some scope in scope_list; startswith(scope, "urn:matrix:client:device:")}) > 1
117137
}
118138

139+
# Prevent the creation of C-S API devices for sessions that don't have C-S API access.
140+
violation contains {"msg": "device scopes are only allowed when the client-server API scope is requested"} if {
141+
has_device_scope
142+
not has_cs_api_scope
143+
}
144+
119145
violation contains {"msg": "request cannot mix unstable and stable scopes"} if {
120146
uses_stable_scopes
121147
uses_unstable_scopes

policies/authorization_grant/authorization_grant_test.rego

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -78,70 +78,84 @@ test_unstable_device_scopes if {
7878
authorization_grant.allow with input.user as user
7979
with input.client as client
8080
with input.grant_type as "authorization_code"
81-
with input.scope as "urn:matrix:org.matrix.msc2967.client:device:AAbbCCdd01"
81+
with input.scope as "urn:matrix:org.matrix.msc2967.client:api:* urn:matrix:org.matrix.msc2967.client:device:AAbbCCdd01"
8282

8383
authorization_grant.allow with input.user as user
8484
with input.client as client
8585
with input.grant_type as "authorization_code"
86-
with input.scope as "urn:matrix:org.matrix.msc2967.client:device:AAbbCCdd01-asdasdsa1-2313"
86+
with input.scope as "urn:matrix:org.matrix.msc2967.client:api:* urn:matrix:org.matrix.msc2967.client:device:AAbbCCdd01-asdasdsa1-2313"
8787

8888
# Too short
8989
not authorization_grant.allow with input.user as user
9090
with input.client as client
9191
with input.grant_type as "authorization_code"
92-
with input.scope as "urn:matrix:org.matrix.msc2967.client:device:abcd"
92+
with input.scope as "urn:matrix:org.matrix.msc2967.client:api:* urn:matrix:org.matrix.msc2967.client:device:abcd"
9393

9494
# Multiple device scope
9595
not authorization_grant.allow with input.user as user
9696
with input.client as client
9797
with input.grant_type as "authorization_code"
98-
with input.scope as "urn:matrix:org.matrix.msc2967.client:device:AAbbCCdd01 urn:matrix:org.matrix.msc2967.client:device:AAbbCCdd02"
98+
with input.scope as "urn:matrix:org.matrix.msc2967.client:api:* urn:matrix:org.matrix.msc2967.client:device:AAbbCCdd01 urn:matrix:org.matrix.msc2967.client:device:AAbbCCdd02"
9999

100100
# Allowed with the device code grant
101101
authorization_grant.allow with input.user as user
102102
with input.client as client
103103
with input.grant_type as "urn:ietf:params:oauth:grant-type:device_code"
104-
with input.scope as "urn:matrix:org.matrix.msc2967.client:device:AAbbCCdd01"
104+
with input.scope as "urn:matrix:org.matrix.msc2967.client:api:* urn:matrix:org.matrix.msc2967.client:device:AAbbCCdd01"
105105

106106
# Not authorization_grant.allowed for the client credentials grant
107107
not authorization_grant.allow with input.client as client
108108
with input.grant_type as "client_credentials"
109-
with input.scope as "urn:matrix:org.matrix.msc2967.client:device:AAbbCCdd01"
109+
with input.scope as "urn:matrix:org.matrix.msc2967.client:api:* urn:matrix:org.matrix.msc2967.client:device:AAbbCCdd01"
110110
}
111111

112112
test_stable_device_scopes if {
113113
authorization_grant.allow with input.user as user
114114
with input.client as client
115115
with input.grant_type as "authorization_code"
116-
with input.scope as "urn:matrix:client:device:AAbbCCdd01"
116+
with input.scope as "urn:matrix:client:api:* urn:matrix:client:device:AAbbCCdd01"
117117

118118
authorization_grant.allow with input.user as user
119119
with input.client as client
120120
with input.grant_type as "authorization_code"
121-
with input.scope as "urn:matrix:client:device:AAbbCCdd01-asdasdsa1-2313"
121+
with input.scope as "urn:matrix:client:api:* urn:matrix:client:device:AAbbCCdd01-asdasdsa1-2313"
122122

123123
# Too short
124124
not authorization_grant.allow with input.user as user
125125
with input.client as client
126126
with input.grant_type as "authorization_code"
127-
with input.scope as "urn:matrix:client:device:abcd"
127+
with input.scope as "urn:matrix:client:api:* urn:matrix:client:device:abcd"
128128

129129
# Multiple device scope
130130
not authorization_grant.allow with input.user as user
131131
with input.client as client
132132
with input.grant_type as "authorization_code"
133-
with input.scope as "urn:matrix:client:device:AAbbCCdd01 urn:matrix:client:device:AAbbCCdd02"
133+
with input.scope as "urn:matrix:client:api:* urn:matrix:client:device:AAbbCCdd01 urn:matrix:client:device:AAbbCCdd02"
134134

135135
# Allowed with the device code grant
136136
authorization_grant.allow with input.user as user
137137
with input.client as client
138138
with input.grant_type as "urn:ietf:params:oauth:grant-type:device_code"
139-
with input.scope as "urn:matrix:client:device:AAbbCCdd01"
139+
with input.scope as "urn:matrix:client:api:* urn:matrix:client:device:AAbbCCdd01"
140140

141141
# Not authorization_grant.allowed for the client credentials grant
142142
not authorization_grant.allow with input.client as client
143143
with input.grant_type as "client_credentials"
144-
with input.scope as "urn:matrix:client:device:AAbbCCdd01"
144+
with input.scope as "urn:matrix:client:api:* urn:matrix:client:device:AAbbCCdd01"
145+
}
146+
147+
test_device_scope_only_with_cs_api_scope if {
148+
not authorization_grant.allow with input.user as user
149+
with input.client as client
150+
with input.grant_type as "authorization_code"
151+
# Requested a device scope but no C-S API scope:
152+
with input.scope as "urn:matrix:client:device:AAbbCCdd01"
153+
154+
not authorization_grant.allow with input.user as user
155+
with input.client as client
156+
with input.grant_type as "authorization_code"
157+
# Requested a device scope but no C-S API scope:
158+
with input.scope as "urn:matrix:org.matrix.msc2967.client:device:AAbbCCdd01"
145159
}
146160

147161
test_mix_stable_and_unstable_scopes if {

0 commit comments

Comments
 (0)