github.com/NVIDIA/aistore@v1.3.23-0.20240517131212-7df6609be51d/api/authn/authn.go (about) 1 // Package authn provides AuthN API over HTTP(S) 2 /* 3 * Copyright (c) 2018-2023, NVIDIA CORPORATION. All rights reserved. 4 */ 5 package authn 6 7 import ( 8 "errors" 9 "net/http" 10 "sort" 11 "time" 12 13 "github.com/NVIDIA/aistore/api" 14 "github.com/NVIDIA/aistore/api/apc" 15 "github.com/NVIDIA/aistore/cmn/cos" 16 jsoniter "github.com/json-iterator/go" 17 ) 18 19 func AddUser(bp api.BaseParams, newUser *User) error { 20 msg, err := jsoniter.Marshal(newUser) 21 if err != nil { 22 return err 23 } 24 bp.Method = http.MethodPost 25 reqParams := api.AllocRp() 26 defer api.FreeRp(reqParams) 27 { 28 reqParams.BaseParams = bp 29 reqParams.Path = apc.URLPathUsers.S 30 reqParams.Body = msg 31 reqParams.Header = http.Header{cos.HdrContentType: []string{cos.ContentJSON}} 32 } 33 return reqParams.DoRequest() 34 } 35 36 func UpdateUser(bp api.BaseParams, user *User) error { 37 msg := cos.MustMarshal(user) 38 bp.Method = http.MethodPut 39 reqParams := api.AllocRp() 40 defer api.FreeRp(reqParams) 41 { 42 reqParams.BaseParams = bp 43 reqParams.Path = apc.URLPathUsers.Join(user.ID) 44 reqParams.Body = msg 45 reqParams.Header = http.Header{cos.HdrContentType: []string{cos.ContentJSON}} 46 } 47 return reqParams.DoRequest() 48 } 49 50 func DeleteUser(bp api.BaseParams, userID string) error { 51 bp.Method = http.MethodDelete 52 reqParams := api.AllocRp() 53 defer api.FreeRp(reqParams) 54 { 55 reqParams.BaseParams = bp 56 reqParams.Path = apc.URLPathUsers.Join(userID) 57 } 58 return reqParams.DoRequest() 59 } 60 61 // Authorize a user and return a user token in case of success. 62 // The token expires in `expire` time. If `expire` is `nil` the expiration 63 // time is set by AuthN (default AuthN expiration time is 24 hours) 64 func LoginUser(bp api.BaseParams, userID, pass, clusterID string, expire *time.Duration) (token *TokenMsg, err error) { 65 bp.Method = http.MethodPost 66 rec := LoginMsg{Password: pass, ExpiresIn: expire, ClusterID: clusterID} 67 reqParams := api.AllocRp() 68 defer api.FreeRp(reqParams) 69 { 70 reqParams.BaseParams = bp 71 reqParams.Path = apc.URLPathUsers.Join(userID) 72 reqParams.Body = cos.MustMarshal(rec) 73 reqParams.Header = http.Header{cos.HdrContentType: []string{cos.ContentJSON}} 74 } 75 if _, err = reqParams.DoReqAny(&token); err != nil { 76 return nil, err 77 } 78 if token.Token == "" { 79 return nil, errors.New("login failed: empty response from AuthN server") 80 } 81 return token, nil 82 } 83 84 func RegisterCluster(bp api.BaseParams, cluSpec CluACL) error { 85 msg := cos.MustMarshal(cluSpec) 86 bp.Method = http.MethodPost 87 reqParams := api.AllocRp() 88 defer api.FreeRp(reqParams) 89 { 90 reqParams.BaseParams = bp 91 reqParams.Path = apc.URLPathClusters.S 92 reqParams.Body = msg 93 reqParams.Header = http.Header{cos.HdrContentType: []string{cos.ContentJSON}} 94 } 95 return reqParams.DoRequest() 96 } 97 98 func UpdateCluster(bp api.BaseParams, cluSpec CluACL) error { 99 msg := cos.MustMarshal(cluSpec) 100 bp.Method = http.MethodPut 101 reqParams := api.AllocRp() 102 defer api.FreeRp(reqParams) 103 { 104 reqParams.BaseParams = bp 105 reqParams.Path = apc.URLPathClusters.Join(cluSpec.ID) 106 reqParams.Body = msg 107 reqParams.Header = http.Header{cos.HdrContentType: []string{cos.ContentJSON}} 108 } 109 return reqParams.DoRequest() 110 } 111 112 func UnregisterCluster(bp api.BaseParams, spec CluACL) error { 113 bp.Method = http.MethodDelete 114 reqParams := api.AllocRp() 115 defer api.FreeRp(reqParams) 116 { 117 reqParams.BaseParams = bp 118 reqParams.Path = apc.URLPathClusters.Join(spec.ID) 119 } 120 return reqParams.DoRequest() 121 } 122 123 func GetRegisteredClusters(bp api.BaseParams, spec CluACL) ([]*CluACL, error) { 124 bp.Method = http.MethodGet 125 path := apc.URLPathClusters.S 126 if spec.ID != "" { 127 path = cos.JoinWords(path, spec.ID) 128 } 129 reqParams := api.AllocRp() 130 defer api.FreeRp(reqParams) 131 { 132 reqParams.BaseParams = bp 133 reqParams.Path = path 134 } 135 136 clusters := &RegisteredClusters{} 137 _, err := reqParams.DoReqAny(clusters) 138 rec := make([]*CluACL, 0, len(clusters.M)) 139 for _, clu := range clusters.M { 140 rec = append(rec, clu) 141 } 142 less := func(i, j int) bool { return rec[i].ID < rec[j].ID } 143 sort.Slice(rec, less) 144 return rec, err 145 } 146 147 func GetRole(bp api.BaseParams, roleID string) (*Role, error) { 148 if roleID == "" { 149 return nil, errors.New("missing role ID") 150 } 151 bp.Method = http.MethodGet 152 reqParams := api.AllocRp() 153 defer api.FreeRp(reqParams) 154 { 155 reqParams.BaseParams = bp 156 reqParams.Path = cos.JoinWords(apc.URLPathRoles.S, roleID) 157 } 158 159 rInfo := &Role{} 160 _, err := reqParams.DoReqAny(&rInfo) 161 return rInfo, err 162 } 163 164 func GetAllRoles(bp api.BaseParams) ([]*Role, error) { 165 bp.Method = http.MethodGet 166 path := apc.URLPathRoles.S 167 reqParams := api.AllocRp() 168 defer api.FreeRp(reqParams) 169 { 170 reqParams.BaseParams = bp 171 reqParams.Path = path 172 } 173 174 roles := make([]*Role, 0) 175 _, err := reqParams.DoReqAny(&roles) 176 177 less := func(i, j int) bool { return roles[i].ID < roles[j].ID } 178 sort.Slice(roles, less) 179 return roles, err 180 } 181 182 func GetAllUsers(bp api.BaseParams) ([]*User, error) { 183 bp.Method = http.MethodGet 184 reqParams := api.AllocRp() 185 defer api.FreeRp(reqParams) 186 { 187 reqParams.BaseParams = bp 188 reqParams.Path = apc.URLPathUsers.S 189 } 190 191 users := make(map[string]*User, 4) 192 _, err := reqParams.DoReqAny(&users) 193 194 list := make([]*User, 0, len(users)) 195 for _, info := range users { 196 list = append(list, info) 197 } 198 199 less := func(i, j int) bool { return list[i].ID < list[j].ID } 200 sort.Slice(list, less) 201 202 return list, err 203 } 204 205 func GetUser(bp api.BaseParams, userID string) (*User, error) { 206 if userID == "" { 207 return nil, errors.New("missing user ID") 208 } 209 bp.Method = http.MethodGet 210 reqParams := api.AllocRp() 211 defer api.FreeRp(reqParams) 212 { 213 reqParams.BaseParams = bp 214 reqParams.Path = cos.JoinWords(apc.URLPathUsers.S, userID) 215 } 216 217 uInfo := &User{} 218 _, err := reqParams.DoReqAny(&uInfo) 219 return uInfo, err 220 } 221 222 func AddRole(bp api.BaseParams, roleSpec *Role) error { 223 msg := cos.MustMarshal(roleSpec) 224 bp.Method = http.MethodPost 225 reqParams := api.AllocRp() 226 defer api.FreeRp(reqParams) 227 { 228 reqParams.BaseParams = bp 229 reqParams.Path = apc.URLPathRoles.S 230 reqParams.Body = msg 231 reqParams.Header = http.Header{cos.HdrContentType: []string{cos.ContentJSON}} 232 } 233 return reqParams.DoRequest() 234 } 235 236 func UpdateRole(bp api.BaseParams, roleSpec *Role) error { 237 msg := cos.MustMarshal(roleSpec) 238 bp.Method = http.MethodPut 239 reqParams := api.AllocRp() 240 defer api.FreeRp(reqParams) 241 { 242 reqParams.BaseParams = bp 243 reqParams.Path = apc.URLPathRoles.Join(roleSpec.ID) 244 reqParams.Body = msg 245 reqParams.Header = http.Header{cos.HdrContentType: []string{cos.ContentJSON}} 246 } 247 return reqParams.DoRequest() 248 } 249 250 func DeleteRole(bp api.BaseParams, role string) error { 251 bp.Method = http.MethodDelete 252 reqParams := api.AllocRp() 253 defer api.FreeRp(reqParams) 254 { 255 reqParams.BaseParams = bp 256 reqParams.Path = apc.URLPathRoles.Join(role) 257 } 258 return reqParams.DoRequest() 259 } 260 261 func RevokeToken(bp api.BaseParams, token string) error { 262 bp.Method = http.MethodDelete 263 msg := &TokenMsg{Token: token} 264 reqParams := api.AllocRp() 265 defer api.FreeRp(reqParams) 266 { 267 reqParams.Body = cos.MustMarshal(msg) 268 reqParams.BaseParams = bp 269 reqParams.Path = apc.URLPathTokens.S 270 reqParams.Header = http.Header{cos.HdrContentType: []string{cos.ContentJSON}} 271 } 272 return reqParams.DoRequest() 273 } 274 275 func GetConfig(bp api.BaseParams) (*Config, error) { 276 bp.Method = http.MethodGet 277 reqParams := api.AllocRp() 278 defer api.FreeRp(reqParams) 279 { 280 reqParams.BaseParams = bp 281 reqParams.Path = apc.URLPathDae.S 282 } 283 284 conf := &Config{} 285 _, err := reqParams.DoReqAny(&conf) 286 return conf, err 287 } 288 289 func SetConfig(bp api.BaseParams, conf *ConfigToUpdate) error { 290 bp.Method = http.MethodPut 291 reqParams := api.AllocRp() 292 defer api.FreeRp(reqParams) 293 { 294 reqParams.Body = cos.MustMarshal(conf) 295 reqParams.BaseParams = bp 296 reqParams.Path = apc.URLPathDae.S 297 reqParams.Header = http.Header{cos.HdrContentType: []string{cos.ContentJSON}} 298 } 299 return reqParams.DoRequest() 300 }