Skip to content

Commit

Permalink
更新访问控制策略 校验相关文档
Browse files Browse the repository at this point in the history
  • Loading branch information
pirunxi committed Dec 15, 2023
1 parent ee05ef2 commit 47106d1
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 35 deletions.
57 changes: 52 additions & 5 deletions docs/business/accesspolicy.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@
```


### 配置规则
## 配置规则

顶级tag为 AccessPolicy,包含0-N个Rule和Target两类配置项。

#### Rule
### Rule

每个Rule包含多个程序集的访问控制规则。每个Rule会计算出一个限制访问的类型集合,最终的限制访问的集合为所有Rule的并集,即只要某个Rule限制访问某个类型,
则最终不允许访问这个类型。
Expand All @@ -52,7 +52,7 @@
|id|属性||Rule的id。字符串类型,不可为空,必须全局唯一|
|assembly|子元素||针对单个程序集的限制集合,Rule下可以包含0-N个assembly,同一个Rule下不可有同名assembly,但不同Rule间可以有同名程序集|

#### assembly
### assembly

针对单个程序集的限制规则集合,配置了禁止访问该程序集的哪些类型。

Expand All @@ -73,7 +73,7 @@
上面的例子中,尽管`<type fullname="System.IO.*"/>`禁止访问`System.IO`命名空间下的所有类型,包括`System.IO.File`,但接下的
`<type fullname="System.IO.File" access="1"/>`又单独取消了对`System.IO.File`的访问限制。

#### type
### type

针对一个或者一组类型的限制规则。

Expand All @@ -83,7 +83,7 @@
|access|属性||是否可访问,默认为false。当取 `true, yes, 1` 时为true,取`false, no, 0`时为false|


#### Target
### Target

Target配置了程序集中代码被施加的访问限制规则。

Expand All @@ -110,6 +110,53 @@ Target配置了程序集中代码被施加的访问限制规则。
}
```

## 校验AccessPolicy配置合法性

实践中很容易错误地填写了`assembly.fullname``type.fullname`之类的名字,导致没有正确执行期望的访问控制策略。
`HybridCLR.Editor.Security.AccessPolicyConfigValidator` 用于检查 AccessPolicy的合法性,避免这种错误。

|函数|说明|
|-|-|
|ValidateRules|检查Rule规则的合法性|
|ValidateTargets|检查Target规则的合法性|

示例代码如下:

```csharp
public static void ValidateAccessPolicy()
{
var reader = new XmlAccessPolicyReader();
reader.LoadXmlFile("Assets/AccessPolicy/AccessPolicy.xml");
List<string> hotUpdateDllNames = SettingsUtil.HotUpdateAssemblyNamesExcludePreserved;
var assemblyCache = new AssemblyCache(MetaUtil.CreateHotUpdateAndAOTAssemblyResolver(EditorUserBuildSettings.activeBuildTarget, hotUpdateDllNames));
var validator = new AccessPolicyConfigValidator(assemblyCache);

var accessPolicy = reader.GetAccessPolicy();
validator.ValidateRules(accessPolicy);
validator.ValidateTargets(accessPolicy, new List<string> { "Tests2" });
}
```

## 预校验程序集是否满足AccessPolicy

`Assembly.Load`加载程序集时不检查程序集中是否存在非法调用,运行过程中第一次调用某函数时才检查调用该函数是否符合AccessPolicy,这带来不便。
`HybridCLR.Editor.Security.AssemblyValidator`用于离线预校验assembly中所有调用是否符合AccessPolicy。

示例代码如下:

```csharp
public static void ValidateAssembly()
{
var reader = new XmlAccessPolicyReader();
reader.LoadXmlFile("Assets/AccessPolicy/AccessPolicy.xml");
var validator = new AssemblyValidator(reader.GetAccessPolicy());
string test2DllPath = $"{SettingsUtil.GetHotUpdateDllsOutputDirByTarget(EditorUserBuildSettings.activeBuildTarget)}/Tests2.dll";
var mod = ModuleDefMD.Load(test2DllPath);
validator.ValidateAssembly(mod);
}

```

## 运行时设置访问策略

