Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
直接コマンドでは確認用 Prompt が省略されます。実行前にソースを確認してください。
npx skills add https://github.com/huiali/rust-skills --skill rust-xacmlコマンドは1行のまま表示されます。コピー前に横へスクロールして全体を確認してください。
ローカルで確認しますか?SkillsMP が現在取得できるファイルをダウンロードできます。
SOC 職業分類に基づく
SKILL.md を表示中
| name | rust-xacml |
| description | 策略引擎、权限决策、RBAC、策略模式、责任链--- |
//! 策略评估器
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
/// 请求上下文
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RequestContext {
pub subject: Subject, // 主体
pub resource: Resource, // 资源
pub action: String, // 操作
pub environment: HashMap<String, String>, // 环境
}
/// 主体
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Subject {
pub id: String,
pub roles: Vec<String>,
pub attributes: HashMap<String, String>,
}
/// 资源
#[derive(Debug, Clone, Serialize, Deserialize)]
{
id: ,
r#: ,
attributes: HashMap<, >,
}
{
Permit,
Deny,
NotApplicable,
(),
}
{
id: ,
target: PolicyTarget,
rules: <Rule>,
combining_algorithm: CombiningAlgorithm,
}
{
(, subjects: <<>>,
resources: <>,
actions: <>,
}
{
id: ,
effect: RuleEffect,
condition: << (&RequestContext) + >>,
}
{
Permit,
Deny,
}
{
DenyOverrides,
PermitOverrides,
FirstApplicable,
OnlyOneApplicable,
}
{
policies: <Policy>,
}
{
(policies: <Policy>) {
{ policies }
}
(&, context: &RequestContext) Decision {
: <&Policy> = .policies
.()
.(|p| .(p, context))
.();
applicable_policies.() {
Decision::NotApplicable;
}
applicable_policies.().(|p| p.combining_algorithm).(CombiningAlgorithm::FirstApplicable) {
CombiningAlgorithm::DenyOverrides => .(&applicable_policies, context),
CombiningAlgorithm::PermitOverrides => .(&applicable_policies, context),
CombiningAlgorithm::FirstApplicable => .(&applicable_policies, context),
CombiningAlgorithm::OnlyOneApplicable => {
applicable_policies.() == {
.(applicable_policies[], context)
} {
Decision::(.())
}
}
}
}
(&, policy: &Policy, context: &RequestContext) {
= policy.target.subjects.() ||
policy.target.subjects.().(|roles| {
roles.().(|r| context.subject.roles.(r))
});
= policy.target.resources.() ||
policy.target.resources.(&context.resource.r#);
= policy.target.actions.() ||
policy.target.actions.(&context.action);
subject_matches && resource_matches && action_matches
}
(&, policies: &[&Policy], context: &RequestContext) Decision {
= ;
= ::();
policies {
.(policy, context) {
Decision::Deny => Decision::Deny,
Decision::(msg) => {
has_error = ;
error_msg = msg;
}
_ => {}
}
}
has_error {
Decision::(error_msg)
} {
Decision::Permit
}
}
(&, policies: &[&Policy], context: &RequestContext) Decision {
= ;
= ::();
policies {
.(policy, context) {
Decision::Permit => Decision::Permit,
Decision::(msg) => {
has_error = ;
error_msg = msg;
}
_ => {}
}
}
has_error {
Decision::(error_msg)
} {
Decision::Deny
}
}
(&, policies: &[&Policy], context: &RequestContext) Decision {
policies {
= .(policy, context);
decision != Decision::NotApplicable {
decision;
}
}
Decision::Deny
}
(&, policy: &Policy, context: &RequestContext) Decision {
&policy.rules {
( condition) = rule.condition {
!(context) {
;
}
}
rule.effect {
RuleEffect::Permit => Decision::Permit,
RuleEffect::Deny => Decision::Deny,
};
}
Decision::NotApplicable
}
}
//! RBAC 权限检查
use std::collections::HashMap;
/// RBAC 配置
#[derive(Debug, Clone)]
pub struct RbacConfig {
/// 角色层级
pub role_hierarchy: HashMap<String, Vec<String>>,
/// 角色权限映射
pub role_permissions: HashMap<String, Vec<String>>,
/// 权限定义
pub permissions: HashMap<String, PermissionDef>,
}
/// 权限定义
#[derive(Debug, Clone)]
pub struct PermissionDef {
pub resource: String,
pub actions: Vec<String>,
}
/// RBAC 检查器
pub struct RbacChecker {
config: RbacConfig,
}
impl RbacChecker {
pub fn new(config: RbacConfig) -> Self {
Self { config }
}
/// 检查用户是否有权限
pub fn check_permission(
&self,
user_roles: &[String],
resource: &str,
action: &str,
) -> bool {
// 获取所有继承的角色
let all_roles = self.expand_roles(user_roles);
// 检查是否有权限
for role in &all_roles {
if let Some(perms) = self.config.role_permissions.get(role) {
for perm_id in perms {
if let Some(perm) = self.config.permissions.get(perm_id) {
if perm.resource == resource && perm.actions.contains(&action) {
return true;
}
}
}
}
}
false
}
/// 展开角色层级
fn expand_roles(&self, roles: &[String]) -> Vec<String> {
let mut expanded = Vec::new();
let mut visited = std::collections::HashSet::new();
let mut queue = Vec::new();
for role in roles {
if !visited.contains(role) {
queue.push(role.clone());
visited.insert(role.clone());
}
}
while let Some(role) = queue.pop() {
expanded.push(role.clone());
if let Some(parents) = self.config.role_hierarchy.get(&role) {
for parent in parents {
if !visited.contains(parent) {
visited.insert(parent.clone());
queue.push(parent.clone());
}
}
}
}
expanded
}
/// 获取用户的所有权限
pub fn get_user_permissions(&self, user_roles: &[String]) -> Vec<String> {
let all_roles = self.expand_roles(user_roles);
let mut permissions = std::collections::HashSet::new();
for role in &all_roles {
if let Some(role_perms) = self.config.role_permissions.get(role) {
for perm in role_perms {
permissions.insert(perm.clone());
}
}
}
permissions.into_iter().collect()
}
}
//! 策略缓存
use crate::{Policy, PolicyEvaluator};
use std::sync::Arc;
use tokio::sync::RwLock;
use std::time::{Duration, Instant};
/// 缓存配置
#[derive(Debug, Clone)]
pub struct PolicyCacheConfig {
pub ttl: Duration,
pub max_size: usize,
}
/// 缓存条目
struct CacheEntry {
policy: Policy,
inserted_at: Instant,
}
/// 策略缓存
pub struct PolicyCache {
config: PolicyCacheConfig,
cache: Arc<RwLock<HashMap<String, CacheEntry>>>,
}
impl PolicyCache {
pub fn new(config: PolicyCacheConfig) -> Self {
Self {
config,
cache: Arc::new(RwLock::new(HashMap::new())),
}
}
/// 获取策略
pub async fn get(&self, policy_id: &str) -> Option<Policy> {
let cache = self.cache.read().await;
cache.get(policy_id).map(|entry| entry.policy.clone())
}
/// 存储策略
pub async fn set(&self, policy: Policy) {
let mut cache = self.cache.write().await;
// 清理过期条目
let now = Instant::now();
cache.retain(|_, v| now.duration_since(v.inserted_at) < self.config.ttl);
// 清理超出大小的条目
if cache.len() >= self.config.max_size {
let to_remove = cache.len() - self.config.max_size + 1;
let keys: Vec<String> = cache.keys().take(to_remove).cloned().collect();
for key in keys {
cache.remove(&key);
}
}
cache.insert(policy.id.clone(), CacheEntry {
policy,
inserted_at: Instant::now(),
});
}
/// 失效策略
pub async fn invalidate(&self, policy_id: &str) {
let mut cache = self.cache.write().await;
cache.remove(policy_id);
}
/// 清理所有
pub async fn clear(&self) {
let mut cache = self.cache.write().await;
cache.clear();
}
}
//! 策略构建器
use crate::{Policy, PolicyTarget, Rule, RuleEffect, CombiningAlgorithm};
/// 策略构建器
pub struct PolicyBuilder {
policy: Policy,
}
impl PolicyBuilder {
pub fn new(id: &str) -> Self {
Self {
policy: Policy {
id: id.to_string(),
target: PolicyTarget {
subjects: Vec::new(),
resources: Vec::new(),
actions: Vec::new(),
},
rules: Vec::new(),
combining_algorithm: CombiningAlgorithm::DenyOverrides,
},
}
}
pub fn with_subject_roles(mut self, roles: &[&str]) -> Self {
self.policy.target.subjects = vec![roles.iter().map(|s| s.to_string()).collect()];
self
}
pub fn with_resource(mut self, resource: &str) -> Self {
self.policy.target.resources = vec![resource.to_string()];
self
}
pub fn with_action(mut self, action: &str) -> Self {
self.policy.target.actions = vec![action.to_string()];
self
}
pub fn add_rule(
mut self,
id: &str,
effect: RuleEffect,
condition: impl Fn(&crate::RequestContext) -> bool + Send + 'static,
) -> Self {
self.policy.rules.push(Rule {
id: id.to_string(),
effect,
condition: Some(Box::new(condition)),
});
self
}
pub fn with_combining_algorithm(mut self, algo: CombiningAlgorithm) -> Self {
self.policy.combining_algorithm = algo;
self
}
pub fn build(self) -> Policy {
self.policy
}
}
/// 使用示例
fn example_policy() -> Policy {
PolicyBuilder::new("read-policy")
.with_subject_roles(&["user", "admin"])
.with_resource("document")
.with_action("read")
.add_rule("own-document", RuleEffect::Permit, |ctx| {
// 自己创建的文档可以读取
ctx.resource.attributes.get("owner") == Some(&ctx.subject.id)
})
.add_rule("public-document", RuleEffect::Permit, |ctx| {
// 公开文档可以读取
ctx.resource.attributes.get("visibility") == Some(&"public".to_string())
})
.with_combining_algorithm(CombiningAlgorithm::DenyOverrides)
.build()
}
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 决策不一致 | 组合算法选择不当 | 根据业务选择合适的算法 |
| 性能差 | 策略过多 | 使用缓存和索引 |
| 权限绕过 | 规则顺序问题 | DenyOverrides 优先 |
rust-auth - 认证授权rust-web - Web 集成rust-cache - 策略缓存rust-performance - 性能优化