Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update ACL config format to support AND/OR logic between subjects #1200

Merged
merged 39 commits into from
Jul 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
d74c363
Add trie dependency
oteffahi Jun 25, 2024
1cb434c
Start replacing subject HashMap with TrieMap
oteffahi Jun 25, 2024
90aeeb0
Complete SubjectTrieMap implementation
oteffahi Jun 26, 2024
5d3ffed
Add new ACL config schema to zenoh config
oteffahi Jun 26, 2024
3f3a959
Add new ACL config parsing logic
oteffahi Jun 27, 2024
1c6e1bb
Fix empty subject lists edge-case for cartesian product of subjects
oteffahi Jun 27, 2024
47cf0e6
Format code, apply clippy suggestions
oteffahi Jun 27, 2024
2983820
Fix edge-case where a subject-combination is repeated in config
oteffahi Jun 27, 2024
b226821
Update new transport ACL logic with subject-combinations support
oteffahi Jun 27, 2024
d56a0da
Make ACL config lists mandatory when ACL config is enabled
oteffahi Jun 28, 2024
3f3a4b1
Update ACL tests
oteffahi Jun 28, 2024
0ca0d2e
Update authentication tests
oteffahi Jun 28, 2024
a1a654e
Break ACL and authentication test into multiple tests that can run co…
oteffahi Jun 28, 2024
9354a08
Fix entry_id value in error message
oteffahi Jun 28, 2024
c95bbc9
Add policy entry rules/subjects id validation
oteffahi Jun 28, 2024
f19ee28
Update DEFAULT_CONFIG
oteffahi Jun 28, 2024
9498076
Fix missing port number in test client config
oteffahi Jun 28, 2024
16663b9
Add ACL subject combination tests
oteffahi Jun 28, 2024
d442802
Empty commit to trigger CI
oteffahi Jun 28, 2024
8e34a00
Fix unsoundness in `SubjectMap`
fuzzypixelz Jul 17, 2024
0b4bb3f
Address review comments from original pull request
fuzzypixelz Jul 18, 2024
53b9eff
Resolve merge conflicts
fuzzypixelz Jul 18, 2024
754c416
Fix typos
fuzzypixelz Jul 18, 2024
0950450
Fix clippy errors
fuzzypixelz Jul 18, 2024
7aa2dbe
Minor edits
fuzzypixelz Jul 18, 2024
28f0231
Check for empty subject attributes
oteffahi Jul 22, 2024
3f2a70f
Rename ACL config field actions to messages
oteffahi Jul 22, 2024
d6da2d7
Rename ACL config field policy to policies
oteffahi Jul 22, 2024
406e07d
Update DEFAULT_CONFIG
oteffahi Jul 22, 2024
090aace
Update ACL tests config
oteffahi Jul 22, 2024
f7e85f1
Add warning when applying ACL on transport with multiple interfaces
oteffahi Jul 22, 2024
1131c09
Improve ACL subject logs
oteffahi Jul 22, 2024
848cfb4
Improve ACL no matching subject log
oteffahi Jul 22, 2024
42a8c63
Separate empty ACL config logs
oteffahi Jul 22, 2024
aa2c497
Replace unwrap with expect
oteffahi Jul 22, 2024
4167dcc
Fix unmodified copy/pasted code
oteffahi Jul 22, 2024
80a2c5c
Rename ACL config message 'get' to 'query'
oteffahi Jul 23, 2024
95d4935
Rename ACL 'get' to 'query' in DEFAULT_CONFIG
oteffahi Jul 23, 2024
a166293
Rename 'get' to 'query' in tests
oteffahi Jul 23, 2024
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
18 changes: 14 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ hmac = { version = "0.12.1", features = ["std"] }
home = "0.5.4"
http-types = "2.12.0"
humantime = "2.1.0"
itertools = "0.13.0"
json5 = "0.4.1"
jsonschema = { version = "0.18.0", default-features = false }
keyed-set = "1.0.0"
Expand Down
86 changes: 72 additions & 14 deletions DEFAULT_CONFIG.json5
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
/// The node's metadata (name, location, DNS name, etc.) Arbitrary JSON data not interpreted by zenohd and available in admin space @/router/<id>
metadata: {
name: "strawberry",
location: "Penny Lane"
location: "Penny Lane",
},

