Skip to content

Commit 5b26abd

Browse files
authored
Add integration tests for authorization (#130)
Added integration tests for the authorization functionality of the Zenoh transport. The tests cover scenarios for both authorized and unauthorized clients, ensuring that the authorization mechanism works as expected. The tests also verify that the access control configuration is correctly applied, and that clients can only publish and subscribe to topics they are authorized to access. Also changed CI jobs to no longer use nextest, as it is not compatible with the test-serial crate, which is used for the authorization integration tests.
1 parent 21dc2cc commit 5b26abd

11 files changed

Lines changed: 431 additions & 56 deletions

File tree

.github/workflows/check.yaml

Lines changed: 16 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,7 @@ on:
2828
outputs:
2929
test_results_url:
3030
description: "URL of the test results artifact"
31-
value: ${{ jobs.nextest.outputs.test_results_url }}
32-
doctest_results_url:
33-
description: "URL of the doctest results artifact"
34-
value: ${{ jobs.doctest.outputs.test_results_url }}
31+
value: ${{ jobs.test.outputs.test_results_url }}
3532
workflow_dispatch:
3633

3734
concurrency:
@@ -120,51 +117,34 @@ jobs:
120117
with:
121118
args: "--cache --max-cache-age 1d --verbose --no-progress --exclude-path './target/' --exclude-path './up-spec/' -- './**/*.md' './**/*.rs' './**/*.adoc'"
122119

123-
nextest:
120+
test:
121+
# Subset of feature-combos, on only one OS - more complete testing in test-featurematrix.yaml
124122
outputs:
125123
test_results_url: ${{ steps.test_results.outputs.artifact-url }}
126124
runs-on: ubuntu-latest
127-
env:
128-
NEXTEST_EXPERIMENTAL_LIBTEST_JSON: 1
125+
strategy:
126+
matrix:
127+
feature-flags: ["", "--no-default-features", "--all-features"]
129128
steps:
130129
- uses: actions/checkout@v4
131130
with:
132131
submodules: "recursive"
133132
- uses: dtolnay/rust-toolchain@master
134133
with:
135134
toolchain: ${{ env.RUST_TOOLCHAIN }}
136-
- uses: Swatinem/rust-cache@v2
137-
# Using nextest because it's faster than built-in test
138-
- uses: taiki-e/install-action@nextest
139-
- name: Run cargo nextest
135+
- name: Run lib tests
140136
run: |
141-
cargo nextest run --message-format libtest-json-plus > testresults.json
137+
mkdir -p ${GITHUB_WORKSPACE}/target
138+
RUSTC_BOOTSTRAP=1 cargo test --no-fail-fast --all-targets ${{ matrix.feature-flags }} -- -Z unstable-options --format junit --report-time > ${GITHUB_WORKSPACE}/target/lib-test-results.xml
139+
- name: Run doc tests
140+
run: |
141+
RUSTC_BOOTSTRAP=1 cargo test --no-fail-fast --doc ${{ matrix.feature-flags }} -- -Z unstable-options --format junit --report-time > ${GITHUB_WORKSPACE}/target/doc-test-results.xml
142+
142143
- name: Upload all-features test results artifact
143144
id: test_results
145+
if: matrix.feature-flags == '--all-features'
144146
uses: actions/upload-artifact@v4
145147
with:
146148
name: test-results
147-
path: testresults.json
148-
149-
doctest:
150-
# Run doctests separately, as nextest doesn't yet (https://github.com/nextest-rs/nextest/issues/16)
151-
outputs:
152-
test_results_url: ${{ steps.doctest_results.outputs.artifact-url }}
153-
runs-on: ubuntu-latest
154-
env:
155-
RUSTDOCFLAGS: -Dwarnings
156-
steps:
157-
- uses: actions/checkout@v4
158-
with:
159-
submodules: "recursive"
160-
- uses: dtolnay/rust-toolchain@master
161-
with:
162-
toolchain: ${{ env.RUST_TOOLCHAIN }}
163-
- name: Run doc tests
164-
run: |
165-
RUSTC_BOOTSTRAP=1 cargo test --doc --all-features -- -Z unstable-options --format json --report-time > doctestresults--all-features.json
166-
- name: Upload doctest results artifact
167-
uses: actions/upload-artifact@v4
168-
with:
169-
name: doctest-results
170-
path: doctestresults--all-features.json
149+
# include all test result files
150+
path: target/*-results.xml

.github/workflows/latest-up-spec-compatibility.yaml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,9 @@ jobs:
6969
with:
7070
toolchain: ${{ env.RUST_TOOLCHAIN }}
7171
- uses: Swatinem/rust-cache@v2
72-
- uses: taiki-e/install-action@nextest
7372
- name: Run tests
7473
run: |
75-
# Using nextest because it's faster than built-in test
76-
cargo nextest run --all-features
77-
# but it cannot execute doc tests
78-
cargo test --doc --all-features
74+
cargo test --all-features
7975
8076
# This step will only be run if the tests in the previous step have succeeded.
8177
# In that case, we use the exit code produced by the OFT run as the job's

Cargo.lock

Lines changed: 75 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ zenoh = { version = "1.5.0" }
4545
chrono = "0.4.41"
4646
clap = { version = "4.5.40", features = ["derive"] }
4747
serde_json = "1.0.128"
48+
serial_test = { version = "3.2.0" }
4849
test-case = { version = "3.3" }
4950
tokio = { version = "1.45.1", default-features = false, features = ["rt-multi-thread", "signal"] }
5051
tracing-subscriber = "0.3.19"

README.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,14 @@ Covers:
7878
### Authentication & Authorization
7979
`uman~auth-configuration~1`
8080

81-
The transport provided by this crate can be configured with credentials that the transport will provide to the Zenoh router during connection establishment. A [_username_ and _password_](https://zenoh.io/docs/manual/user-password/) can be specified in the Zenoh config file that is passed into the `UPTransportZenoh::new` function to create a new transport instance.
81+
The transport provided by this crate can be configured with credentials that the transport will provide to the Zenoh router during connection establishment. A [_username_ and _password_](https://zenoh.io/docs/manual/user-password/) can be specified in the Zenoh config file that is passed into the `UPTransportZenohBuilder::with_config_file` function.
8282

83-
Access to resources can be configured in the Zenoh config file by means of [Access Control Lists](https://zenoh.io/docs/manual/access-control/).
83+
Access to resources can be configured in the Zenoh (peer's or router's) config file by means of [Access Control Lists](https://zenoh.io/docs/manual/access-control/).
84+
The [authorization integration tests](./tests/authorization.rs) illustrate, how ACLs can be used to restrict a client's authority to put and subscribe to messages using corresponding rule sets.
8485

8586
Covers:
86-
- `req~utransport-send-error-permission-denied~2`
87+
- `req~utransport-send-prevent-address-spoofing~1`
88+
- `req~utransport-registerlistener-prevent-unauthorized-access~1`
8789

8890
### Maximum number of listeners
8991
`uman~max-listeners-configuration~1`
@@ -116,15 +118,16 @@ Needs: impl, itest
116118

117119
In general, uProtocol entities are only allowed to send messages on their own behalf. Certain specific uEntities acting as a uProtocol Streamer also need to send messages _on behalf of_ other uEntities in order to fulfill their original purpose of routing messages hence and forth between different transports. Making these authoritzation decisions requires the (proven) establishment of an _identity_ and its _authorities_.
118120

119-
The Zenoh transport delegates all authorization decisions to the Zenoh router that the transport is configured to connect to. For this purpose, the transport supports configuration of credentials which are being used during connection establishment. The Zenoh router uses the provided credentials to establish the client's identity and its associated authorities. Whenever the uEntity sends a message via the router or registers a subscriber for a key pattern, the router verifies, if the client is authorized to publish using the key or receive messages matching the key pattern.
121+
The Zenoh transport delegates all authorization decisions to the Zenoh router (or peer) that the transport is configured to connect to. For this purpose, the transport supports configuration of credentials which are being used during connection establishment. The Zenoh router uses the provided credentials to establish the client's identity and its associated authorities. Whenever the uEntity sends a message via the router or registers a subscriber for a key pattern, the router verifies that the client is authorized to publish using the key or receive messages matching the key pattern.
120122

121123
Rationale:
122124
The Zenoh transport is implemented as a library that is linked to the (custom) code that implements a uEntity's functionality. It is therefore not feasible to perform the authentication and authoritzation within the transport library code, because uEntities can not be forced to actually utilize one of uProtocol's transport libraries but may instead chooose to implement the binding to the transport protocol themselves.
123125

124126
Covers:
125-
- `req~utransport-send-error-permission-denied~2`
127+
- `req~utransport-send-prevent-address-spoofing~1`
128+
- `req~utransport-registerlistener-prevent-unauthorized-access~1`
126129

127-
Needs: impl, utest
130+
Needs: itest
128131

129132
## Change Log
130133

src/utransport.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use async_trait::async_trait;
1515
use bytes::Bytes;
1616
use protobuf::Message;
1717
use std::sync::Arc;
18-
use tracing::{debug, error};
18+
use tracing::{debug, error, trace};
1919
use up_rust::{
2020
ComparableListener, UAttributes, UAttributesValidators, UCode, UListener, UMessage, UPriority,
2121
UStatus, UTransport, UUri,
@@ -125,6 +125,7 @@ impl UPTransportZenoh {
125125
// [impl->dsn~up-transport-zenoh-attributes-mapping~1]
126126
.attachment(attachment)
127127
.await
128+
.inspect(|()| trace!("putting message with key: {zenoh_key}"))
128129
.map_err(|e| {
129130
UStatus::fail_with_code(
130131
UCode::INTERNAL,

0 commit comments

Comments
 (0)