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  }