github.com/NVIDIA/aistore@v1.3.23-0.20240517131212-7df6609be51d/docs/authn.md (about)

     1  ---
     2  layout: post
     3  title: AUTHN
     4  permalink: /docs/authn
     5  redirect_from:
     6   - /authn.md/
     7   - /docs/authn.md/
     8  ---
     9  
    10  AIStore Authentication Server (**AuthN**) provides OAuth 2.0 compliant [JSON Web Tokens](https://datatracker.ietf.org/doc/html/rfc7519) based secure access to AIStore.
    11  
    12  ## AuthN Config
    13  
    14  Note:
    15  
    16  * AuthN configuration directory: `$HOME/.config/ais/authn`
    17  
    18  The directory usually contains plain-text `authn.json` configuration and tokens DB `authn.db`
    19  
    20  > For the most updated system filenames and configuration directories, please see [`fname/fname.go`](https://github.com/NVIDIA/aistore/blob/main/cmn/fname/fname.go) source.
    21  
    22  Examples below use AuthN specific environment variables. Note that all of them are enumerated in:
    23  
    24  * [`api/env/authn.go`](https://github.com/NVIDIA/aistore/blob/main/api/env/authn.go)
    25  
    26  ## Getting started with AuthN: local-playground session
    27  
    28  The following brief and commented sequence assumes that [AIS local playground](getting_started.md#local-playground) is up and running.
    29  
    30  ```console
    31  # 1. Login as administrator (and note that admin user and password can be only
    32  #    provisioned at AuthN deployment time and can never change)
    33  $ ais auth login admin -p admin
    34  Token(/root/.config/ais/cli/auth.token):
    35  ...
    36  
    37  # 2. Connect AIS cluster to *this* authentication server (note that a single AuthN can be shared my multiple AIS clusters)
    38  #    List existing pre-defined roles
    39  $ ais auth show role
    40  ROLE    DESCRIPTION
    41  Admin   AuthN administrator
    42  $ ais auth add cluster myclu http://localhost:8080
    43  $ ais auth show role
    44  ROLE                    DESCRIPTION
    45  Admin                   AuthN administrator
    46  BucketOwner-myclu       Full access to buckets in WayZWN_f4[myclu]
    47  ClusterOwner-myclu      Admin access to WayZWN_f4[myclu]
    48  Guest-myclu             Read-only access to buckets in WayZWN_f4[myclu]
    49  
    50  # 3. Create a bucket (to further demonstrate access permissions in action)
    51  $ ais create ais://nnn
    52  "ais://nnn" created (see https://github.com/NVIDIA/aistore/blob/main/docs/bucket.md#default-bucket-properties)
    53  $ ais put README.md ais://nnn
    54  PUT "README.md" to ais://nnn
    55  
    56  4. Create a new role. A named role is, ultimately, a combination of access permissions
    57  #  and a (user-friendly) description. A given role can be assigned to multiple users.
    58  $ ais auth add role new-role myclu <TAB-TAB>
    59  ADMIN                  DESTROY-BUCKET         HEAD-OBJECT            MOVE-OBJECT            ro
    60  APPEND                 UPDATE-OBJECT          LIST-BUCKETS           PATCH                  rw
    61  CREATE-BUCKET          GET                    LIST-OBJECTS           PROMOTE                SET-BUCKET-ACL
    62  DELETE-OBJECT          HEAD-BUCKET            MOVE-BUCKET            PUT                    su
    63  
    64  # Notice that <TAB-TAB> can be used to both list existing access permissions
    65  # and
    66  # complete those that you started to type.
    67  $ ais auth add role new-role myclu --desc "this is description" LIST-BUCKETS LIST-OBJECTS GET HEAD-BUCKET HEAD-OBJECT ... <TAB-TAB>
    68  
    69  # 5. Show users. Add a new user.
    70  #    We can always utilize one of the prebuilt roles, e.g. `Guest-myclu` for read-only access.
    71  #    But in this example we will use the newly added `new-role`:
    72  $ ais auth show user
    73  NAME    ROLES
    74  admin   Admin
    75  
    76  $ ais auth add user new-user -p 12345 new-role
    77  $ ais auth show user
    78  NAME    ROLES
    79  admin   Admin
    80  new-user Guest-myclu
    81  
    82  # Not showing here is how to add a new role
    83  # (that can be further conveniently used to grant subsets of permissions)
    84  
    85  # 5. Login as `new-user` (added above) and save the token separately as `/tmp/new-user.token`
    86  #    Note that by default the token for a logged-in user will be saved in the
    87  #    $HOME/.config/ais/cli directory
    88  #    (which is always checked if `AIS_AUTHN_TOKEN_FILE` environment is not specified)
    89  
    90  $ ais auth login new-user -p 12345 -f /tmp/new-user.token
    91  Token(/tmp/new-user.token):
    92  ...
    93  
    94  # 6. Perform operations. Note that the `new-user` has a limited `Guest-myclu` access.
    95  $ AIS_AUTHN_TOKEN_FILE=/tmp/new-user.token ais ls ais:
    96  AIS Buckets (1)
    97    ais://nnn
    98  $ AIS_AUTHN_TOKEN_FILE=/tmp/new-user.token ais ls ais://nnn
    99  NAME             SIZE
   100  README.md        8.96KiB
   101  
   102  # However:
   103  $ AIS_AUTHN_TOKEN_FILE=/tmp/new-user.token ais create ais://mmm
   104  Failed to create "ais://mmm": insufficient permissions
   105  
   106  $ AIS_AUTHN_TOKEN_FILE=/tmp/new-user.token ais put LICENSE ais://nnn
   107  Insufficient permissions
   108  ```
   109  
   110  Further references:
   111  
   112  * See [CLI auth subcommand](/docs/cli/auth.md) for all supported command line options and usage examples.
   113  
   114  ---------------------
   115  
   116  ## Table of Contents
   117  
   118  - [Overview](#overview)
   119  - [Environment and configuration](#environment-and-configuration)
   120    - [Notation](#notation)
   121    - [AuthN configuration and log](#authn-configuration-and-log)
   122    - [How to enable AuthN server after deployment](#how-to-enable-authn-server-after-deployment)
   123    - [Using Kubernetes secrets](#using-kubernetes-secrets)
   124  - [REST API](#rest-api)
   125    - [Authorization](#authorization)
   126    - [Tokens](#tokens)
   127    - [Clusters](#clusters)
   128    - [Roles](#roles)
   129    - [Users](#users)
   130    - [Configuration](#configuration)
   131  - [Typical workflow](#typical-workflow)
   132  - [Known limitations](#known-limitations)
   133  
   134  ## Overview
   135  
   136  AIStore Authentication Server (AuthN) provides OAuth 2.0 compliant [JSON Web Tokens](https://datatracker.ietf.org/doc/html/rfc7519) based secure access to AIStore.
   137  
   138  * [Brief introduction to JWT](https://jwt.io/introduction/)
   139  * [Go (language) implementation of JSON Web Tokens](https://github.com/golang-jwt/jwt) that we utilize for AuthN.
   140  
   141  Currently, we only support hash-based message authentication (HMAC) using SHA256 hash.
   142  
   143  AuthN is a standalone server that manages users and tokens. If AuthN is enabled on a cluster,
   144  a client must request a token from AuthN and put it into HTTP headers of every request to the cluster.
   145  Requests without tokens are rejected.
   146  
   147  A typical workflow looks as follows:
   148  
   149  ![AuthN workflow](images/authn_flow.png)
   150  
   151  AuthN generates self-sufficient tokens: a proxy does not need access to AuthN to check permissions.
   152  Though, for security reasons, clusters should be registered at AuthN server.
   153  AuthN broadcasts revoked tokens to all registered clusters, so they updated their blacklists.
   154  
   155  A workflow for the case when a token is revoked and only one cluster is registered.
   156  "AIS Cluster 2" is unregistered and allows requests with revoked token:
   157  
   158  ![Revoke token workflow](images/token_revoke.png)
   159  
   160  AuthN supports both HTTP and HTTPS protocols. By default, AuthN starts as an HTTP server listening on port 52001.
   161  If you enable HTTPS access, make sure that the configuration file options `server_crt` and `server_key` point to the correct SSL certificate and key.
   162  
   163  ## Environment and configuration
   164  
   165  Environment variables used by the deployment script to setup AuthN server:
   166  
   167  | Variable | Default value | Description |
   168  |---|---|---|
   169  | AIS_SECRET_KEY | `aBitLongSecretKey` | A secret key to sign tokens |
   170  | AIS_AUTHN_ENABLED | `false` | Set it to `true` to enable AuthN server and token-based access in AIStore proxy |
   171  | AIS_AUTHN_PORT | `52001` | Port on which AuthN listens to requests |
   172  | AIS_AUTHN_TTL | `24h` | A token expiration time. Can be set to 0 which means "no expiration time" |
   173  | AIS_AUTHN_USE_HTTPS | `false` | Enable HTTPS for AuthN server. If `true`, AuthN server requires also `AIS_SERVER_CRT` and `AIS_SERVER_KEY` to be set |
   174  | AIS_SERVER_CRT | ` ` | OpenSSL certificate. Optional: set it only when secure HTTP is enabled |
   175  | AIS_SERVER_KEY | ` ` | OpenSSL key. Optional: set it only when secure HTTP is enabled |
   176  
   177  All variables can be set at AIStore cluster deployment.
   178  Example of starting a cluster with AuthN enabled:
   179  
   180  ```console
   181  $ AIS_AUTHN_ENABLED=true make deploy
   182  ```
   183  
   184  Note: don't forget to change the default secret key used to sign tokens before starting the deployment process.
   185  
   186  To change AuthN settings after deployment, modify the server's configuration file and restart the server.
   187  If you change the server's secret key, make sure to modify AIStore proxy configuration as well.
   188  
   189  Upon startup, AuthN checks the user list. If it is empty, AuthN creates a default user that can access everything:
   190  user ID is `admin` and password is `admin`. Do not forget to change the user's password for security reasons.
   191  
   192  ### Notation
   193  
   194  In this README:
   195  
   196  > `AUTHSRV` - denotes a (hostname:port) address of a deployed AuthN server
   197  
   198  > `PROXY` - (hostname:port) of a **gateway**(any gateway in a given AIS cluster)
   199  
   200  ### AuthN configuration and log
   201  
   202  | File                 | Location                     |
   203  |----------------------|------------------------------|
   204  | Server configuration | `$AIS_AUTHN_CONF_DIR/authn.json` |
   205  | User database        | `$AIS_AUTHN_CONF_DIR/authn.db`   |
   206  | Log directory        | `$AIS_LOG_DIR/authn/log/`    |
   207  
   208  Note: when AuthN is running, execute `ais auth show config` to find out the current location of all AuthN files.
   209  
   210  ### How to enable AuthN server after deployment
   211  
   212  By default, AIStore deployment currently does not launch the AuthN server.
   213  To start AuthN manually, perform the following steps:
   214  
   215  - Start authn server: <path_to_ais_binaries>/authn -config=<path_to_config_dir>/authn.json. Path to config directory is set at the time of cluster deployment and it is the same as the directory for AIStore proxies and targets
   216  - Update AIS CLI configuration file: change AuthN URL. Alternatively, prepend AuthN URL to every CLI command that uses `auth` subcommand: `AIS_AUTHN_URL=http://10.10.1.190:52001 ais auth COMMAND`
   217  - Change AIStore cluster configuration to enable token-based access and use the same secret as AuthN uses:
   218  
   219  ```console
   220  $ # Change the secret
   221  $ ais config cluster auth.secret SECRET
   222  
   223  $ # Enable cluster-wide authorization
   224  $ ais config cluster auth.enabled true
   225  
   226  $ # Register the cluster at AuthN to receive AuthN messages (e.g, revoked token list)
   227  $ # ais auth add cluster CLUSTER_ALIAS CLUSTER-URL-LIST
   228  $ ais auth add cluster mainCluster http://10.10.1.70:50001 http://10.10.1.71:50001
   229  
   230  $ # Calling AuthN without modifying CLI configuration
   231  $ # Assuming AuthN listens at http://10.10.1.190:52001
   232  $ AIS_AUTHN_URL=http://10.10.1.190:52001 ais auth add cluster mainCluster http://10.10.1.70:50001 http://10.10.1.71:50001
   233  ```
   234  
   235  ### Using Kubernetes secrets
   236  
   237  To increase security, a secret key for token generation can be
   238  put to [Kubernetes secrets](https://kubernetes.io/docs/concepts/configuration/secret/)
   239  instead of keeping them in an AuthN configuration file. When secrets are used, AuthN
   240  overrides configuration values with environment variables set by Kubernetes.
   241  
   242  Add secrets to AuthN pod description:
   243  
   244  ```
   245  apiVersion: v1
   246  kind: Pod
   247  metadata:
   248    name: secret-env-pod
   249  spec:
   250    containers:
   251    - name: container-name
   252          image: image-name
   253          env:
   254            - name: SECRETKEY
   255              valueFrom:
   256                secretKeyRef:
   257                  name: mysecret
   258                  key: secret-key
   259  ```
   260  
   261  In the example above the values in all-capitals are the names of the environment
   262  variables that AuthN looks for. All other values are arbitrary.
   263  
   264  When AuthN pod starts, it loads its configuration from the local file, and then
   265  overrides secret values with ones from the pod's description.
   266  
   267  ## REST API
   268  
   269  ### Authorization
   270  
   271  After deploying the cluster, a superuser role `Admin` and `admin` account are created automatically.
   272  Only users with `Admin` role can manage AuthN. Every request to AuthN(except login one) must
   273  contain authentication token in the header:
   274  
   275  ```
   276  Authorization: Bearer <token-issued-by-AuthN-after-login>
   277  ```
   278  
   279  For curl, it is an argument `-H 'Authorization: Bearer token'`.
   280  
   281  ### Tokens
   282  
   283  AIStore gateways and targets require a valid token in a request header - but only if AuthN is enabled.
   284  
   285  Every token includes the following information (needed to enforce access permissions):
   286  
   287  - User name
   288  - User ACL
   289  - Time when the token expires
   290  
   291  To pass all the checks, the token must not be expired or blacklisted (revoked).
   292  
   293  #### Revoked tokens
   294  
   295  AuthN makes sure that all AIS gateways are timely updated with each revoked token.
   296  When AuthN registers a new cluster, it sends to the cluster the entire list of revoked tokens.
   297  Periodically the list is cleaned up whereby expired and invalid tokens get removed.
   298  
   299  #### Expired tokens
   300  Generating a token for data access requires user name and user password.
   301  By default, token expiration time is set to 24 hours.
   302  Modify `expiration_time` in the configuration file to change default expiration time.
   303  
   304  To issue single token with custom expiration time, pass optional expiration duration in the request.
   305  Example: generate a token that expires in 5 hours. API:
   306  
   307  ```
   308  POST {"password": "password", "expires_in": 18000000000000} /v1/users/usename
   309  ````
   310  
   311  CLI:
   312  
   313  ```console
   314  $ ais auth login -p password usename -e 5h
   315  ```
   316  
   317  Pass a zero value `"expires_in": 0` to generate a never-expired token.
   318  
   319  AuthN return the generated token in as a JSON formatted message. Example: `{"token": "issued_token"}`.
   320  
   321  Call revoke token API to forcefully invalidate a token before it expires.
   322  
   323  | Operation | HTTP Action | Example |
   324  |---|---|---|
   325  | Generate a token for a user (Log in) | POST {"password": "pass"} /v1/users/username | curl -X POST AUTHSRV/v1/users/username -d '{"password":"pass"}' -H 'Content-Type: application/json' |
   326  | Revoke a token | DEL { "token": "issued_token" } /v1/tokens | curl -X DEL AUTHSRV/v1/tokens -d '{"token":"issued_token"}' -H 'Content-Type: application/json' |
   327  
   328  ### Clusters
   329  
   330  When a cluster is registered, an arbitrary alias can be assigned for the cluster.
   331  CLI supports both cluster's ID and cluster's alias in commands.
   332  The alias is used to create default roles for a just registered cluster.
   333  If a cluster does not have an alias, the role names contain cluster ID.
   334  
   335  | Operation | HTTP Action | Example |
   336  |---|---|---|
   337  | Get a list of registered clusters | GET /v1/clusters | curl -X GET AUTHSRV/v1/clusters |
   338  | Get a registered cluster info | GET /v1/clusters/cluster-id | curl -X GET AUTHSRV/v1/clusters/cluster-id |
   339  | Register a cluster | POST /v1/clusters {"id": "cluster-id", "alias": "cluster-alias", "urls": ["http://CLUSTERIP:PORT"]}| curl -X POST AUTHSRV/v1/clusters -d '{"id": "cluster-id", "alias": "cluster-alias", "urls": ["http://CLUSTERIP:PORT"]}' -H 'Content-Type: application/json' |
   340  | Update a registered cluster | PUT /v1/clusters/id {"alias": "cluster-alias", "urls": ["http://CLUSTERIP:PORT"]}| curl -X PUT AUTHSRV/v1/clusters/id -d '{"alias": "cluster-alias", "urls": ["http://CLUSTERIP:PORT"]}' -H 'Content-Type: application/json' |
   341  | Delete a registered cluster | DELETE /v1/clusters/cluster-id | curl -X DELETE AUTHSRV/v1/clusters/cluster-id |
   342  
   343  ### Roles
   344  
   345  | Operation | HTTP Action | Example |
   346  |---|---|---|
   347  | Get a list of roles | GET /v1/roles | curl -X GET AUTHSRV/v1/roles |
   348  | Get a role | GET /v1/roles/ROLE_ID | curl -X GET AUTHSRV/v1/roles/ROLE_ID |
   349  | Create a new role | POST /v1/roles {"name": "rolename", "desc": "description", "clusters": ["clusterid": permissions]} | curl -X AUTHSRV/v1/roles '{"name": "rolename", "desc": "description", "clusters": ["clusterid": permissions]}' |
   350  | Update an existing role | PUT /v1/roles/role-name {"desc": "description", "clusters": ["clusterid": permissions]} | curl -X PUT AUTHSRV/v1/roles '{"desc": "description", "clusters": ["clusterid": permissions]}' |
   351  | Delete a role | DELETE /v1/roles/role-name | curl -X DELETE AUTHSRV/v1/roles/role-name |
   352  
   353  ### Users
   354  
   355  | Operation | HTTP Action | Example |
   356  |---|---|---|
   357  | Get a list of users | GET /v1/users | curl -X GET AUTHSRV/v1/users |
   358  | Get a users | GET /v1/users/USER_ID | curl -X GET AUTHSRV/v1/users/USER_ID |
   359  | Add a user | POST {"id": "username", "password": "pass", "roles": ["CluOne-owner", "CluTwo-readonly"]} /v1/users | curl -X POST AUTHSRV/v1/users -d '{"id": "username", "password":"pass", "roles": ["CluOne-owner", "CluTwo-readonly"]}' -H 'Content-Type: application/json' |
   360  | Update an existing user| PUT {"password": "pass", "roles": ["CluOne-owner", "CluTwo-readonly"]} /v1/users/user-id | curl -X PUT AUTHSRV/v1/users/user-id -d '{"password":"pass", "roles": ["CluOne-owner", "CluTwo-readonly"]}' -H 'Content-Type: application/json' |
   361  | Delete a user | DELETE /v1/users/username | curl -X DELETE AUTHSRV/v1/users/username |
   362  
   363  ### Configuration
   364  
   365  | Operation | HTTP Action | Example |
   366  |---|---|---|
   367  | Get AuthN configuration | GET /v1/daemon | curl -X GET AUTHSRV/v1/daemon |
   368  | Update AuthN configuration | PUT /v1/daemon { "auth": { "secret": "new_secret", "expiration_time": "24h"}}  | curl -X PUT AUTHSRV/v1/daemon -d '{"auth": {"secret": "new_secret"}}' -H 'Content-Type: application/json' |
   369  
   370  ## Typical workflow
   371  
   372  When AuthN is enabled all requests to buckets and objects must contain a valid token (issued by the AuthN).
   373  Requests without a token will be rejected.
   374  
   375  Steps to generate and use a token:
   376  
   377  1. Superuser creates a user account
   378  
   379  ```console
   380  $ curl -X POST http://AUTHSRV/v1/users \
   381    -d '{"name": "username", "password": "pass"}' \
   382    -H 'Content-Type: application/json' -uadmin:admin
   383  ```
   384  
   385  2. The user requests a token
   386  
   387  ```console
   388  $ curl -X POST http://AUTHSRV/v1/users/username \
   389    -d '{"password": "pass"}' -H 'Content-Type: application/json'
   390  
   391  {"token": "eyJhbGciOiJI.eyJjcmVkcyI.T6r6790"}
   392  ```
   393  3. The user adds the token to every AIStore request (list buckets names example)
   394  
   395  ```console
   396  $ curl -L  http://PROXY/v1/buckets/* -X GET \
   397    -H 'Content-Type: application/json' \
   398    -H "Authorization: Bearer eyJhbGciOiJI.eyJjcmVkcyI.T6r6790"
   399  
   400  {
   401    "ais": [ "train-set-001", "train-set-002" ]
   402    "gcp": [ "image-net-set-1" ],
   403  }
   404  ```