/// Which endpoints to connect to. E.g. tcp/localhost:7447.
Expand Down Expand Up @@ -186,38 +186,97 @@
// },
// ],

// /// configure access control (ACL) rules
// /// Configure access control (ACL) rules
// access_control: {
// ///[true/false] acl will be activated only if this is set to true
// /// [true/false] acl will be activated only if this is set to true
// "enabled": false,
// ///[deny/allow] default permission is deny (even if this is left empty or not specified)
// /// [deny/allow] default permission is deny (even if this is left empty or not specified)
// "default_permission": "deny",
// ///rule set for permissions allowing or denying access to key-expressions
// /// Rule set for permissions allowing or denying access to key-expressions
// "rules":
// [
// {
// "actions": [
// "put", "get", "declare_subscriber", "declare_queryable"
// /// Id has to be unique within the rule set
// "id": "rule1",
// "messages": [
// "put", "query", "declare_subscriber", "declare_queryable"
// ],
// "flows":["egress","ingress"],
// "permission": "allow",
// "key_exprs": [
// "test/demo"
// ],
// },
// {
// "id": "rule2",
// "messages": [
// "put", "query", "declare_subscriber", "declare_queryable"
// ],
// "flows":["ingress"],
// "permission": "allow",
// "key_exprs": [
// "**"
// ],
// },
// ],
// /// List of combinations of subjects.
// ///
// /// If a subject property (i.e. username, certificate common name or interface) is empty
// /// it is interpreted as a wildcard. Moreover, a subject property cannot be an empty list.
// "subjects":
// [
// {
// /// Id has to be unique within the subjects list
// "id": "subject1",
// /// Subjects can be interfaces
// "interfaces": [
// "lo0"
// "lo0",
// "en0",
// ],
// /// Subjects can be cert_common_names when using TLS or Quic
// /// Subjects can be cert_common_names when using TLS or Quic
// "cert_common_names": [
// "example.zenoh.io"
// ],
// /// Subjects can be usernames when using user/password authentication
// "usernames": [
// "zenoh-example"
// ]
// ],
// /// This instance translates internally to this filter:
// /// (interface="lo0" && cert_common_name="example.zenoh.io" && username="zenoh-example") ||
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a valuable clarification but maybe it could be in prose rather than pseudo code. To me it seems to imply the existence of a filtering DSL.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another nitpick.

// /// (interface="en0" && cert_common_name="example.zenoh.io" && username="zenoh-example")
// },
// {
// "id": "subject2",
// "interfaces": [
// "lo0",
// "en0",
// ],
// "cert_common_names": [
// "example2.zenoh.io"
// ],
// /// This instance translates internally to this filter:
// /// (interface="lo0" && cert_common_name="example2.zenoh.io") ||
// /// (interface="en0" && cert_common_name="example2.zenoh.io")
// },
// ]
// {
// "id": "subject3",
// /// An empty subject combination is a wildcard
// },
// ],
// /// The policies list associates rules to subjects
// "policies":
// [
// /// Each policy associates one or multiple rules to one or multiple subject combinations
// {
// /// Rules and Subjects are identified with their unique IDs declared above
// "rules": ["rule1"],
// "subjects": ["subject1", "subject2"],
// },
// {
// "rules": ["rule2"],
// "subjects": ["subject3"],
// },
// ]
//},