RuntimeApi类中提供了LoadAccessPolicy函数用于设置访问策略。运行过程中可以多次调用该函数更新访问策略。
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,37 +12,37 @@ Then you cannot call any function of that type, including class constructors (fu
```xml
<AccessPolicy>

<Rule id="DisableIO">
<assembly fullname="mscorlib">
<type fullname="System.IO.*"/> disable
<type fullname="System.IO.File" access="1"/> enable
</assembly>
</Rule>

<Rule id="DisableReflection">
<assembly fullname="mscorlib">
<type fullname="System.Reflection.*"/>
</assembly>
</Rule>

<Rule id="DisableHybridCLR">
<assembly fullname="HybridCLR.Runtime">
<type fullname="*"/>
</assembly>
</Rule>

<Target assembly="Tests2" accessAssemblyNotInRules="0" rules="DisableReflection,DisableIO,DisableHybridCLR"/>
<Rule id="DisableIO">
<assembly fullname="mscorlib">
<type fullname="System.IO.*"/> disable
<type fullname="System.IO.File" access="1"/> enable
</assembly>
</Rule>

<Rule id="DisableReflection">
<assembly fullname="mscorlib">
<type fullname="System.Reflection.*"/>
</assembly>
</Rule>

<Rule id="DisableHybridCLR">
<assembly fullname="HybridCLR.Runtime">
<type fullname="*"/>
</assembly>
</Rule>

<Target assembly="Tests2" accessAssemblyNotInRules="0" rules="DisableReflection,DisableIO,DisableHybridCLR"/>

</AccessPolicy>

```


### Configuration rules
## Configuration rules

The top-level tag is AccessPolicy, which contains 0-N Rule and Target configuration items.

#### Rule
### Rule

Each Rule contains access control rules for multiple assemblies. Each Rule will calculate a set of types that restrict access. The final set of restricted access is the union of all Rules. That is, as long as a Rule restricts access to a certain type,
Then access to this type is ultimately not allowed.
Expand All @@ -52,7 +52,7 @@ Then access to this type is ultimately not allowed.
|id|Attribute|No|The id of the Rule. String type, cannot be empty, must be globally unique |
|assembly|Sub-element|| For the restricted set of a single assembly, a Rule can contain 0-N assemblies. There cannot be an assembly with the same name under the same Rule, but there can be an assembly with the same name between different Rules|

#### assembly
### assembly

A set of restriction rules for a single assembly configures which types of access to that assembly are prohibited.

Expand All @@ -65,15 +65,15 @@ In the same assembly, if there are multiple rules related to a certain type, the

```xml
<assembly fullname="mscorlib">
<type fullname="System.IO.*"/> disable
<type fullname="System.IO.File" access="1"/> enable
<type fullname="System.IO.*"/> disable
<type fullname="System.IO.File" access="1"/> enable
</assembly>
```

In the above example, although `<type fullname="System.IO.*"/>` prohibits access to all types under the `System.IO` namespace, including `System.IO.File`, the following
`<type fullname="System.IO.File" access="1"/>` has separately canceled the access restrictions on `System.IO.File`.

#### type
### type

Restrictive rules for one or a group of types.

Expand All @@ -83,7 +83,7 @@ Restrictive rules for one or a group of types.
|access|Attribute|Yes|Whether it is accessible, the default is false. It is true when `true, yes, 1` is taken and false when `false, no, 0` is taken|


#### Target
### Target

Target configures access restriction rules that are imposed on the code in the assembly.

Expand All @@ -106,10 +106,57 @@ The sample code is as follows:
{
string accessPolicyDir = Application.dataPath + "/AccessPolicy";
AccessPolicyUtil.ConvertXmlAccessPolicyToBinaryAccessPolicy($"{accessPolicyDir}/AccessPolicy.xml",
$"{accessPolicyDir}/AccessPolicy.bytes");
$"{accessPolicyDir}/AccessPolicy.bytes");
}
```

## Verify the legality of AccessPolicy configuration

In practice, it is easy to incorrectly fill in names such as `assembly.fullname` and `type.fullname`, resulting in the expected access control policy not being correctly implemented.
`HybridCLR.Editor.Security.AccessPolicyConfigValidator` is used to check the validity of AccessPolicy to avoid this error.

|Function|Description|
|-|-|
|ValidateRules|Check the legality of Rule rules|
|ValidateTargets|Check the legality of Target rules|

The sample code is as follows:

```csharp
public static void ValidateAccessPolicy()
{
var reader = new XmlAccessPolicyReader();
reader.LoadXmlFile("Assets/AccessPolicy/AccessPolicy.xml");
List<string> hotUpdateDllNames = SettingsUtil.HotUpdateAssemblyNamesExcludePreserved;
var assemblyCache = new AssemblyCache(MetaUtil.CreateHotUpdateAndAOTAssemblyResolver(EditorUserBuildSettings.activeBuildTarget, hotUpdateDllNames));
var validator = new AccessPolicyConfigValidator(assemblyCache);

var accessPolicy = reader.GetAccessPolicy();
validator.ValidateRules(accessPolicy);
validator.ValidateTargets(accessPolicy, new List<string> { "Tests2" });
}
```

## Pre-verify whether the assembly meets AccessPolicy

`Assembly.Load` does not check whether there are illegal calls in the assembly when loading the assembly. During the running process, it only checks whether the calling function complies with the AccessPolicy when a function is called for the first time, which causes inconvenience.
`HybridCLR.Editor.Security.AssemblyValidator` is used to offline pre-verify whether all calls in the assembly comply with AccessPolicy.

The sample code is as follows:

```csharp
public static void ValidateAssembly()
{
var reader = new XmlAccessPolicyReader();
reader.LoadXmlFile("Assets/AccessPolicy/AccessPolicy.xml");
var validator = new AssemblyValidator(reader.GetAccessPolicy());
string test2DllPath = $"{SettingsUtil.GetHotUpdateDllsOutputDirByTarget(EditorUserBuildSettings.activeBuildTarget)}/Tests2.dll";
var mod = ModuleDefMD.Load(test2DllPath);
validator.ValidateAssembly(mod);
}

```

## Set access policy at runtime

The RuntimeApi class provides the LoadAccessPolicy function for setting access policies. This function can be called multiple times during operation to update the access policy.
Expand All @@ -120,8 +167,8 @@ The sample code is as follows:

void LoadAccessPolicy()
{
byte[] accessPolicyData = File.ReadAllBytes($"{Application.streamingAssetsPath}/AccessPolicy.bin");
RuntimeApi.LoadAccessPolicy(accessPolicyData);
byte[] accessPolicyData = File.ReadAllBytes($"{Application.streamingAssetsPath}/AccessPolicy.bin");
RuntimeApi.LoadAccessPolicy(accessPolicyData);
}

```

0 comments on commit 47106d1

Please sign in to comment.