github.com/cs3org/reva/v2@v2.27.7/pkg/auth/manager/json/json.go (about)

     1  // Copyright 2018-2021 CERN
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  //
    15  // In applying this license, CERN does not waive the privileges and immunities
    16  // granted to it by virtue of its status as an Intergovernmental Organization
    17  // or submit itself to any jurisdiction.
    18  
    19  package json
    20  
    21  import (
    22  	"context"
    23  	"encoding/json"
    24  	"os"
    25  
    26  	authpb "github.com/cs3org/go-cs3apis/cs3/auth/provider/v1beta1"
    27  	user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
    28  	typespb "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
    29  	"github.com/cs3org/reva/v2/pkg/auth"
    30  	"github.com/cs3org/reva/v2/pkg/auth/manager/registry"
    31  	"github.com/cs3org/reva/v2/pkg/auth/scope"
    32  	"github.com/cs3org/reva/v2/pkg/errtypes"
    33  	"github.com/mitchellh/mapstructure"
    34  	"github.com/pkg/errors"
    35  )
    36  
    37  func init() {
    38  	registry.Register("json", New)
    39  }
    40  
    41  // Credentials holds a pair of secret and userid
    42  type Credentials struct {
    43  	ID           *user.UserId    `mapstructure:"id" json:"id"`
    44  	Username     string          `mapstructure:"username" json:"username"`
    45  	Mail         string          `mapstructure:"mail" json:"mail"`
    46  	MailVerified bool            `mapstructure:"mail_verified" json:"mail_verified"`
    47  	DisplayName  string          `mapstructure:"display_name" json:"display_name"`
    48  	Secret       string          `mapstructure:"secret" json:"secret"`
    49  	Groups       []string        `mapstructure:"groups" json:"groups"`
    50  	UIDNumber    int64           `mapstructure:"uid_number" json:"uid_number"`
    51  	GIDNumber    int64           `mapstructure:"gid_number" json:"gid_number"`
    52  	Opaque       *typespb.Opaque `mapstructure:"opaque" json:"opaque"`
    53  }
    54  
    55  type manager struct {
    56  	credentials map[string]*Credentials
    57  }
    58  
    59  type config struct {
    60  	// Users holds a path to a file containing json conforming the Users struct
    61  	Users string `mapstructure:"users"`
    62  }
    63  
    64  func (c *config) init() {
    65  	if c.Users == "" {
    66  		c.Users = "/etc/revad/users.json"
    67  	}
    68  }
    69  
    70  func parseConfig(m map[string]interface{}) (*config, error) {
    71  	c := &config{}
    72  	if err := mapstructure.Decode(m, c); err != nil {
    73  		err = errors.Wrap(err, "error decoding conf")
    74  		return nil, err
    75  	}
    76  	c.init()
    77  	return c, nil
    78  }
    79  
    80  // New returns a new auth Manager.
    81  func New(m map[string]interface{}) (auth.Manager, error) {
    82  	mgr := &manager{}
    83  	err := mgr.Configure(m)
    84  	if err != nil {
    85  		return nil, err
    86  	}
    87  	return mgr, nil
    88  }
    89  
    90  func (m *manager) Configure(ml map[string]interface{}) error {
    91  	c, err := parseConfig(ml)
    92  	if err != nil {
    93  		return err
    94  	}
    95  
    96  	m.credentials = map[string]*Credentials{}
    97  	f, err := os.ReadFile(c.Users)
    98  	if err != nil {
    99  		return err
   100  	}
   101  
   102  	credentials := []*Credentials{}
   103  
   104  	err = json.Unmarshal(f, &credentials)
   105  	if err != nil {
   106  		return err
   107  	}
   108  
   109  	for _, c := range credentials {
   110  		m.credentials[c.Username] = c
   111  	}
   112  	return nil
   113  }
   114  
   115  func (m *manager) Authenticate(ctx context.Context, username string, secret string) (*user.User, map[string]*authpb.Scope, error) {
   116  	if c, ok := m.credentials[username]; ok {
   117  		if c.Secret == secret {
   118  			var scopes map[string]*authpb.Scope
   119  			var err error
   120  			if c.ID != nil && (c.ID.Type == user.UserType_USER_TYPE_LIGHTWEIGHT || c.ID.Type == user.UserType_USER_TYPE_FEDERATED) {
   121  				scopes, err = scope.AddLightweightAccountScope(authpb.Role_ROLE_OWNER, nil)
   122  				if err != nil {
   123  					return nil, nil, err
   124  				}
   125  			} else {
   126  				scopes, err = scope.AddOwnerScope(nil)
   127  				if err != nil {
   128  					return nil, nil, err
   129  				}
   130  			}
   131  			return &user.User{
   132  				Id:           c.ID,
   133  				Username:     c.Username,
   134  				Mail:         c.Mail,
   135  				MailVerified: c.MailVerified,
   136  				DisplayName:  c.DisplayName,
   137  				Groups:       c.Groups,
   138  				UidNumber:    c.UIDNumber,
   139  				GidNumber:    c.GIDNumber,
   140  				Opaque:       c.Opaque,
   141  				// TODO add arbitrary keys as opaque data
   142  			}, scopes, nil
   143  		}
   144  	}
   145  	return nil, nil, errtypes.InvalidCredentials(username)
   146  }