[#334] Add auth doc #336
313
docs/authentication.md
Normal file
|
@ -0,0 +1,313 @@
|
|||
# Authentication and authorization scheme
|
||||
|
||||
This document describes s3-gw authentication and authorization mechanism.
|
||||
|
||||
## General overview
|
||||
|
||||
Basic provisions:
|
||||
|
||||
* A request to s3-gw can be signed or not (request that isn't signed we will cal 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
|
||||
process.
|
||||
|
||||
<a>
|
||||
<img src="images/authentication/auth-overview.svg" alt="Auth general overview"/>
|
||||
</a>
|
||||
|
||||
There are several participants of 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.
|
||||
|
||||
## Data auth process
|
||||
|
||||
Let's look at the process in more detail:
|
||||
|
||||
<a>
|
||||
<img src="images/authentication/auth-sequence.svg" alt="Auth sequence diagram"/>
|
||||
</a>
|
||||
|
||||
* 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.
|
||||
|
||||
* **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
|
||||
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
|
||||
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
|
||||
match the `AccessDenied` is returned.
|
||||
|
||||
* `AccessBox` also contains `OwnerID` that is related to `AccessKeyId` that was provided. So we have to check if
|
||||
such `OwnerID` exists in `frsotfsid` contract (that stores all registered valid users). If user doesn't exist in
|
||||
contract the `AccessDenied` is returned.
|
||||
|
||||
* **Authorization steps**:
|
||||
* To know if user has access right to do what he wants to do we must find appropriate access policies. Such policies
|
||||
are stored in `policy` contract and locally (can be manged using [control api](#control-auth-process)). So we need
|
||||
to get policies from contract and [check them](#policies) along with local to decide if user has access right. If
|
||||
he doesn't have such right the `AccessDenied` is returned.
|
||||
|
||||
* 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.
|
||||
|
||||
### AWS Signing
|
||||
|
||||
Every interaction with FrostFS S3 gateway is either authenticated or anonymous. This section explains request
|
||||
authentication with the AWS Signature Version 4 algorithm. More info in AWS documentation:
|
||||
|
||||
* [Authenticating Requests (AWS Signature Version 4)](https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html)
|
||||
* [Signing AWS API requests](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_aws-signing.html)
|
||||
|
||||
#### Authentication Methods
|
||||
|
||||
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
|
||||
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,
|
||||
see [Authenticating Requests: Using the Authorization Header (AWS Signature Version 4)](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-auth-using-authorization-header.html).
|
||||
* **Query string parameters** - You can use a query string to express a request entirely in a URL. In this case, you use
|
||||
query parameters to provide request information, including the authentication information. Because the request
|
||||
signature is part of the URL, this type of URL is often referred to as a presigned URL. You can use presigned URLs to
|
||||
embed clickable links, which can be valid for up to seven days, in HTML. For more information,
|
||||
see [Authenticating Requests: Using Query Parameters (AWS Signature Version 4)](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html).
|
||||
|
||||
FrostFS S3 also supports browser-based uploads that use HTTP POST requests. With an HTTP POST request, you can upload
|
||||
alexvanin marked this conversation as resolved
Outdated
|
||||
content to FrostFS S3 directly from the browser. For information about authenticating POST requests,
|
||||
see [Browser-Based Uploads Using POST (AWS Signature Version 4)](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-UsingHTTPPOST.html).
|
||||
|
||||
#### Introduction to Signing Requests
|
||||
|
||||
Authentication information that you send in a request must include a signature. To calculate a signature, you first
|
||||
concatenate select request elements to form a string, referred to as the string to sign. You then use a signing key to
|
||||
calculate the hash-based message authentication code (HMAC) of the string to sign.
|
||||
|
||||
In AWS Signature Version 4, you don't use your secret access key to sign the request. Instead, you first use your secret
|
||||
access key to derive a signing key. The derived signing key is specific to the date, service, and Region. For more
|
||||
information about how to derive a signing key in different programming languages, see Examples of how to derive a
|
||||
signing key for Signature Version 4.
|
||||
|
||||
The following diagram illustrates the general process of computing a signature.
|
||||
|
||||
<a>
|
||||
<img src="images/authentication/aws-signing.png" alt="AWS Signing"/>
|
||||
</a>
|
||||
|
||||
The string to sign depends on the request type. For example, when you use the HTTP Authorization header or the query
|
||||
parameters for authentication, you use a varying combination of request elements to create the string to sign. For an
|
||||
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
|
||||
final step is the signing key.
|
||||
|
||||
Upon receiving an authenticated request, FrostFS S3 servers re-create the signature by using the authentication
|
||||
information that is contained in the request. If the signatures match, FrostFS S3 processes your request; otherwise, the
|
||||
request is rejected.
|
||||
alexvanin marked this conversation as resolved
Outdated
alexvanin
commented
`To calculate...`
|
||||
|
||||
##### Signature Calculations for the Authorization Header
|
||||
|
||||
To calculate a signature, you first need a string to sign. You then calculate a HMAC-SHA256 hash of the string to sign
|
||||
by using a signing key. The following diagram illustrates the process, including the various components of the string
|
||||
that you create for signing.
|
||||
|
||||
When FrostFS S3 receives an authenticated request, it computes the signature and then compares it with the signature
|
||||
that you provided in the request. For that reason, you must compute the signature by using the same method that is used
|
||||
by FrostFS S3. The process of putting a request in an agreed-upon form for signing is called canonicalization.
|
||||
|
||||
<a>
|
||||
<img src="images/authentication/auth-header-signing.png" alt="Signature Calculations for the Authorization Header"/>
|
||||
</a>
|
||||
|
||||
See detains in [AWS documentation](https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-header-based-auth.html).
|
||||
|
||||
#### s3-gw
|
||||
|
||||
s3-gw support 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)
|
||||
* [Browser-Based Uploads Using POST](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-UsingHTTPPOST.html)
|
||||
|
||||
All these methods provide `AccessKeyId` and signature. Using `AccessKeyId` s3-gw can get `SecretAccessKey`
|
||||
(see [data auth](#data-auth-process)) to compute signature using exactly the same mechanics
|
||||
as [client does](#introduction-to-signing-requests). After signature calculation the s3-gw just compares signatures and
|
||||
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
|
||||
storage node.
|
||||
|
||||
Based on this object s3 credentials are formed:
|
||||
|
||||
* `AccessKeyId` - is concatenated container id and object id (`<cid>0<oid>`) of `AccessBox` (
|
||||
e.g. `2XGRML5EW3LMHdf64W2DkBy1Nkuu4y4wGhUj44QjbXBi05ZNvs8WVwy1XTmSEkcVkydPKzCgtmR7U3zyLYTj3Snxf`)
|
||||
* `SecretAccessKey` - hex-encoded random generated 32 bytes (that is encrypted and stored in object payload)
|
||||
|
||||
> **Note**: sensitive info in `AccessBox` is [encrypted](#encryption), so only someone who posses specific private key
|
||||
> can decrypt such info.
|
||||
|
||||
`AccessBox` has the following structure:
|
||||
|
||||
<a>
|
||||
<img src="images/authentication/accessbox-object.svg" alt="AccessBox object structure"/>
|
||||
</a>
|
||||
|
||||
**Headers:**
|
||||
|
||||
`AccessBox` object has the following attributes (at least them, it also can contain custom one):
|
||||
|
||||
* `Timestamp` - unix timestamp when 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))
|
||||
* `S3-Access-Box-CRDT-Name` - `AccessKeyId` of credentials to which current `AccessBox` is related (
|
||||
see [AccessBox versions](#accessbox-versions))
|
||||
* `FilePath` - just object name
|
||||
|
||||
**Payload:**
|
||||
|
||||
The `AccessBox` payload is an encoded [AccessBox protobuf type](../creds/accessbox/accessbox.proto) .
|
||||
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)
|
||||
* Encrypted tokens:
|
||||
* `SecretAccessKey` - hex-encoded random generated 32 bytes
|
||||
* Marshaled bearer token - more detail
|
||||
in [spec](https://git.frostfs.info/TrueCloudLab/frostfs-api/src/commit/4c68d92468503b10282c8a92af83a56f170c8a3a/acl/types.proto#L189)
|
||||
* Marshaled session token - more detail
|
||||
in [spec](https://git.frostfs.info/TrueCloudLab/frostfs-api/src/commit/4c68d92468503b10282c8a92af83a56f170c8a3a/session/types.proto#L89)
|
||||
* Container placement policies:
|
||||
* `LocationsConstraint` - name of location constraint that can be used to create bucket/container using s3
|
||||
credentials related to this `AccessBox`
|
||||
* Marshaled placement policy - more detail
|
||||
in [spec](https://git.frostfs.info/TrueCloudLab/frostfs-api/src/commit/4c68d92468503b10282c8a92af83a56f170c8a3a/netmap/types.proto#L111)
|
||||
|
||||
#### AccessBox versions
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
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
|
||||
by `S3-Access-Box-CRDT-Name`.
|
||||
|
||||
##### Search algorithm
|
||||
|
||||
To support scenario from previous section and find appropriate version of `AccessBox` (that contains more recent and
|
||||
relevant data) the following sequence is used:
|
||||
|
||||
<a>
|
||||
<img src="images/authentication/accessbox-search.svg" alt="AccessBox search process"/>
|
||||
</a>
|
||||
|
||||
* Search all object whose attribute `S3-Access-Box-CRDT-Name` is equal to `AccessKeyId` (extract container id
|
||||
from `AccessKeyId` that has format: `<cid>0<oid>`).
|
||||
* Get metadata for these object using `HEAD` requests (not `Get` to reduce network traffic)
|
||||
* Sort all these objects by creation epoch and object id
|
||||
* Pick last object id (If no object is found then extract object id from `AccessKeyId` that has format: `<cid>0<oid>`.
|
||||
We need to do this because versions of `AccessBox` can miss the `S3-Access-Box-CRDT-Name` attribute.)
|
||||
* Get appropriate object from FrostFS storage
|
||||
* Decrypt `AccessBox` (see [encryption](#encryption))
|
||||
|
||||
#### Encryption
|
||||
|
||||
Each `AccessBox` contains sensitive information (`AccessSecretKey`, bearer/session tokens etc.) that must be protected
|
||||
and available only to trusted parties (in our case it's a s3-gw).
|
||||
|
||||
To encrypt/decrypt data the authenticated encryption with associated
|
||||
data ([AEAD](https://en.wikipedia.org/wiki/Authenticated_encryption)) is used. The encryption algorithm
|
||||
is [ChaCha20-Poly1305](https://en.wikipedia.org/wiki/ChaCha20-Poly1305) ([RFC](https://datatracker.ietf.org/doc/html/rfc7905)).
|
||||
|
||||
Is the following algorithm the ECDSA keys (with curve implements NIST P-256 (FIPS 186-3, section D.2.3) also known as
|
||||
secp256r1 or prime256v1) is used (unless otherwise stated).
|
||||
|
||||
**Encryption:**
|
||||
|
||||
* Create ephemeral key (`SeedKey`), it's need to generate shared secret
|
||||
* Generate random 32-byte (that after hex-encoded be `SecretAccessKey`) or use existing secret access key
|
||||
(if `AccessBox` is being updated rather than creating brand new)
|
||||
* Generate shared secret as [ECDH](https://en.wikipedia.org/wiki/Elliptic-curve_Diffie%E2%80%93Hellman)
|
||||
* Derive 32-byte key using shared secret from previous step with key derivation function based on
|
||||
HMAC with SHA256 [HKDF](https://en.wikipedia.org/wiki/HKDF)
|
||||
* Encrypt marshaled [Tokens](../creds/accessbox) using derived key
|
||||
with [ChaCha20-Poly1305](https://en.wikipedia.org/wiki/ChaCha20-Poly1305) algorithm without additional data.
|
||||
|
||||
**Decryption:**
|
||||
|
||||
* Get public part of `SeedKey` from `AccessBox`
|
||||
* Generate shared secret as follows:
|
||||
* Make scalar curve multiplication of public part of `SeedKey` and private part of s3-gw key
|
||||
* Use `X` part of multiplication (with zero padding at the beginning to fit 32-byte)
|
||||
* Derive 32-byte key using shared secret from previous step with key derivation function based on
|
||||
HMAC with SHA256 [HKDF](https://en.wikipedia.org/wiki/HKDF)
|
||||
alexvanin marked this conversation as resolved
Outdated
alexvanin
commented
Add a little more details about the way S3 Gateway creates request context to pass it to APE. Add a little more details about the way S3 Gateway creates request context to pass it to APE.
|
||||
* Decrypt encrypted marshaled [Tokens](../creds/accessbox) using derived key
|
||||
with [ChaCha20-Poly1305](https://en.wikipedia.org/wiki/ChaCha20-Poly1305) algorithm without additional data.
|
||||
|
||||
### Policies
|
||||
|
||||
The main repository that contains policy implementation is https://git.frostfs.info/TrueCloudLab/policy-engine.
|
||||
|
||||
Policies can be stored locally (using [control api](#control-auth-process)) or in `policy` contract. When policies check
|
||||
is performed the following algorithm is applied:
|
||||
|
||||
* Check local policies:
|
||||
* If any rule was matched return checking result.
|
||||
* Check contract policies:
|
||||
* If any rule was matched return checking result.
|
||||
* 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`.
|
||||
|
||||
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.
|
||||
|
||||
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):
|
||||
|
||||
* `Owner` - address of owner that is performing request (this is taken from bearer token from `AccessBox`)
|
||||
* `frostfsid:groupID` - groups to which the owner belongs (this is taken from `frostfsid` contract)
|
||||
|
||||
## Control auth process
|
||||
|
||||
There are control path [grpc api](../pkg/service/control/service.proto) in s3-gw that also has their own authentication
|
||||
and authorization process.
|
||||
|
||||
But this process is quite straight forward:
|
||||
|
||||
* Get grpc request
|
||||
* Check if signing key belongs to [allowed key list](configuration.md#control-section) (that is located in config file)
|
||||
* Validate signature
|
||||
|
||||
For signing process the asymmetric encryption based on elliptic curves (`ECDSA_SHA512`) is used.
|
||||
For more details see the appropriate code
|
||||
in [frostfs-api](https://git.frostfs.info/TrueCloudLab/frostfs-api/src/commit/4c68d92468503b10282c8a92af83a56f170c8a3a/refs/types.proto#L94)
|
||||
and [frostfs-api-go](https://git.frostfs.info/TrueCloudLab/frostfs-api-go/src/commit/a85146250b312fcdd6da9a71285527fed544234f/refs/types.go#L38).
|
44
docs/images/authentication/accessbox-object.puml
Normal file
|
@ -0,0 +1,44 @@
|
|||
@startuml
|
||||
|
||||
package AccessBox {
|
||||
map Tokens {
|
||||
SecretKey => Private key
|
||||
BearerToken => Encoded bearer token
|
||||
SessionTokens => List of encoded session tokens
|
||||
}
|
||||
|
||||
map Gate {
|
||||
GateKey => Encoded public gate key
|
||||
Encrypted tokens *--> Tokens
|
||||
}
|
||||
|
||||
map ContainerPolicy {
|
||||
LocationConstraint => Policy name
|
||||
PlacementPolicy => Encoded placement policy
|
||||
}
|
||||
|
||||
map Box {
|
||||
SeedKey => Encoded public seed key
|
||||
List of Gates *--> Gate
|
||||
List of container policies *--> ContainerPolicy
|
||||
}
|
||||
|
||||
|
||||
map ObjectAttributes {
|
||||
Timestamp => 1710418478
|
||||
_~_SYSTEM_~_EXPIRATION_EPOCH => 10801
|
||||
S3-CRDT-Versions-Add => 5ZNvs8WVwy1XTmSEkcVkydPKzCgtmR7U3zyLYTj3Snxf,9bLtL1EsUpuSiqmHnqFf6RuT6x5QMLMNBqx7vCcCcNhy
|
||||
S3-Access-Box-CRDT-Name => 2XGRML5EW3LMHdf64W2DkBy1Nkuu4y4wGhUj44QjbXBi05ZNvs8WVwy1XTmSEkcVkydPKzCgtmR7U3zyLYTj3Snxf
|
||||
FilePath => 1710418478_access.box
|
||||
}
|
||||
|
||||
map FrostFSObject {
|
||||
Header *-> ObjectAttributes
|
||||
Payload *--> Box
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@enduml
|
60
docs/images/authentication/accessbox-object.svg
Normal file
After Width: | Height: | Size: 13 KiB |
29
docs/images/authentication/accessbox-search.puml
Normal file
|
@ -0,0 +1,29 @@
|
|||
@startuml
|
||||
|
||||
User -> "S3-GW": AccessKey
|
||||
"S3-GW" -> "FrostFS Node": Search objects
|
||||
|
||||
note right
|
||||
Search by exact attribute matching:
|
||||
**S3-Access-Box-CRDT-Name:** //AccessKey//
|
||||
end note
|
||||
|
||||
"FrostFS Node" --> "S3-GW": AccessBox objects ids
|
||||
|
||||
"S3-GW" -> "FrostFS Node" : Head AccessBox objects
|
||||
"FrostFS Node" --> "S3-GW": AccessBox object headers
|
||||
|
||||
"S3-GW" -> "S3-GW": Choose latest AccessBox
|
||||
|
||||
note left
|
||||
Sort AccessBox headers by creation epoch
|
||||
and then by ObjectID
|
||||
Pick last
|
||||
end note
|
||||
|
||||
"S3-GW" -> "FrostFS Node" : Get AccessBox object
|
||||
"FrostFS Node" --> "S3-GW": AccessBox object
|
||||
|
||||
"S3-GW" -> "S3-GW": Decrypt and validate AccessBox
|
||||
|
||||
@enduml
|
39
docs/images/authentication/accessbox-search.svg
Normal file
After Width: | Height: | Size: 8.3 KiB |
BIN
docs/images/authentication/auth-header-signing.png
Normal file
After Width: | Height: | Size: 133 KiB |
25
docs/images/authentication/auth-overview.puml
Normal file
|
@ -0,0 +1,25 @@
|
|||
@startuml
|
||||
!include <c4/C4_Container.puml>
|
||||
AddElementTag("smart-contract", $bgColor=#0abab5)
|
||||
|
||||
Person(user, "User", "User with or without credentials")
|
||||
|
||||
System_Boundary(c1, "FrostFS") {
|
||||
Container(s3, "S3 Gateway", $descr="AWS S3 compatible gate")
|
||||
Container(stor, "FrostFS Storage", $descr="Storage service")
|
||||
}
|
||||
|
||||
System_Boundary(c3, "Blockchain") {
|
||||
Interface "NeoGo"
|
||||
Container(ffsid, "FrostFS ID", $tags="smart-contract", $descr="Stores namespaces and users")
|
||||
Container(policy, "Policy", $tags="smart-contract", $descr="Stores APE rules")
|
||||
}
|
||||
|
||||
Rel_R(user, s3, "Requests", "HTTP")
|
||||
Rel_R(s3, stor, "Get data to validate request, store objects")
|
||||
Rel_D(s3, NeoGo, "Get data to validate request")
|
||||
Rel("NeoGo", ffsid, "Fetch users")
|
||||
Rel("NeoGo", policy, "Fetch policies")
|
||||
|
||||
SHOW_LEGEND(true)
|
||||
@enduml
|
611
docs/images/authentication/auth-overview.svg
Normal file
|
@ -0,0 +1,611 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentStyleType="text/css" height="660px" preserveAspectRatio="none" style="width:851px;height:660px;background:#FFFFFF;" version="1.1" viewBox="0 0 851 660" width="851px" zoomAndPan="magnify"><defs/><g><!--MD5=[84dda40acb3410cad7262261daba2aaf]
|
||||
cluster c1--><g id="cluster_c1"><rect fill="none" height="152" rx="2.5" ry="2.5" style="stroke:#444444;stroke-width:1.0;stroke-dasharray:7.0,7.0;" width="587" x="258" y="7"/><text fill="#444444" font-family="sans-serif" font-size="16" font-weight="bold" lengthAdjust="spacing" textLength="71" x="516" y="23.8516">FrostFS</text><text fill="#444444" font-family="sans-serif" font-size="12" font-weight="bold" lengthAdjust="spacing" textLength="61" x="521" y="38.7637">[System]</text></g><!--MD5=[fb252dd5a834d4be8567d0df3f6bbec4]
|
||||
cluster c3--><g id="cluster_c3"><rect fill="none" height="301" rx="2.5" ry="2.5" style="stroke:#444444;stroke-width:1.0;stroke-dasharray:7.0,7.0;" width="405" x="259" y="243.5"/><text fill="#444444" font-family="sans-serif" font-size="16" font-weight="bold" lengthAdjust="spacing" textLength="95" x="414" y="260.3516">Blockchain</text><text fill="#444444" font-family="sans-serif" font-size="12" font-weight="bold" lengthAdjust="spacing" textLength="61" x="431" y="275.2637">[System]</text></g><!--MD5=[b165ca7cce796f881c879adda4a6bef9]
|
||||
entity s3--><g id="elem_s3"><rect fill="#438DD5" height="85.1875" rx="2.5" ry="2.5" style="stroke:#3C7FC0;stroke-width:0.5;" width="199" x="274.5" y="58"/><text fill="#FFFFFF" font-family="sans-serif" font-size="16" font-weight="bold" lengthAdjust="spacing" textLength="108" x="320" y="82.8516">S3 Gateway</text><text fill="#FFFFFF" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="10" x="369" y="97.7637">[]</text><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="4" x="372" y="113.5889"> </text><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="175" x="288.5" y="129.8857">AWS S3 compatible gate</text></g><!--MD5=[b631bc93683c8d3c6bcd86869bd62c2d]
|
||||
entity stor--><g id="elem_stor"><rect fill="#438DD5" height="85.1875" rx="2.5" ry="2.5" style="stroke:#3C7FC0;stroke-width:0.5;" width="169" x="660.5" y="58"/><text fill="#FFFFFF" font-family="sans-serif" font-size="16" font-weight="bold" lengthAdjust="spacing" textLength="149" x="670.5" y="82.8516">FrostFS Storage</text><text fill="#FFFFFF" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="10" x="740" y="97.7637">[]</text><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="4" x="743" y="113.5889"> </text><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="111" x="691.5" y="129.8857">Storage service</text></g><!--MD5=[d75780de534459f9083ff96c63e26824]
|
||||
entity NeoGo--><g id="elem_NeoGo"><ellipse cx="374" cy="323.5" fill="#F1F1F1" rx="8" ry="8" style="stroke:#181818;stroke-width:0.5;"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="48" x="350" y="353.4951">NeoGo</text></g><!--MD5=[a1c7fbed12783ec305c3357d72c64f9e]
|
||||
entity ffsid--><g id="elem_ffsid"><rect fill="#0ABAB5" height="101.4844" rx="2.5" ry="2.5" style="stroke:#3C7FC0;stroke-width:0.5;" width="198" x="275" y="427.5"/><text fill="#FFFFFF" font-family="sans-serif" font-size="16" font-weight="bold" lengthAdjust="spacing" textLength="96" x="326" y="452.3516">FrostFS ID</text><text fill="#FFFFFF" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="10" x="369" y="467.2637">[]</text><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="4" x="372" y="483.0889"> </text><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="170" x="289" y="499.3857">Stores namespaces and</text><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="38" x="355" y="515.6826">users</text></g><!--MD5=[4361443624774238dacd0e01c3165ecf]
|
||||
entity policy--><g id="elem_policy"><rect fill="#0ABAB5" height="85.1875" rx="2.5" ry="2.5" style="stroke:#3C7FC0;stroke-width:0.5;" width="139" x="508.5" y="435.5"/><text fill="#FFFFFF" font-family="sans-serif" font-size="16" font-weight="bold" lengthAdjust="spacing" textLength="52" x="552" y="460.3516">Policy</text><text fill="#FFFFFF" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="10" x="573" y="475.2637">[]</text><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="4" x="576" y="491.0889"> </text><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="115" x="522.5" y="507.3857">Stores APE rules</text></g><!--MD5=[8fc3522a43f8c7199df5e09e5bb0188e]
|
||||
entity user--><g id="elem_user"><rect fill="#08427B" height="135.5156" rx="2.5" ry="2.5" style="stroke:#073B6F;stroke-width:0.5;" width="168" x="7" y="32.5"/><image height="48" width="48" x="67" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAIAAADYYG7QAAACD0lEQVR4Xu2YoU4EMRCGT+4j8Ai8AhaH4QHgAUjQuFMECUgMIUgwJAgMhgQsAYUiJCiQIBBY+EITsjfTdme6V24v4c8vyGbb+ZjOtN0bNcvjQXmkH83WvYBWto6PLm6v7p7uH1/w2fXD+PBycX1Pv2l3IdDm/vn7x+dXQiAubRzoURa7gRZWd0iGRIiJbOnhnfYBQZNJjNbuyY2eJG8fkDE3bbG4ep6MHUAsgYxmE3nVs6VsBWJSGccsOlFPmLIViMzLOB7pCVO2AtHJMohH7Fh6zqitQK7m0rJvAVYgGcEpe//PLdDz65sM4pF9N7ICcXDKIB5Nv6j7tD0NoSdM2QrU9Gg0ewE1LqBhHR3BBdvj2vapnidjHxD/q6vd7Pvhr31AwcY8eXMTXAKECZZJFXuEq27aLgQK5uLMohCenGGuGewOxSjBvYBqeG6B+Nqiblggdjnc+ZXDy+FNFpFzw76O3UBAROuXh6FoiAcf5g9eTvUgzy0nWg6I8cXHRUpg5bOVBCo+KDpFajOf23GgPme7RSQ+lacIENUgJ6gg1k6HjgOlqnLqip4tEuhv0hNEMXUD0clyXE3p6pZA0S2nnvTlXwLJEZWlb7cTQH1+USgTN4VhAenm/wea1OCAOmqo6fE1WCb9WSKBah+rbUWPWAmE2Rvk0ApiB45eOyNAzU8xcTvj8KvkKEoOaIYeHNA3ZuygAvFMUO0AAAAASUVORK5CYII=" y="42.5"/><text fill="#FFFFFF" font-family="sans-serif" font-size="16" font-weight="bold" lengthAdjust="spacing" textLength="42" x="70" y="105.3516">User</text><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="4" x="89" y="122.1201"> </text><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="140" x="21" y="138.417">User with or without</text><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="79" x="51.5" y="154.7139">credentials</text></g><!--MD5=[52d0c115c7d06b979b7f69659773ccc0]
|
||||
link user to s3--><g id="link_user_s3"><path d="M175.14,100.5 C203.78,100.5 236.2,100.5 266.42,100.5 " fill="none" id="user-to-s3" style="stroke:#666666;stroke-width:1.0;"/><polygon fill="#666666" points="274.47,100.5,266.47,97.5,266.47,103.5,274.47,100.5" style="stroke:#666666;stroke-width:1.0;"/><text fill="#666666" font-family="sans-serif" font-size="12" font-weight="bold" lengthAdjust="spacing" textLength="63" x="193.25" y="80.6387">Requests</text><text fill="#666666" font-family="sans-serif" font-size="12" font-style="italic" lengthAdjust="spacing" textLength="40" x="204.75" y="94.6074">[HTTP]</text></g><!--MD5=[22d466a8c2458259cbad703a0636b8fb]
|
||||
link s3 to stor--><g id="link_s3_stor"><path d="M473.91,100.5 C529.33,100.5 597.81,100.5 652.08,100.5 " fill="none" id="s3-to-stor" style="stroke:#666666;stroke-width:1.0;"/><polygon fill="#666666" points="660.32,100.5,652.32,97.5,652.32,103.5,660.32,100.5" style="stroke:#666666;stroke-width:1.0;"/><text fill="#666666" font-family="sans-serif" font-size="12" font-weight="bold" lengthAdjust="spacing" textLength="136" x="497" y="80.6387">Get data to validate</text><text fill="#666666" font-family="sans-serif" font-size="12" font-weight="bold" lengthAdjust="spacing" textLength="150" x="492" y="94.6074">request, store objects</text></g><!--MD5=[8c98dd26c815ae7a8024bcc2d9dd4f66]
|
||||
link s3 to NeoGo--><g id="link_s3_NeoGo"><path d="M374,143.07 C374,192.21 374,271.65 374,305.9 " fill="none" id="s3-to-NeoGo" style="stroke:#666666;stroke-width:1.0;"/><polygon fill="#666666" points="374,314.3,377,306.3,371,306.3,374,314.3" style="stroke:#666666;stroke-width:1.0;"/><text fill="#666666" font-family="sans-serif" font-size="12" font-weight="bold" lengthAdjust="spacing" textLength="136" x="375" y="210.6387">Get data to validate</text><text fill="#666666" font-family="sans-serif" font-size="12" font-weight="bold" lengthAdjust="spacing" textLength="53" x="418.5" y="224.6074">request</text></g><!--MD5=[67f0c0ebd6d2a23c30e202ac0cd81435]
|
||||
link NeoGo to ffsid--><g id="link_NeoGo_ffsid"><path d="M374,332.7 C374,348.95 374,386.52 374,419.25 " fill="none" id="NeoGo-to-ffsid" style="stroke:#666666;stroke-width:1.0;"/><polygon fill="#666666" points="374,427.45,377,419.45,371,419.45,374,427.45" style="stroke:#666666;stroke-width:1.0;"/><text fill="#666666" font-family="sans-serif" font-size="12" font-weight="bold" lengthAdjust="spacing" textLength="79" x="375" y="394.6387">Fetch users</text></g><!--MD5=[d37da9b99a3aca6bfa9447725e2e6374]
|
||||
link NeoGo to policy--><g id="link_NeoGo_policy"><path d="M383.06,329.95 C399.4,339.87 434.74,361.78 463,382.5 C483.22,397.33 504.63,414.49 523.43,430.09 " fill="none" id="NeoGo-to-policy" style="stroke:#666666;stroke-width:1.0;"/><polygon fill="#666666" points="529.7,435.31,525.4816,427.88,521.6363,432.4858,529.7,435.31" style="stroke:#666666;stroke-width:1.0;"/><text fill="#666666" font-family="sans-serif" font-size="12" font-weight="bold" lengthAdjust="spacing" textLength="93" x="483" y="394.6387">Fetch policies</text></g><rect fill="none" height="16.2969" style="stroke:none;stroke-width:1.0;" width="236" x="584" y="568.5"/><text fill="#000000" font-family="sans-serif" font-size="14" font-weight="bold" lengthAdjust="spacing" textLength="59" x="584" y="581.4951">Legend</text><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="4" x="643" y="581.4951"> </text><rect fill="#08427B" height="16.2969" style="stroke:none;stroke-width:1.0;" width="236" x="584" y="584.7969"/><text fill="#073B6F" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="8" x="588" y="597.792">▯</text><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="4" x="596" y="597.792"> </text><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="49" x="604" y="597.792">person</text><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="4" x="657" y="597.792"> </text><rect fill="#438DD5" height="16.2969" style="stroke:none;stroke-width:1.0;" width="236" x="584" y="601.0938"/><text fill="#3C7FC0" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="8" x="588" y="614.0889">▯</text><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="4" x="596" y="614.0889"> </text><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="68" x="604" y="614.0889">container</text><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="4" x="676" y="614.0889"> </text><rect fill="#0ABAB5" height="16.2969" style="stroke:none;stroke-width:1.0;" width="236" x="584" y="617.3906"/><text fill="#0ABAB5" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="8" x="588" y="630.3857">▯</text><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="4" x="596" y="630.3857"> </text><text fill="#66622E" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="208" x="604" y="630.3857">smart-contract (no text color)</text><text fill="#FFFFFF" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="4" x="816" y="630.3857"> </text><line style="stroke:none;stroke-width:1.0;" x1="584" x2="820" y1="568.5" y2="568.5"/><line style="stroke:none;stroke-width:1.0;" x1="584" x2="820" y1="584.7969" y2="584.7969"/><line style="stroke:none;stroke-width:1.0;" x1="584" x2="820" y1="601.0938" y2="601.0938"/><line style="stroke:none;stroke-width:1.0;" x1="584" x2="820" y1="617.3906" y2="617.3906"/><line style="stroke:none;stroke-width:1.0;" x1="584" x2="820" y1="633.6875" y2="633.6875"/><line style="stroke:none;stroke-width:1.0;" x1="584" x2="584" y1="568.5" y2="633.6875"/><line style="stroke:none;stroke-width:1.0;" x1="820" x2="820" y1="568.5" y2="633.6875"/><!--MD5=[c02d88aa5b998c40021c1d715125d393]
|
||||
@startuml
|
||||
!include <c4/C4_Container.puml>
|
||||
AddElementTag("smart-contract", $bgColor=#0abab5)
|
||||
|
||||
Person(user, "User", "User with or without credentials")
|
||||
|
||||
System_Boundary(c1, "FrostFS") {
|
||||
Container(s3, "S3 Gateway", $descr="AWS S3 compatible gate")
|
||||
Container(stor, "FrostFS Storage", $descr="Storage service")
|
||||
}
|
||||
|
||||
System_Boundary(c3, "Blockchain") {
|
||||
Interface "NeoGo"
|
||||
Container(ffsid, "FrostFS ID", $tags="smart-contract", $descr="Stores namespaces and users")
|
||||
Container(policy, "Policy", $tags="smart-contract", $descr="Stores APE rules")
|
||||
}
|
||||
|
||||
Rel_R(user, s3, "Requests", "HTTP")
|
||||
Rel_R(s3, stor, "Get data to validate request, store objects")
|
||||
Rel_D(s3, NeoGo, "Get data to validate request")
|
||||
Rel("NeoGo", ffsid, "Fetch users")
|
||||
Rel("NeoGo", policy, "Fetch policies")
|
||||
|
||||
SHOW_LEGEND(true)
|
||||
@enduml
|
||||
|
||||
@startuml
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
skinparam defaultTextAlignment center
|
||||
|
||||
skinparam wrapWidth 200
|
||||
skinparam maxMessageSize 150
|
||||
|
||||
skinparam LegendBorderColor transparent
|
||||
skinparam LegendBackgroundColor transparent
|
||||
skinparam LegendFontColor #FFFFFF
|
||||
|
||||
skinparam shadowing<<legendArea>> false
|
||||
skinparam rectangle<<legendArea>> {
|
||||
backgroundcolor #00000000
|
||||
bordercolor #00000000
|
||||
}
|
||||
|
||||
skinparam rectangle {
|
||||
StereotypeFontSize 12
|
||||
shadowing false
|
||||
}
|
||||
|
||||
skinparam database {
|
||||
StereotypeFontSize 12
|
||||
shadowing false
|
||||
}
|
||||
|
||||
skinparam queue {
|
||||
StereotypeFontSize 12
|
||||
shadowing false
|
||||
}
|
||||
|
||||
skinparam arrow {
|
||||
Color #666666
|
||||
FontColor #666666
|
||||
FontSize 12
|
||||
}
|
||||
|
||||
skinparam actor {
|
||||
StereotypeFontSize 12
|
||||
shadowing false
|
||||
style awesome
|
||||
}
|
||||
|
||||
skinparam person {
|
||||
StereotypeFontSize 12
|
||||
shadowing false
|
||||
}
|
||||
|
||||
skinparam package {
|
||||
StereotypeFontSize 6
|
||||
StereotypeFontColor transparent
|
||||
FontStyle plain
|
||||
BackgroundColor transparent
|
||||
}
|
||||
|
||||
skinparam rectangle<<boundary>> {
|
||||
Shadowing false
|
||||
StereotypeFontSize 6
|
||||
StereotypeFontColor transparent
|
||||
FontColor #444444
|
||||
BorderColor #444444
|
||||
BackgroundColor transparent
|
||||
BorderStyle dashed
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
skinparam rectangle<<person>> {
|
||||
StereotypeFontColor #FFFFFF
|
||||
FontColor #FFFFFF
|
||||
BackgroundColor #08427B
|
||||
BorderColor #073B6F
|
||||
}
|
||||
skinparam database<<person>> {
|
||||
StereotypeFontColor #FFFFFF
|
||||
FontColor #FFFFFF
|
||||
BackgroundColor #08427B
|
||||
BorderColor #073B6F
|
||||
}
|
||||
skinparam queue<<person>> {
|
||||
StereotypeFontColor #FFFFFF
|
||||
FontColor #FFFFFF
|
||||
BackgroundColor #08427B
|
||||
BorderColor #073B6F
|
||||
}
|
||||
skinparam actor<<person>> {
|
||||
StereotypeFontColor #08427B
|
||||
FontColor #08427B
|
||||
BackgroundColor #08427B
|
||||
BorderColor #073B6F
|
||||
}
|
||||
skinparam person<<person>> {
|
||||
StereotypeFontColor #FFFFFF
|
||||
FontColor #FFFFFF
|
||||
BackgroundColor #08427B
|
||||
BorderColor #073B6F
|
||||
}
|
||||
|
||||
|
||||
skinparam rectangle<<external_person>> {
|
||||
StereotypeFontColor #FFFFFF
|
||||
FontColor #FFFFFF
|
||||
BackgroundColor #686868
|
||||
BorderColor #8A8A8A
|
||||
}
|
||||
skinparam database<<external_person>> {
|
||||
StereotypeFontColor #FFFFFF
|
||||
FontColor #FFFFFF
|
||||
BackgroundColor #686868
|
||||
BorderColor #8A8A8A
|
||||
}
|
||||
skinparam queue<<external_person>> {
|
||||
StereotypeFontColor #FFFFFF
|
||||
FontColor #FFFFFF
|
||||
BackgroundColor #686868
|
||||
BorderColor #8A8A8A
|
||||
}
|
||||
skinparam actor<<external_person>> {
|
||||
StereotypeFontColor #686868
|
||||
FontColor #686868
|
||||
BackgroundColor #686868
|
||||
BorderColor #8A8A8A
|
||||
}
|
||||
skinparam person<<external_person>> {
|
||||
StereotypeFontColor #FFFFFF
|
||||
FontColor #FFFFFF
|
||||
BackgroundColor #686868
|
||||
BorderColor #8A8A8A
|
||||
}
|
||||
|
||||
|
||||
skinparam rectangle<<system>> {
|
||||
StereotypeFontColor #FFFFFF
|
||||
FontColor #FFFFFF
|
||||
BackgroundColor #1168BD
|
||||
BorderColor #3C7FC0
|
||||
}
|
||||
skinparam database<<system>> {
|
||||
StereotypeFontColor #FFFFFF
|
||||
FontColor #FFFFFF
|
||||
BackgroundColor #1168BD
|
||||
BorderColor #3C7FC0
|
||||
}
|
||||
skinparam queue<<system>> {
|
||||
StereotypeFontColor #FFFFFF
|
||||
FontColor #FFFFFF
|
||||
BackgroundColor #1168BD
|
||||
BorderColor #3C7FC0
|
||||
}
|
||||
skinparam actor<<system>> {
|
||||
StereotypeFontColor #1168BD
|
||||
FontColor #1168BD
|
||||
BackgroundColor #1168BD
|
||||
BorderColor #3C7FC0
|
||||
}
|
||||
skinparam person<<system>> {
|
||||
StereotypeFontColor #FFFFFF
|
||||
FontColor #FFFFFF
|
||||
BackgroundColor #1168BD
|
||||
BorderColor #3C7FC0
|
||||
}
|
||||
|
||||
|
||||
skinparam rectangle<<external_system>> {
|
||||
StereotypeFontColor #FFFFFF
|
||||
FontColor #FFFFFF
|
||||
BackgroundColor #999999
|
||||
BorderColor #8A8A8A
|
||||
}
|
||||
skinparam database<<external_system>> {
|
||||
StereotypeFontColor #FFFFFF
|
||||
FontColor #FFFFFF
|
||||
BackgroundColor #999999
|
||||
BorderColor #8A8A8A
|
||||
}
|
||||
skinparam queue<<external_system>> {
|
||||
StereotypeFontColor #FFFFFF
|
||||
FontColor #FFFFFF
|
||||
BackgroundColor #999999
|
||||
BorderColor #8A8A8A
|
||||
}
|
||||
skinparam actor<<external_system>> {
|
||||
StereotypeFontColor #999999
|
||||
FontColor #999999
|
||||
BackgroundColor #999999
|
||||
BorderColor #8A8A8A
|
||||
}
|
||||
skinparam person<<external_system>> {
|
||||
StereotypeFontColor #FFFFFF
|
||||
FontColor #FFFFFF
|
||||
BackgroundColor #999999
|
||||
BorderColor #8A8A8A
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
sprite $person [48x48/16] {
|
||||
000000000000000000000000000000000000000000000000
|
||||
000000000000000000000000000000000000000000000000
|
||||
0000000000000000000049BCCA7200000000000000000000
|
||||
0000000000000000006EFFFFFFFFB3000000000000000000
|
||||
00000000000000001CFFFFFFFFFFFF700000000000000000
|
||||
0000000000000001EFFFFFFFFFFFFFF80000000000000000
|
||||
000000000000000CFFFFFFFFFFFFFFFF6000000000000000
|
||||
000000000000007FFFFFFFFFFFFFFFFFF100000000000000
|
||||
00000000000001FFFFFFFFFFFFFFFFFFF900000000000000
|
||||
00000000000006FFFFFFFFFFFFFFFFFFFF00000000000000
|
||||
0000000000000BFFFFFFFFFFFFFFFFFFFF40000000000000
|
||||
0000000000000EFFFFFFFFFFFFFFFFFFFF70000000000000
|
||||
0000000000000FFFFFFFFFFFFFFFFFFFFF80000000000000
|
||||
0000000000000FFFFFFFFFFFFFFFFFFFFF80000000000000
|
||||
0000000000000DFFFFFFFFFFFFFFFFFFFF60000000000000
|
||||
0000000000000AFFFFFFFFFFFFFFFFFFFF40000000000000
|
||||
00000000000006FFFFFFFFFFFFFFFFFFFE00000000000000
|
||||
00000000000000EFFFFFFFFFFFFFFFFFF800000000000000
|
||||
000000000000007FFFFFFFFFFFFFFFFFF100000000000000
|
||||
000000000000000BFFFFFFFFFFFFFFFF5000000000000000
|
||||
0000000000000001DFFFFFFFFFFFFFF70000000000000000
|
||||
00000000000000000BFFFFFFFFFFFF500000000000000000
|
||||
0000000000000000005DFFFFFFFFA1000000000000000000
|
||||
0000000000000000000037ABB96100000000000000000000
|
||||
000000000000000000000000000000000000000000000000
|
||||
000000000000000000000000000000000000000000000000
|
||||
000000000000025788300000000005886410000000000000
|
||||
000000000007DFFFFFFD9643347BFFFFFFFB400000000000
|
||||
0000000004EFFFFFFFFFFFFFFFFFFFFFFFFFFB1000000000
|
||||
000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFD200000000
|
||||
00000006FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE10000000
|
||||
0000003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB0000000
|
||||
000000BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5000000
|
||||
000003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD000000
|
||||
000009FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF200000
|
||||
00000DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF600000
|
||||
00000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF800000
|
||||
00001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA00000
|
||||
00001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB00000
|
||||
00001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB00000
|
||||
00001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB00000
|
||||
00001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA00000
|
||||
00000EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF700000
|
||||
000006FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE100000
|
||||
0000008FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD3000000
|
||||
000000014555555555555555555555555555555300000000
|
||||
000000000000000000000000000000000000000000000000
|
||||
000000000000000000000000000000000000000000000000
|
||||
}
|
||||
|
||||
sprite $person2 [48x48/16] {
|
||||
0000000000000000000049BCCA7200000000000000000000
|
||||
0000000000000000006EFFFFFFFFB3000000000000000000
|
||||
00000000000000001CFFFFFFFFFFFF700000000000000000
|
||||
0000000000000001EFFFFFFFFFFFFFF80000000000000000
|
||||
000000000000000CFFFFFFFFFFFFFFFF6000000000000000
|
||||
000000000000007FFFFFFFFFFFFFFFFFF100000000000000
|
||||
00000000000001FFFFFFFFFFFFFFFFFFF900000000000000
|
||||
00000000000006FFFFFFFFFFFFFFFFFFFF00000000000000
|
||||
0000000000000BFFFFFFFFFFFFFFFFFFFF40000000000000
|
||||
0000000000000EFFFFFFFFFFFFFFFFFFFF70000000000000
|
||||
0000000000000FFFFFFFFFFFFFFFFFFFFF80000000000000
|
||||
0000000000000FFFFFFFFFFFFFFFFFFFFF80000000000000
|
||||
0000000000000DFFFFFFFFFFFFFFFFFFFF60000000000000
|
||||
0000000000000AFFFFFFFFFFFFFFFFFFFF40000000000000
|
||||
00000000000006FFFFFFFFFFFFFFFFFFFE00000000000000
|
||||
00000000000000EFFFFFFFFFFFFFFFFFF800000000000000
|
||||
000000000000007FFFFFFFFFFFFFFFFFF100000000000000
|
||||
000000000000000BFFFFFFFFFFFFFFFF5000000000000000
|
||||
0000000000000001DFFFFFFFFFFFFFF70000000000000000
|
||||
00000000000000000BFFFFFFFFFFFF500000000000000000
|
||||
0000000000000000005DFFFFFFFFA1000000000000000000
|
||||
0000000000000000000037ABB96100000000000000000000
|
||||
000000000002578888300000000005888864100000000000
|
||||
0000000007DFFFFFFFFD9643347BFFFFFFFFFB4000000000
|
||||
00000004EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB10000000
|
||||
0000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD2000000
|
||||
000006FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE100000
|
||||
00003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB00000
|
||||
0000BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF50000
|
||||
0003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD0000
|
||||
0009FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2000
|
||||
000DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6000
|
||||
000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000
|
||||
001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB000
|
||||
001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB000
|
||||
001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB000
|
||||
001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA000
|
||||
000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8000
|
||||
000DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6000
|
||||
0009FFFFFFFF8FFFFFFFFFFFFFFFFFFFFFF8FFFFFFFF2000
|
||||
0003FFFFFFFF8FFFFFFFFFFFFFFFFFFFFFF8FFFFFFFD0000
|
||||
0000BFFFFFFF8FFFFFFFFFFFFFFFFFFFFFF8FFFFFFF50000
|
||||
00003FFFFFFF8FFFFFFFFFFFFFFFFFFFFFF8FFFFFFB00000
|
||||
000006FFFFFF8FFFFFFFFFFFFFFFFFFFFFF8FFFFFE100000
|
||||
0000007FFFFF8FFFFFFFFFFFFFFFFFFFFFF8FFFFD2000000
|
||||
00000004EFFF8FFFFFFFFFFFFFFFFFFFFFF8FFFB10000000
|
||||
0000000007DF8FFFFFFFFFFFFFFFFFFFFFF8FB4000000000
|
||||
000000000002578888888888888888888864100000000000
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
skinparam rectangle<<container>> {
|
||||
StereotypeFontColor #FFFFFF
|
||||
FontColor #FFFFFF
|
||||
BackgroundColor #438DD5
|
||||
BorderColor #3C7FC0
|
||||
}
|
||||
skinparam database<<container>> {
|
||||
StereotypeFontColor #FFFFFF
|
||||
FontColor #FFFFFF
|
||||
BackgroundColor #438DD5
|
||||
BorderColor #3C7FC0
|
||||
}
|
||||
skinparam queue<<container>> {
|
||||
StereotypeFontColor #FFFFFF
|
||||
FontColor #FFFFFF
|
||||
BackgroundColor #438DD5
|
||||
BorderColor #3C7FC0
|
||||
}
|
||||
skinparam actor<<container>> {
|
||||
StereotypeFontColor #438DD5
|
||||
FontColor #438DD5
|
||||
BackgroundColor #438DD5
|
||||
BorderColor #3C7FC0
|
||||
}
|
||||
skinparam person<<container>> {
|
||||
StereotypeFontColor #FFFFFF
|
||||
FontColor #FFFFFF
|
||||
BackgroundColor #438DD5
|
||||
BorderColor #3C7FC0
|
||||
}
|
||||
|
||||
|
||||
skinparam rectangle<<external_container>> {
|
||||
StereotypeFontColor #FFFFFF
|
||||
FontColor #FFFFFF
|
||||
BackgroundColor #B3B3B3
|
||||
BorderColor #A6A6A6
|
||||
}
|
||||
skinparam database<<external_container>> {
|
||||
StereotypeFontColor #FFFFFF
|
||||
FontColor #FFFFFF
|
||||
BackgroundColor #B3B3B3
|
||||
BorderColor #A6A6A6
|
||||
}
|
||||
skinparam queue<<external_container>> {
|
||||
StereotypeFontColor #FFFFFF
|
||||
FontColor #FFFFFF
|
||||
BackgroundColor #B3B3B3
|
||||
BorderColor #A6A6A6
|
||||
}
|
||||
skinparam actor<<external_container>> {
|
||||
StereotypeFontColor #B3B3B3
|
||||
FontColor #B3B3B3
|
||||
BackgroundColor #B3B3B3
|
||||
BorderColor #A6A6A6
|
||||
}
|
||||
skinparam person<<external_container>> {
|
||||
StereotypeFontColor #FFFFFF
|
||||
FontColor #FFFFFF
|
||||
BackgroundColor #B3B3B3
|
||||
BorderColor #A6A6A6
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
skinparam rectangle<<smart-contract>> {
|
||||
BackgroundColor #0abab5
|
||||
}
|
||||
skinparam database<<smart-contract>> {
|
||||
BackgroundColor #0abab5
|
||||
}
|
||||
skinparam queue<<smart-contract>> {
|
||||
BackgroundColor #0abab5
|
||||
}
|
||||
skinparam actor<<smart-contract>> {
|
||||
StereotypeFontColor #0abab5
|
||||
FontColor #0abab5
|
||||
BackgroundColor #0abab5
|
||||
}
|
||||
skinparam person<<smart-contract>> {
|
||||
BackgroundColor #0abab5
|
||||
}
|
||||
|
||||
|
||||
|
||||
rectangle "<$person>\n==User\n\n User with or without credentials" <<person>> as user
|
||||
|
||||
rectangle "==FrostFS\n<size:12>[System]</size>" <<boundary>> as c1 {
|
||||
rectangle "==S3 Gateway\n//<size:12>[]</size>//\n\n AWS S3 compatible gate" <<container>> as s3
|
||||
rectangle "==FrostFS Storage\n//<size:12>[]</size>//\n\n Storage service" <<container>> as stor
|
||||
}
|
||||
|
||||
rectangle "==Blockchain\n<size:12>[System]</size>" <<boundary>> as c3 {
|
||||
Interface "NeoGo"
|
||||
rectangle "==FrostFS ID\n//<size:12>[]</size>//\n\n Stores namespaces and users" <<smart-contract>><<container>> as ffsid
|
||||
rectangle "==Policy\n//<size:12>[]</size>//\n\n Stores APE rules" <<smart-contract>><<container>> as policy
|
||||
}
|
||||
|
||||
user -RIGHT->> s3 : **Requests**\n//<size:12>[HTTP]</size>//
|
||||
s3 -RIGHT->> stor : **Get data to validate request, store objects**
|
||||
s3 -DOWN->> NeoGo : **Get data to validate request**
|
||||
NeoGo - ->> ffsid : **Fetch users**
|
||||
NeoGo - ->> policy : **Fetch policies**
|
||||
|
||||
hide stereotype
|
||||
legend right
|
||||
<#00000000,#00000000>|<color:#000000>**Legend**</color> |
|
||||
|<#08427B><color:#073B6F> <U+25AF></color> <color:#FFFFFF> person </color> |
|
||||
|<#438DD5><color:#3C7FC0> <U+25AF></color> <color:#FFFFFF> container </color> |
|
||||
|<#0abab5><color:#0abab5> <U+25AF></color> <color:#66622E> smart-contract (no text color) </color> |
|
||||
endlegend
|
||||
@enduml
|
||||
|
||||
PlantUML version 1.2022.13(Sat Nov 19 16:22:17 MSK 2022)
|
||||
(GPL source distribution)
|
||||
Java Runtime: OpenJDK Runtime Environment
|
||||
JVM: OpenJDK 64-Bit Server VM
|
||||
Default Encoding: UTF-8
|
||||
Language: en
|
||||
Country: US
|
||||
--></g></svg>
|
After Width: | Height: | Size: 25 KiB |
60
docs/images/authentication/auth-sequence.puml
Normal file
|
@ -0,0 +1,60 @@
|
|||
@startuml
|
||||
|
||||
participant User
|
||||
participant "S3-GW"
|
||||
collections "FrostFS Storage"
|
||||
|
||||
User -> "S3-GW": Request
|
||||
|
||||
group signed request
|
||||
|
||||
"S3-GW" -> "FrostFS Storage": Find Access Box
|
||||
"FrostFS Storage" -> "FrostFS Storage": Check request
|
||||
|
||||
alt #pink Check failure
|
||||
"FrostFS Storage" -->> "S3-GW": Access Denied
|
||||
"S3-GW" -->> User: Access Denied
|
||||
end
|
||||
|
||||
"FrostFS Storage" -->> "S3-GW": Access Box
|
||||
"S3-GW" -> "S3-GW": Check sign
|
||||
|
||||
alt #pink Check failure
|
||||
"S3-GW" -->> User: Access Denied
|
||||
end
|
||||
|
||||
"S3-GW" -> "frostfsid contract": Find user
|
||||
"frostfsid contract" -->> "S3-GW": User info
|
||||
"S3-GW" -> "S3-GW": Check user info
|
||||
|
||||
alt #pink Check failure
|
||||
"S3-GW" -->> User: Access Denied
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
"S3-GW" -> "policy contract": Get policies
|
||||
"policy contract" -->> "S3-GW": Policies
|
||||
"S3-GW" -> "S3-GW": Check policy
|
||||
|
||||
alt #pink Check failure
|
||||
"S3-GW" -->> User: Access Denied
|
||||
end
|
||||
|
||||
"S3-GW" -> "FrostFS Storage": User Request
|
||||
"FrostFS Storage" -> "FrostFS Storage": Check request
|
||||
|
||||
alt #pink Check failure
|
||||
"FrostFS Storage" -->> "S3-GW": Access Denied
|
||||
"S3-GW" -->> User: Access Denied
|
||||
end
|
||||
|
||||
"FrostFS Storage" -->> "S3-GW": Response
|
||||
"S3-GW" -->> User: Response
|
||||
|
||||
box "Neo Go"
|
||||
participant "frostfsid contract"
|
||||
participant "policy contract"
|
||||
end box
|
||||
|
||||
@enduml
|
70
docs/images/authentication/auth-sequence.svg
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
docs/images/authentication/aws-signing.png
Normal file
After Width: | Height: | Size: 35 KiB |
This part is focused on the way how request is signed. It is useful for the client, but we want to emphasize here how Gateway validates this signature.
Can we be a bit more explicit down there and in
AccessBox
section, how gateway uses accessbox fields to re-create signature from the request and compare it. Let's focus more on this process.