frostfs-http-gw/docs/authentication.md
Alex Vanin a945a947ac
Some checks failed
/ Vulncheck (push) Successful in 2m19s
/ Builds (push) Has been cancelled
/ Lint (push) Has been cancelled
/ Tests (push) Has been cancelled
[#183] Unlink API.md to README file
This is useful for auto-generated document tools
which parse docs dir.

Signed-off-by: Alex Vanin <a.vanin@yadro.com>
2024-12-17 13:03:02 +00:00

4.1 KiB

Request authentication

HTTP Gateway does not authorize requests. Gateway converts HTTP request to a FrostFS request and signs it with its own private key.

You can always upload files to public containers (open for anyone to put objects into), but for restricted containers you need to explicitly allow PUT operations for a request signed with your HTTP Gateway keys.

If you don't want to manage gateway's secret keys and adjust policies when gateway configuration changes (new gate, key rotation, etc) or you plan to use public services, there is an option to let your application backend (or you) to issue Bearer Tokens and pass them from the client via gate down to FrostFS level to grant access.

FrostFS Bearer Token basically is a container owner-signed policy (refer to FrostFS documentation for more details). There are two options to pass them to gateway:

  • "Authorization" header with "Bearer" type and base64-encoded token in credentials field
  • "Bearer" cookie with base64-encoded token contents

For example, you have a mobile application frontend with a backend part storing data in FrostFS. When a user authorizes in the mobile app, the backend issues a FrostFS Bearer token and provides it to the frontend. Then, the mobile app may generate some data and upload it via any available FrostFS HTTP Gateway by adding the corresponding header to the upload request. Accessing policy protected data works the same way.

Example

In order to generate a bearer token, you need to have wallet (which will be used to sign the token)

  1. Suppose you have a container with private policy for wallet key
$ frostfs-cli container create -r <endpoint> --wallet <wallet> -policy <policy> --basic-acl 0 --await
CID: 9dfzyvq82JnFqp5svxcREf2iy6XNuifYcJPusEDnGK9Z

$ frostfs-cli ape-manager add -r <endpoint> --wallet <wallet> \
  --target-type container --target-name 9dfzyvq82JnFqp5svxcREf2iy6XNuifYcJPusEDnGK9Z \
  --rule "allow Object.* RequestCondition:"\$Actor:publicKey"=03b09baabff3f6107c7e9acb8721a6fc5618d45b50247a314d82e548702cce8cd5 *" \
  --chain-id <chainID>
  1. Form a Bearer token (10000 is lifetime expiration in epoch) to impersonate HTTP Gateway request as wallet signed request and save it to bearer.json:
{
    "body": {
        "allowImpersonate": true,
        "lifetime": {
            "exp": "10000",
            "nbf": "0",
            "iat": "0"
        }
    },
    "signature": null
}
  1. Sign it with the wallet:
$ frostfs-cli util sign bearer-token --from bearer.json --to signed.json -w <wallet>
  1. Encode to base64 to use in header:
$ base64 -w 0 signed.json
# output: Ck4KKgoECAIQBhIiCiCZGdlbN7DPGPMg9rsWqV+p2XdMzUqknRiexewSFp8kmBIbChk17MUri6OJ0X5ftsHzy7NERDNFB4C92PcaGgMIkE4SZgohAxpsb7vfAso1F0X6hrm6WpRS14WsT3/Ct1SMoqRsT89KEkEEGxKi8GjKSf52YqhppgaOTQHbUsL3jn7SHLqS3ndAQ7NtAATnmRHleZw2V2xRRSRBQdjDC05KK83LhdSax72Fsw==

After that, the Bearer token can be used:

$ curl -F 'file=@cat.jpeg;filename=cat.jpeg' -H "Authorization: Bearer Ck4KKgoECAIQBhIiCiCZGdlbN7DPGPMg9rsWqV+p2XdMzUqknRiexewSFp8kmBIbChk17MUri6OJ0X5ftsHzy7NERDNFB4C92PcaGgMIkE4SZgohAxpsb7vfAso1F0X6hrm6WpRS14WsT3/Ct1SMoqRsT89KEkEEGxKi8GjKSf52YqhppgaOTQHbUsL3jn7SHLqS3ndAQ7NtAATnmRHleZw2V2xRRSRBQdjDC05KK83LhdSax72Fsw==" \
  http://localhost:8082/upload/BJeErH9MWmf52VsR1mLWKkgF3pRm3FkubYxM7TZkBP4K
# output:
# {
#	"object_id": "DhfES9nVrFksxGDD2jQLunGADfrXExxNwqXbDafyBn9X",
#	"container_id": "BJeErH9MWmf52VsR1mLWKkgF3pRm3FkubYxM7TZkBP4K"
# }
Note: Bearer Token owner

You can specify exact key who can use Bearer Token (gateway wallet address). To do this, encode wallet address in base64 format

$ echo 'NhVtreTTCoqsMQV5Wp55fqnriiUCpEaKm3' | base58 --decode | base64
# output: NezFK4ujidF+X7bB88uzREQzRQeAvdj3Gg==

Then specify this value in Bearer Token Json

{
    "body": {
        "ownerID": {
            "value": "NezFK4ujidF+X7bB88uzREQzRQeAvdj3Gg=="
        },
        ...
Note: Policy override

Instead of impersonation, you can define the set of policies that will be applied to the request sender. This allows to restrict access to specific operation and specific objects without giving full impersonation control to the token user.