diff --git a/docs/authentication.md b/docs/authentication.md index dfe859f..60f2e4f 100644 --- a/docs/authentication.md +++ b/docs/authentication.md @@ -6,23 +6,23 @@ This document describes s3-gw authentication and authorization mechanism. Basic provisions: -* A request to s3-gw can be signed or not (request that isn't signed we will cal anonymous or just anon) +* A request to s3-gw can be signed or not (request that isn't signed we will call anonymous or just anon) * To manage resources (buckets/objects) using s3-gw you must have appropriate access rights Each request must be authenticated (at least as anonymous) and authorized. The following scheme shows components that -are involved to this +are involved in this process. Auth general overview -There are several participants of this process: +There are several participants in this process: 1. User that make a request 2. S3-GW that accepts a request 3. FrostFS Storage that stores AccessObjects (objects are needed for authentication) -4. Blockchain smart contracts (`frostfsid`, `policy`) that stores user info and access rules. +4. Blockchain smart contracts (`frostfsid`, `policy`) that store user info and access rules. ## Data auth process @@ -32,23 +32,23 @@ Let's look at the process in more detail: Auth sequence diagram -* First of all, someone make a request. If request is signed we will check its signature (`Authentication`) after that - we will check access rights using policies (`Auhorization`). For anonymous requests only authorization be performed. +* First of all, someone makes a request. If request is signed we will check its signature (`Authentication`) after that + we will check access rights using policies (`Auhorization`). For anonymous requests only authorization is performed. * **Authentication steps**: * Each signed request is provided with `AccessKeyId` and signature. So if request is signed we must check its - signature. To do this we must know the `AccessKeyId`/`SecretAccessKey` pair (How the signature is calculated - using this pair see [signing](#aws-signing). Client and server (s3-gw) use the same credentials and algorithm to - compute signature). The `AccessKeyId` is a public part of credentials, and it's passed to gate in request. The + signature. To do this we must know the `AccessKeyId`/`SecretAccessKey` pair (For how the signature is calculated + using this pair, see [signing](#aws-signing). Client and server (s3-gw) use the same credentials and algorithm to + compute signature). The `AccessKeyId` is a public part of credentials, and it's passed to the gate in request. The private part of credentials is `SecretAccessKey` and it's encrypted and stored in [AccessBox](#accessbox). So on - this step we must find appropriate `AccessBox` in FrostFS storage node (How to find appropriate `AccessBox` - knowing `AccessKeyId` see [search algorithm](#search-algorithm)). On this stage we can get `AccessDenied` from + this step we must find appropriate `AccessBox` in FrostFS storage node (For how to find appropriate `AccessBox` + knowing `AccessKeyId`, see [search algorithm](#search-algorithm)). On this stage we can get `AccessDenied` from FrostFS storage node if the s3-gw doesn't have permission to read this `AccessBox` object. - * After successful retrieving object we must extract `SecretAccessKey` from it. Since it's encrypted the s3-gw must - decrypt (see [encryption](#encryption)) this object using own private key and `SeedKey` from `AccessBox` - (see [AccessBox inner structure](#accessbox)). After s3-gw have got the `AccessKeyId`/`SecretAccessKey` pair it - [calculate signature](#aws-signing) and compare got signature with provided withing request. If signature doesn't + * After successfully retrieving the object we must extract `SecretAccessKey` from it. Since it's encrypted, the s3-gw must + decrypt (see [encryption](#encryption)) this object using its own private key and `SeedKey` from `AccessBox` + (see [AccessBox inner structure](#accessbox)). After s3-gw got the `AccessKeyId`/`SecretAccessKey` pair it + [calculates signature](#aws-signing) and compares this signature with one provided by the request. If signature doesn't match the `AccessDenied` is returned. * `AccessBox` also contains `OwnerID` that is related to `AccessKeyId` that was provided. So we have to check if @@ -63,7 +63,7 @@ Let's look at the process in more detail: * After successful authentication and authorization the request will be processed by s3-gw business logic and finally be propagated to FrostFS storage node which also performs some auth checks and can return `AccessDenied`. If this happens - s3-gw also returns `AccessDenied` as response. + s3-gw also returns `AccessDenied` as a response. ### AWS Signing @@ -77,7 +77,7 @@ authentication with the AWS Signature Version 4 algorithm. More info in AWS docu You can express authentication information by using one of the following methods: -* **HTTP Authorization header** - Using the HTTP Authorization header is the most common method of authenticating an +* **HTTP Authorization header** - Using the HTTP Authorization header is the most common method of authenticating FrostFS S3 request. All the FrostFS S3 REST operations (except for browser-based uploads using POST requests) require this header. For more information about the Authorization header value, and how to calculate signature and related options, @@ -114,7 +114,7 @@ parameters for authentication, you use a varying combination of request elements HTTP POST request, the POST policy in the request is the string you sign. For more information about computing string to sign, follow links provided at the end of this section. -For signing key, the diagram shows series of calculations, where result of each step you feed into the next step. The +For signing key, the diagram shows series of calculations, where the result of each step you feed into the next step. The final step is the signing key. Upon receiving an authenticated request, FrostFS S3 servers re-create the signature by using the authentication @@ -139,7 +139,7 @@ See detains in [AWS documentation](https://docs.aws.amazon.com/AmazonS3/latest/A #### s3-gw -s3-gw support the following ways to provide the singed request: +s3-gw supports the following ways to provide the singed request: * [HTTP Authorization header](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-auth-using-authorization-header.html) * [Query string parameters](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html) @@ -153,10 +153,10 @@ if they don't match the access denied is returned. ### AccessBox `AccessBox` is an ordinary object in FrostFS storage. It contains all information that can be used by s3-gw to -successfully authenticate request. Also, it contains data that is required to successful authentication in FrostFS +successfully authenticate request. Also, it contains data that is required for successful authentication in FrostFS storage node. -Based on this object s3 credentials are formed: +Object s3 credentials are formed based on: * `AccessKeyId` - is concatenated container id and object id (`0`) of `AccessBox` ( e.g. `2XGRML5EW3LMHdf64W2DkBy1Nkuu4y4wGhUj44QjbXBi05ZNvs8WVwy1XTmSEkcVkydPKzCgtmR7U3zyLYTj3Snxf`) @@ -173,9 +173,9 @@ Based on this object s3 credentials are formed: **Headers:** -`AccessBox` object has the following attributes (at least them, it also can contain custom one): +`AccessBox` object has the following attributes (at least them, it also can contain custom ones): -* `Timestamp` - unix timestamp when object was created +* `Timestamp` - unix timestamp indicating when the object was created * `__SYSTEM__EXPIRATION_EPOCH` - epoch after which the object isn't available anymore * `S3-CRDT-Versions-Add` - comma separated list of previous versions of `AccessBox` ( see [AccessBox versions](#accessbox-versions)) @@ -190,7 +190,7 @@ It contains: * Seed key - hex-encoded public seed key to compute shared secret using ECDH (see [encryption](#encryption)) * List of gate data: - * Gate public key (so that gate (when it will decrypt data later) know which one item from list it should process) + * Gate public key (so that gate (when it will decrypt data later) know which item from the list it should process) * Encrypted tokens: * `SecretAccessKey` - hex-encoded random generated 32 bytes * Marshaled bearer token - more detail @@ -207,16 +207,16 @@ It contains: Imagine the following scenario: -* There is a system where only one s3-gw exist -* There is a `AccessBox` that can be used by this s3-gw -* User has s3 credentials (`AccessKeyId`/`SecretAccessKey`) related to corresponded `AccessBox` and can successfully +* There is a system where only one s3-gw exists +* There is an `AccessBox` that can be used by this s3-gw +* User has s3 credentials (`AccessKeyId`/`SecretAccessKey`) related to corresponding `AccessBox` and can successfully make request to s3-gw -* The system is expanded and new one s3-gw is added -* User must be able to use the credentials (that he has already had) to make request to new one s3-gw +* The system is expanded and a new s3-gw is added +* User must be able to use the credentials (that he has already had) to make request to the new s3-gw Since `AccessBox` object is immutable and `SecretAccessKey` is encrypted only for restricted list of keys (can be used -(decrypted) only by limited number of s3-gw) we have to create new `AccessBox` that has encrypted secrets for new list -of s3-gw and be related to initial s3 credentials (`AccessKeyId`/`SecretAccessKey`). Such relationship is done +(decrypted) only by limited number of s3-gw) we have to create a new `AccessBox` that has encrypted secrets for a new list +of s3-gw and is related to the initial s3 credentials (`AccessKeyId`/`SecretAccessKey`). Such relation is done by `S3-Access-Box-CRDT-Name`. ##### Search algorithm @@ -285,10 +285,10 @@ is performed the following algorithm is applied: * If no rules were matched return `deny` status. To local and contract policies `deny first` scheme is applied. This means that if several rules were matched for -reqeust (with both statuses `allow` and `deny`) the resulting status be `deny`. +reqeust (with both statuses `allow` and `deny`) the resulting status is `deny`. Policy rules validate if specified request can be performed on the specific resource. Request and resource can contain -some properties and rules can contain conditions on some such properties. +some properties, and rules can contain conditions on some of these properties. In s3-gw resource is `/bucket/object`, `/bucket` or just `/` (if request is trying to list buckets). Currently, request that is checked contains the following properties (so policy rule can contain conditions on them):