/// Configure internal transport parameters
Expand All @@ -238,7 +297,7 @@
/// NOTE: Currently, the LowLatency transport doesn't preserve QoS prioritization.
/// NOTE: Due to the note above, 'lowlatency' is incompatible with 'qos' option, so in order to
/// enable 'lowlatency' you need to explicitly disable 'qos'.
/// NOTE: LowLatency transport does not support the fragmentation, so the message size should be
/// NOTE: LowLatency transport does not support the fragmentation, so the message size should be
/// smaller than the tx batch_size.
lowlatency: false,
/// Enables QoS on unicast communications.
Expand Down Expand Up @@ -317,7 +376,7 @@
/// Using CongestionControl::Drop the message might be dropped, depending on conditions configured here.
congestion_control: {
/// The maximum time in microseconds to wait for an available batch before dropping the message if still no batch is available.
wait_before_drop: 1000
wait_before_drop: 1000,
},
/// The initial exponential backoff time in nanoseconds to allow the batching to eventually progress.
/// Higher values lead to a more aggressive batching but it will introduce additional latency.
Expand Down Expand Up @@ -539,5 +598,4 @@
// __config__: "./plugins/zenoh-plugin-storage-manager/config.json5",
// }
// },

}
2 changes: 2 additions & 0 deletions commons/zenoh-config/src/defaults.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,8 @@ impl Default for AclConfig {
enabled: false,
default_permission: Permission::Deny,
rules: None,
subjects: None,
policies: None,
}
}
}
Expand Down
70 changes: 51 additions & 19 deletions commons/zenoh-config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,40 +104,70 @@ pub struct DownsamplingItemConf {
}

#[derive(Serialize, Debug, Deserialize, Clone)]
pub struct AclConfigRules {
pub interfaces: Option<Vec<String>>,
pub cert_common_names: Option<Vec<String>>,
pub usernames: Option<Vec<String>>,
pub struct AclConfigRule {
pub id: String,
pub key_exprs: Vec<String>,
pub actions: Vec<Action>,
pub messages: Vec<AclMessage>,
pub flows: Option<Vec<InterceptorFlow>>,
pub permission: Permission,
}

#[derive(Serialize, Debug, Deserialize, Clone)]
pub struct AclConfigSubjects {
pub id: String,
pub interfaces: Option<Vec<Interface>>,
pub cert_common_names: Option<Vec<CertCommonName>>,
pub usernames: Option<Vec<Username>>,
}

#[derive(Serialize, Debug, Deserialize, Clone, PartialEq, Eq, Hash)]
pub struct Interface(pub String);

impl std::fmt::Display for Interface {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Interface({})", self.0)
}
}

#[derive(Serialize, Debug, Deserialize, Clone, PartialEq, Eq, Hash)]
pub struct CertCommonName(pub String);

impl std::fmt::Display for CertCommonName {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "CertCommonName({})", self.0)
}
}

#[derive(Serialize, Debug, Deserialize, Clone, PartialEq, Eq, Hash)]
pub struct Username(pub String);

impl std::fmt::Display for Username {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Username({})", self.0)
}
}

#[derive(Serialize, Debug, Deserialize, Clone, PartialEq, Eq, Hash)]
pub struct AclConfigPolicyEntry {
pub rules: Vec<String>,
pub subjects: Vec<String>,
}

#[derive(Clone, Serialize, Debug, Deserialize)]
pub struct PolicyRule {
pub subject: Subject,
pub subject_id: usize,
pub key_expr: String,
pub action: Action,
pub message: AclMessage,
pub permission: Permission,
pub flow: InterceptorFlow,
}

#[derive(Serialize, Debug, Deserialize, Eq, PartialEq, Hash, Clone)]
#[serde(untagged)]
#[serde(rename_all = "snake_case")]
pub enum Subject {
Interface(String),
CertCommonName(String),
Username(String),
}

#[derive(Clone, Copy, Debug, Serialize, Deserialize, Eq, Hash, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum Action {
pub enum AclMessage {
Put,
DeclareSubscriber,
Get,
Query,
DeclareQueryable,
}

Expand Down Expand Up @@ -516,7 +546,9 @@ validated_struct::validator! {
pub access_control: AclConfig {
pub enabled: bool,
pub default_permission: Permission,
pub rules: Option<Vec<AclConfigRules>>
pub rules: Option<Vec<AclConfigRule>>,
pub subjects: Option<Vec<AclConfigSubjects>>,
pub policies: Option<Vec<AclConfigPolicyEntry>>,
},

/// A list of directories where plugins may be searched for if no `__path__` was specified for them.
Expand Down
1 change: 1 addition & 0 deletions zenoh/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ flume = { workspace = true }
form_urlencoded = { workspace = true }
futures = { workspace = true }
git-version = { workspace = true }
itertools = { workspace = true }
lazy_static = { workspace = true }
tracing = { workspace = true }
ordered-float = { workspace = true }
Expand Down
Loading