Crate nacm_validator

Crate nacm_validator 

Source
Expand description

§NACM Validator - Network Access Control Model with Tail-f ACM Extensions

This library implements NACM (RFC 8341) access control validation in Rust with comprehensive support for Tail-f ACM (Access Control Model) extensions and multiple configuration files. It provides functionality to:

§Core NACM Features (RFC 8341)

  • Parse real-world NACM XML configurations
  • Validate access requests against defined rules
  • Handle user groups and rule precedence
  • Support various operations (CRUD + exec) and path matching

§Multiple Configuration Files Support (v0.2.0+)

  • Configuration Merging: Combine multiple XML files using YANG merge semantics
  • YANG Compliance: Proper merge rules (last-wins for globals, additive for groups/rules)
  • Rule Precedence: Automatic precedence adjustment across files
  • Error Resilience: Handle invalid files gracefully during merging
  • Modular Configuration: Support team-based and environment-specific configurations

§Tail-f ACM Extensions

  • Command Rules: Context-aware command access control (CLI, WebUI, NETCONF)
  • Enhanced Logging: Granular logging control with log-if-* attributes
  • ValidationResult: Returns both access decision and logging indication
  • Group ID Mapping: External authentication system integration via GID
  • Context Awareness: Different access policies for different user interfaces

§Quick Start

§Standard NACM Data Access Validation

use nacm_validator::{NacmConfig, AccessRequest, Operation, RequestContext};

// Load configuration from XML
let xml_content = r#"<?xml version="1.0" encoding="UTF-8"?>
<config xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-acm">
  <nacm>
    <enable-nacm>true</enable-nacm>
    <read-default>permit</read-default>
    <write-default>deny</write-default>
    <exec-default>permit</exec-default>
    <groups>
      <group>
        <name>admin</name>
        <user-name>alice</user-name>
      </group>
    </groups>
    <rule-list>
      <name>admin-acl</name>
      <group>admin</group>
      <rule>
        <name>permit-all</name>
        <action>permit</action>
      </rule>
    </rule-list>
  </nacm>
</config>"#;
let config = NacmConfig::from_xml(&xml_content)?;

// Create a data access request
let context = RequestContext::NETCONF;
let request = AccessRequest {
    user: "alice",
    module_name: Some("ietf-interfaces"),
    rpc_name: None,
    operation: Operation::Read,
    path: Some("/interfaces"),
    context: Some(&context),
    command: None,
};

// Validate the request - returns ValidationResult with access decision and logging info
let result = config.validate(&request);
println!("Access {}: {}", 
         if result.effect == nacm_validator::RuleEffect::Permit { "PERMIT" } else { "DENY" },
         if result.should_log { "[LOGGED]" } else { "" });

§Tail-f ACM Command Access Validation

use nacm_validator::{NacmConfig, AccessRequest, Operation, RequestContext};

// Load configuration with Tail-f ACM command rules
let xml_content = r#"<?xml version="1.0" encoding="UTF-8"?>
<config xmlns="http://tail-f.com/ns/config/1.0">
    <nacm xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-acm">
        <enable-nacm>true</enable-nacm>
        <read-default>deny</read-default>
        <write-default>deny</write-default>
        <exec-default>deny</exec-default>
        <cmd-read-default xmlns="http://tail-f.com/yang/acm">permit</cmd-read-default>
        <cmd-exec-default xmlns="http://tail-f.com/yang/acm">deny</cmd-exec-default>
        <groups>
            <group>
                <name>admin</name>
                <user-name>alice</user-name>
            </group>
        </groups>
        <rule-list>
            <name>admin-rules</name>
            <group>admin</group>
            <cmdrule xmlns="http://tail-f.com/yang/acm">
                <name>cli-show</name>
                <context>cli</context>
                <command>show *</command>
                <action>permit</action>
            </cmdrule>
        </rule-list>
    </nacm>
</config>"#;
let config = NacmConfig::from_xml(&xml_content)?;

// Create a command access request
let context = RequestContext::CLI;
let request = AccessRequest {
    user: "alice",
    module_name: None,
    rpc_name: None,
    operation: Operation::Read,
    path: None,
    context: Some(&context),
    command: Some("show status"),
};

