diff --git a/docs/ape.md b/docs/ape.md new file mode 100644 index 0000000..a239499 --- /dev/null +++ b/docs/ape.md @@ -0,0 +1,85 @@ +# Access policy engine + +## General overview + +### Purpose + +Access policy engine (APE) is aimed at checking if a request can be performed over a resource by looking up the set chains of rules. + +#### Terms + +| Term | Description | Structure overview | +| -------------- | -------------------------------------------------------------- | -------------- | +| `Request` | The action that is being performed on the `Resource`. | | +| `Resource` | The object that the request is being performed on. Check also [resource.md](./resource.md). | | +| `Chain` | A chain of `Rule`-s defined for a specific target. Chains are strictly distinguished by `Name`-s , i.e. chains with name `ingress` are not intersected with chains with name `s3`. Chains are stored in serialized format. | | +| `Rule` | `Rule` defines which status is returned if `Request` matches all conditions. | | +| `Name` | `Name` of a chain (do not confuse with chain ID). `Name` defines a layer of `Chain`'s usage, so chains are distinguished by `Name`-s. Basically, `Name` refers to a protocol. | String value (`ingress`, `s3`, `iam`). | +| `Target` | A scope of request. `Target` can be either simple (only namespace; only container; only user; only groups) or compound (namespace + container). | | +| `Engine` | `Engine` checks a request in a scope defined by `Target`. First, it is trying to match a request with rules defined in `LocalOverrideStorage` and, then, in `MorphRuleChainStorage`. | | + +#### Details + +Here some entities are overviewed in more detail. + +##### Resource + +`Resource`'s name is strictly formatted, the format is defined by a schema (`native`, `aws` etc.). Examples: + +```bash +# The resource is the particular object with the address within Root namespace +native:object//HRwWbb1bJjRms33kkA21hy4JdPfARaH3fW9NfuNN6Fgj/EbxzAdz5LB4uqxuz6crWKAumBNtZyK2rKsqQP7TdZvwr +# The resource is all objects within the container within Root namespace +native:object//HRwWbb1bJjRms33kkA21hy4JdPfARaH3fW9NfuNN6Fgj/* +# The resource is the particular container within the namespace +native:container/namespace1/HRwWbb1bJjRms33kkA21hy4JdPfARaH3fW9NfuNN6Fgj +# The resource is all containers within the namespace +native:container/namespace1/* +``` + +##### Rule + +`Rule` works out if: + + 1. a requests's operation matches the rule's `Actions`; + 2. resource name matches the rule's `Resources`; + 3. if all (or at least one if `Any=true`) conditions in `Condition` is met. Each condition defines how to retrieve +and compare the retrieved value. If `Condition`'s `Object` is set to `Resource` then the value is retrieved from the +resource's properties (example: container zone attribute). If `Object` is set to `Request`, the it's retrieved from the request's properties (example: actor's public key). + +###### Name matching + +`Resource`'s name in `Rule` may contain wildcard '*' that can be considered as a regular expression: + +```bash +# The resource is all objects within the container within Root namespace +native:object//HRwWbb1bJjRms33kkA21hy4JdPfARaH3fW9NfuNN6Fgj/* +``` + +If an incoming request has such a resource name, then names are matched: + +```bash +# The resource is all objects within the container within Root namespace +native:object//HRwWbb1bJjRms33kkA21hy4JdPfARaH3fW9NfuNN6Fgj/EbxzAdz5LB4uqxuz6crWKAumBNtZyK2rKsqQP7TdZvwr +``` + +If the incoming request has such a resource name that specifies a container's object within namespace, for instance, `namespicy`, +then matching does not work out: + +```bash +# The resource is all objects within the container within `namespicy` namespace: +native:object/namespicy/HRwWbb1bJjRms33kkA21hy4JdPfARaH3fW9NfuNN6Fgj/EbxzAdz5LB4uqxuz6crWKAumBNtZyK2rKsqQP7TdZvwr +``` + +##### Engine + +`Engine` is trying to match the request against **the target** looking up chain rules, firstly, in `LocalOverrideStorage` (these rules are also known as *local overrides*) and then in `MorphRuleChainStorage` (contract `Policy`). Both storages iterate chain rules according to the specified priority of the targets: `namespace` -> `container` -> `user` -> `groups`. + +#### Diagrams + +The diagram demonstrates a scenario in Storage node. The request `A` cannot be performed as APE matched +the request and returned `Access Denied` status. The request `B` is allowed and the client gets `OK` status. +![Storage node](images/ape/storage_node_ape.svg) + +The diagram demonstrates a complex scenario with S3, IAM and Storage node. +![S3 and IAM](images/ape/s3_ape.svg) diff --git a/docs/images/ape/s3_ape.puml b/docs/images/ape/s3_ape.puml new file mode 100644 index 0000000..cf4e2ec --- /dev/null +++ b/docs/images/ape/s3_ape.puml @@ -0,0 +1,61 @@ +@startuml s3 ape + +participant "Client" as client + +participant "IAM" as iam +participant "IAM -> APE converter" as converter + +box "S3" #HotPink + participant "S3 gateway" as s3 +end box + +box "Access Policy Engine (as s3 middleware)" #LightPink + participant "Local override storage" as s3localOverrides + participant "Chain router" as s3chainRouter +end box + +box "Policy contract (shared)" + participant "Morph rule storage" as morphRuleStorage +end box + +box "Access Policy Engine (as storage middleware)" #LightGreen + participant "Chain Router" as storageChainRouter + participant "Local override storage" as storageLocalOverrides +end box + +box "Storage node" #Green + participant "Object service" as obj + participant "Control service" as control +end box + +group Request IAM to set a policy + client -> iam : Set IAM policy + iam -> converter : Convert IAM policy + converter -> iam : Return APE chain + iam -> morphRuleStorage : Store IAM policy and APE chain + iam -> s3localOverrides : Set S3 local overrides + iam -> client : OK +end + +group Request S3 to set a policy + client -> s3 : Set bucket policy + s3 -> converter : Convert IAM policy + converter -> s3 : Return APE chain + s3 -> morphRuleStorage : Store bucket policy and APE chain + s3 -> client : OK +end + +group Get object + client -> s3: GetObject + s3 -> s3chainRouter: Check if APE allows request for S3 + note over s3chainRouter: matching the request with overrides and rules + s3chainRouter -> s3: Status: ALLOW + s3 -> obj: Get object + obj -> storageChainRouter: Check if APE allows the request + note over storageChainRouter : matching the request with overrides and rules + storageChainRouter -> obj: Status: ALLOW + obj -> s3: Response: OK, Object + s3 -> client: Response: OK, Object +end + +@enduml \ No newline at end of file diff --git a/docs/images/ape/s3_ape.svg b/docs/images/ape/s3_ape.svg new file mode 100644 index 0000000..bd119c0 --- /dev/null +++ b/docs/images/ape/s3_ape.svg @@ -0,0 +1,73 @@ +S3Access Policy Engine (as s3 middleware)Policy contract (shared)Access Policy Engine (as storage middleware)Storage nodeClientClientIAMIAMIAM -> APE converterIAM -> APE converterS3 gatewayS3 gatewayLocal override storageLocal override storageChain routerChain routerMorph rule storageMorph rule storageChain RouterChain RouterLocal override storageLocal override storageObject serviceObject serviceControl serviceControl serviceRequest IAM to set a policySet IAM policyConvert IAM policyReturn APE chainStore IAM policy and APE chainSet S3 local overridesOKRequest S3 to set a policySet bucket policyConvert IAM policyReturn APE chainStore bucket policy and APE chainOKGet objectGetObjectCheck if APE allows request for S3matching the request with overrides and rulesStatus: ALLOWGet objectCheck if APE allows the requestmatching the request with overrides and rulesStatus: ALLOWResponse: OK, ObjectResponse: OK, Object \ No newline at end of file diff --git a/docs/images/ape/storage_node_ape.puml b/docs/images/ape/storage_node_ape.puml new file mode 100644 index 0000000..ddf55e3 --- /dev/null +++ b/docs/images/ape/storage_node_ape.puml @@ -0,0 +1,46 @@ +@startuml storage node ape +!pragma teoz true + +participant "Administrator" as administrator +participant "Client" as client + +box "Storage node" #Green + participant "Object service" as obj + participant "Control service" as control +end box + +box "Access Policy Engine" #LightGreen + participant "Local override storage" as localOverrides + participant "Chain Router" as chainRouter + participant "Morph rule storage" as morphRuleStorage +end box + +group Set local override + client -> control: Add local override + control -> localOverrides: Save override in DB + localOverrides -> control: OK + control -> client: OK +end + +group Update state in Policy contract + administrator -> morphRuleStorage: Add chain + morphRuleStorage -> administrator: OK +end + +group Perform a request A + client -> obj : Sending a request + obj -> chainRouter: Check if APE allows the request + note over chainRouter : Fetches local overrides and rules defined for a target/targets and looks for a match + chainRouter -> obj: APE returns status: "ACCESS DENIED" + obj -> client: Response: "the request is denied" +end + +group Perform a request B + client -> obj : Sending a request + obj -> chainRouter: Check if APE allows the request + note over chainRouter : Fetches local overrides and rules defined for a target/targets and looks for a match + chainRouter -> obj: APE returns status: "ALLOW" + obj -> client: Response: "OK" +end + +@enduml \ No newline at end of file diff --git a/docs/images/ape/storage_node_ape.svg b/docs/images/ape/storage_node_ape.svg new file mode 100644 index 0000000..6e84081 --- /dev/null +++ b/docs/images/ape/storage_node_ape.svg @@ -0,0 +1,58 @@ +Storage nodeAccess Policy EngineAdministratorClientObject serviceControl serviceLocal override storageChain RouterMorph rule storageAdministratorClientObject serviceControl serviceLocal override storageChain RouterMorph rule storageSet local overrideAdd local overrideSave override in DBOKOKUpdate state in Policy contractAdd chainOKPerform a request ASending a requestCheck if APE allows the requestFetches local overrides and rules defined for a target/targets and looks for a matchAPE returns status: "ACCESS DENIED"Response: "the request is denied"Perform a request BSending a requestCheck if APE allows the requestFetches local overrides and rules defined for a target/targets and looks for a matchAPE returns status: "ALLOW"Response: "OK" \ No newline at end of file