Files
regorus/bindings/ffi/src/schema_registry.rs
Anand Krishnamoorthi cc917ea75d feat: Complete target system with C# bindings and resource inference (#458)
* feat: Add Schema Registry and Validation Framework

This commit introduces a comprehensive schema registry and validation framework, providing schema-based validation of resources and policy effects.

- Thread-safe, in-memory registry for schema storage and management
- Global registry patterns for effects and resources
- Concurrent access with proper error handling
- Unicode schema names support

- JSON Schema-compliant validation for all primitive types
- Advanced constraint validation (patterns, ranges, length limits)
- Discriminated union support with anyOf schemas
- Detailed error reporting with nested validation paths
- Discriminated subobject validation for polymorphic schemas

- **Registry Tests**: All registry operations
- **Effect Tests**: Policy effect validation
- **Resource Tests**: Resource validation
- **Validation Tests**: Core validation engine
- Thread-safety, error handling, integration scenarios, edge cases

- **Dependencies**: dashmap, once_cell, regex
- **Thread Safety**: Minimal locking with Rc<Schema> sharing
- **Error Types**: TypeMismatch, OutOfRange, PatternMismatch, etc.

- Complete schema registry and validation subsystem
- Comprehensive test coverage
- Foundation for policy validation in Regorus

Benchmarks:

- Criterion benchmarks for basic types, effects and Azure resources
- Performance range: 3.22ns (string) to 34.74µs (Azure VM resource schema validation)
- String withs patterns validation: 30.2µs. Need to explore whether regex caching helps
  bring this down.
- Azure policy effects: 188ns-1.4µs

Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>

* feat: Complete target system with C# bindings and resource inference

- Add comprehensive target system with TargetRegistry and target-aware compilation
- Implement resource type inference from policy equality expressions
- Create modular C# bindings with separate wrapper classes for each concept
- Add thread-safe CompiledPolicy with reference counting for safe disposal
- Enhance FFI with detailed error propagation and target functionality
- Create TargetExampleApp demonstrating Azure Policy integration
- Add CI/CD pipeline testing for all C# applications
- Support target definitions with schema validation and resource selectors
- Implement PolicyModule struct and target-aware compilation methods
- Add comprehensive test coverage for target functionality

Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>

---------

Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
2025-08-19 20:23:43 -05:00

179 lines
5.3 KiB
Rust

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
//! Schema registry functions for FFI.
//!
//! These functions provide access to regorus's resource schema registry functionality,
//! enabling registration and management of Azure Policy resource schemas.
#![cfg(feature = "azure_policy")]
use crate::common::{from_c_str, RegorusResult, RegorusStatus};
use regorus::{registry::schemas, Schema};
use std::os::raw::c_char;
// Resource Schema Registry Functions
/// Register a resource schema from JSON with a given name.
///
/// # Parameters
/// * `name` - Name to register the schema under
/// * `schema_json` - JSON string representing the schema
///
/// # Returns
/// Returns a RegorusResult with success/error status.
///
/// # Safety
/// All string parameters must be valid null-terminated UTF-8 strings.
#[cfg(feature = "azure_policy")]
#[no_mangle]
pub extern "C" fn regorus_resource_schema_register(
name: *const c_char,
schema_json: *const c_char,
) -> RegorusResult {
let schema_name = match from_c_str(name) {
Ok(s) => s,
Err(e) => {
return RegorusResult::err_with_message(
RegorusStatus::InvalidArgument,
format!("Invalid schema name string: {e}"),
)
}
};
let schema_str = match from_c_str(schema_json) {
Ok(s) => s,
Err(e) => {
return RegorusResult::err_with_message(
RegorusStatus::InvalidDataFormat,
format!("Invalid schema JSON string: {e}"),
)
}
};
// Parse schema from JSON
let schema = match Schema::from_json_str(&schema_str) {
Ok(schema) => schema,
Err(e) => {
return RegorusResult::err_with_message(
RegorusStatus::InvalidDataFormat,
format!("Failed to parse schema JSON: {e}"),
)
}
};
// Register the schema
match schemas::resource::register(schema_name, schema.into()) {
Ok(()) => RegorusResult::ok_pointer(std::ptr::null_mut()),
Err(e) => RegorusResult::err_with_message(
RegorusStatus::Error,
format!("Failed to register schema: {e}"),
),
}
}
/// Check if a resource schema with the given name exists.
///
/// # Parameters
/// * `name` - Name of the schema to check
///
/// # Returns
/// Returns a RegorusResult with "true" or "false" string output.
///
/// # Safety
/// The name parameter must be a valid null-terminated UTF-8 string.
#[cfg(feature = "azure_policy")]
#[no_mangle]
pub extern "C" fn regorus_resource_schema_contains(name: *const c_char) -> RegorusResult {
let schema_name = match from_c_str(name) {
Ok(s) => s,
Err(e) => {
return RegorusResult::err_with_message(
RegorusStatus::InvalidArgument,
format!("Invalid schema name string: {e}"),
)
}
};
let contains = schemas::resource::contains(&schema_name);
RegorusResult::ok_bool(contains)
}
/// Get the number of registered resource schemas.
///
/// # Returns
/// Returns a RegorusResult with the count as a string.
#[cfg(feature = "azure_policy")]
#[no_mangle]
pub extern "C" fn regorus_resource_schema_len() -> RegorusResult {
let count = schemas::resource::len();
RegorusResult::ok_int(count as i64)
}
/// Check if the resource schema registry is empty.
///
/// # Returns
/// Returns a RegorusResult with "true" or "false" string output.
#[cfg(feature = "azure_policy")]
#[no_mangle]
pub extern "C" fn regorus_resource_schema_is_empty() -> RegorusResult {
let is_empty = schemas::resource::is_empty();
RegorusResult::ok_bool(is_empty)
}
/// List all registered resource schema names as a JSON array.
///
/// # Returns
/// Returns a RegorusResult with a JSON array of schema names.
#[cfg(feature = "azure_policy")]
#[no_mangle]
pub extern "C" fn regorus_resource_schema_list_names() -> RegorusResult {
let names = schemas::resource::list_names();
match serde_json::to_string(&names) {
Ok(json_str) => RegorusResult::ok_string(json_str),
Err(e) => RegorusResult::err_with_message(
RegorusStatus::Error,
format!("Failed to serialize schema names to JSON: {e}"),
),
}
}
/// Remove a resource schema by name.
///
/// # Parameters
/// * `name` - Name of the schema to remove
///
/// # Returns
/// Returns a RegorusResult with "true" if removed, "false" if not found.
///
/// # Safety
/// The name parameter must be a valid null-terminated UTF-8 string.
#[cfg(feature = "azure_policy")]
#[no_mangle]
pub extern "C" fn regorus_resource_schema_remove(name: *const c_char) -> RegorusResult {
let schema_name = match from_c_str(name) {
Ok(s) => s,
Err(e) => {
return RegorusResult::err_with_message(
RegorusStatus::InvalidArgument,
format!("Invalid schema name string: {e}"),
)
}
};
let removed = schemas::resource::remove(&schema_name).is_some();
RegorusResult::ok_bool(removed)
}
/// Clear all resource schemas from the registry.
///
/// # Returns
/// Returns a RegorusResult with success status.
#[cfg(feature = "azure_policy")]
#[no_mangle]
pub extern "C" fn regorus_resource_schema_clear() -> RegorusResult {
schemas::resource::clear();
RegorusResult::ok_pointer(std::ptr::null_mut())
}