// Validate command access using Tail-f ACM command rules
let result = config.validate(&request);
match result.effect {
    nacm_validator::RuleEffect::Permit => {
        println!("Command access PERMITTED{}", 
                if result.should_log { " [LOGGED]" } else { "" });
    },
    nacm_validator::RuleEffect::Deny => {
        println!("Command access DENIED{}", 
                if result.should_log { " [LOGGED]" } else { "" });
    }
}

§Multiple Configuration Files with YANG Merge Semantics (v0.2.0+)

use nacm_validator::{NacmConfig, AccessRequest, Operation, RequestContext};

// First configuration file - base settings and admin group
let base_config = r#"<?xml version="1.0" encoding="UTF-8"?>
<config xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-acm">
  <nacm>
    <enable-nacm>true</enable-nacm>
    <read-default>deny</read-default>
    <write-default>deny</write-default>
    <exec-default>deny</exec-default>
    <groups>
      <group>
        <name>admin</name>
        <user-name>alice</user-name>
      </group>
    </groups>
    <rule-list>
      <name>admin-rules</name>
      <group>admin</group>
      <rule>
        <name>admin-access</name>
        <action>permit</action>
      </rule>
    </rule-list>
  </nacm>
</config>"#;

// Second configuration file - operators group and rules  
let ops_config = r#"<?xml version="1.0" encoding="UTF-8"?>
<config xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-acm">
  <nacm>
    <enable-nacm>true</enable-nacm>
    <read-default>permit</read-default>  <!-- Override base setting -->
    <write-default>deny</write-default>
    <exec-default>deny</exec-default>
    <groups>
      <group>
        <name>admin</name>
        <user-name>bob</user-name>  <!-- Add to existing admin group -->
      </group>
      <group>
        <name>operators</name>      <!-- New group -->
        <user-name>charlie</user-name>
      </group>
    </groups>
    <rule-list>
      <name>operator-rules</name>   <!-- New rule list -->
      <group>operators</group>
      <rule>
        <name>read-only</name>
        <access-operations>read</access-operations>
        <action>permit</action>
      </rule>
    </rule-list>
  </nacm>
</config>"#;

// Parse individual configurations
let config1 = NacmConfig::from_xml(&base_config)?;
let config2 = NacmConfig::from_xml(&ops_config)?;

// Merge configurations using YANG merge semantics
let merged_config = NacmConfig::merge(vec![
    (config1, 0),  // File index 0 - lower precedence
    (config2, 1),  // File index 1 - higher precedence
])?;

// Result demonstrates YANG merge semantics:
// - Global settings: read-default is "permit" (last-wins from config2)
// - Groups merged additively: admin now has ["alice", "bob"], operators has ["charlie"] 
// - Rule lists combined: admin-rules (precedence 0) and operator-rules (precedence 10000)
// - Rules maintain proper precedence across files

assert_eq!(merged_config.read_default, nacm_validator::RuleEffect::Permit); // Last-wins
assert_eq!(merged_config.groups.len(), 2); // admin + operators
assert_eq!(merged_config.groups["admin"].users.len(), 2); // alice + bob merged
assert_eq!(merged_config.rule_lists.len(), 2); // admin-rules + operator-rules

// Validate access with merged configuration
let request = AccessRequest {
    user: "charlie",
    module_name: None,
    rpc_name: None,
    operation: Operation::Read,
    path: None,
    context: Some(&RequestContext::NETCONF),
    command: None,
};

let result = merged_config.validate(&request);
// Charlie (operator) gets read access via operator-rules from second config
assert_eq!(result.effect, nacm_validator::RuleEffect::Permit);

Structs§

AccessRequest
Represents an access request for validation
NacmCommandRule
NACM Command Rule structure (Tail-f ACM extension)
NacmConfig
Full NACM configuration
NacmGroup
NACM Group definition
NacmRule
NACM Rule structure (extended to match XML format)
NacmRuleList
NACM Rule List with associated groups
ValidationResult
Access control validation result with logging indication

Enums§

Operation
NACM operations enumeration
RequestContext
Request context enumeration
RuleEffect
NACM Rule effect (permit or deny)