2个版本
0.1.1 | 2021年1月8日 |
---|---|
0.1.0 | 2021年1月8日 |
#294 in 身份验证
74KB
1.5K SLoC
Allow-me
一个基于JSON策略定义的身份验证库。
在简单的Identity
(I),Operation
(O),Resource
(R)模型中定义你的授权规则。评估请求是否符合你的策略规则。
入门指南
[dependencies]
allow-me = "0.1"
示例用法
JSON定义
这是一个包含一个声明并对该策略进行评估的请求的简单示例。
let json = r#"{
"statements": [
{
"effect": "allow",
"identities": [
"actor_a"
],
"operations": [
"write"
],
"resources": [
"resource_1"
]
}
]
}"#;
// Construct the policy.
let policy = PolicyBuilder::from_json(json).build()?;
// Prepare request (e.g. from user input).
let request = Request::new("actor_a", "write", "resource_1")?;
// Evaluate the request.
match policy.evaluate(&request)? {
Decision::Allowed => println!("Allowed"),
Decision::Denied => {
panic!("Denied!")
}
};
试试看
cargo run --example json
可变规则
以下示例展示了一个允许任何身份读取/写入其自身资源的规则。
let json = r#"{
"statements": [
{
"effect": "allow",
"identities": [
"{{any}}"
],
"operations": [
"read",
"write"
],
"resources": [
"/home/{{identity}}/"
]
}
]
}"#;
// Construct the policy.
let policy = PolicyBuilder::from_json(json)
// use "starts with" matching for resources.
.with_matcher(matcher::StartsWith)
.with_default_decision(Decision::Denied)
.build()?;
// Prepare request (e.g. from user input).
let request = Request::new("johndoe", "write", "/home/johndoe/my.resource")?;
// Evaluate the request.
match policy.evaluate(&request)? {
Decision::Allowed => println!("Allowed"),
Decision::Denied => {
panic!("Denied!")
}
};
试试看
cargo run --example vars
规则顺序
规则的顺序很重要。在存在冲突规则的情况下,第一个规则生效。在下面的示例中,我们允许actor_a
写入resource_1
,并拒绝写入其他任何内容。请注意,任何其他请求都将被允许(默认决定)。
let json = r#"{
"statements": [
{
"effect": "allow",
"identities": [
"actor_a"
],
"operations": [
"write"
],
"resources": [
"resource_1"
]
},
{
"effect": "deny",
"identities": [
"actor_a"
],
"operations": [
"write"
],
"resources": [
"{{any}}"
]
}
]
}"#;
// Construct the policy.
let policy = PolicyBuilder::from_json(json)
// default to Allow all requests.
.with_default_decision(Decision::Allowed)
.build()?;
// Prepare request (e.g. from user input).
let request = Request::new("actor_a", "write", "resource_1")?;
// Evaluate specific request.
match policy.evaluate(&request)? {
Decision::Allowed => println!("allowed write resource_1"),
Decision::Denied => {
panic!("Denied!")
}
};
let request = Request::new("actor_a", "write", "some_other_resource")?;
// Everything else denies.
assert_matches!(policy.evaluate(&request), Ok(Decision::Denied));
试试看
cargo run --example order
自定义
库中有几个扩展点
ResourceMatcher
特质 - 负责执行资源匹配逻辑。Substituter
特质 - 你可以添加自定义变量,这些变量可以被替换。Validator
特质 - 验证策略定义。如果你的策略规则需要自定义验证。- 请求上下文 - 你可以将自定义数据类型与
Request
关联。对于自定义Substituter
或ResourceMatcher
,实现自定义变量或匹配逻辑非常有用。
ResourceMatcher
自定义ResourceMatcher,实现"以...开始"匹配。
pub struct StartsWith;
impl ResourceMatcher for StartsWith {
type Context = ();
fn do_match(&self, _context: &Request<Self::Context>, input: &str, policy: &str) -> bool {
input.starts_with(policy)
}
}
Substituter和自定义请求上下文
自定义Substituter,支持{{any}}
和{{role}}
变量。{{role}}
变量用请求上下文中的值替换。
// custom context
struct MyContext {
role: String
};
// custom substituter
struct RoleSubstituter;
impl Substituter for RoleSubstituter {
type Context = MyContext;
fn visit_resource(&self, value: &str, context: &Request<Self::Context>) -> Result<String> {
match context.context() {
Some(role_context) => {
let mut result = value.to_owned();
for variable in VariableIter::new(value) {
result = match variable {
"{{any}}" => replace(&result, variable, context.resource()),
"{{role}}" => replace(&result, variable, &role_context.role),
_ => result,
};
}
Ok(result)
}
None => Ok(value.to_owned()),
}
}
...
}
试试看
cargo run --example customizations
路线图
- PolicyBuilder的流畅API
- 正则表达式支持
- 基准测试
贡献
欢迎所有贡献和评论!当你发现错误或有改进这个crate的想法时,不要害怕打开问题或PR。
依赖项
~2.8–4.5MB
~85K SLoC