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 ```