github.com/cs3org/reva/v2@v2.27.7/pkg/auth/manager/machine/machine.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 machine 20 21 import ( 22 "context" 23 "strings" 24 25 authpb "github.com/cs3org/go-cs3apis/cs3/auth/provider/v1beta1" 26 userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" 27 rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" 28 "github.com/cs3org/reva/v2/pkg/auth" 29 "github.com/cs3org/reva/v2/pkg/auth/manager/registry" 30 "github.com/cs3org/reva/v2/pkg/auth/scope" 31 "github.com/cs3org/reva/v2/pkg/errtypes" 32 "github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool" 33 "github.com/mitchellh/mapstructure" 34 "github.com/pkg/errors" 35 ) 36 37 // 'machine' is an authentication method used to impersonate users. 38 // To impersonate the given user it's only needed an api-key, saved 39 // in a config file. 40 41 // supported claims 42 var claims = []string{"mail", "uid", "username", "gid", "userid"} 43 44 type manager struct { 45 APIKey string `mapstructure:"api_key"` 46 GatewayAddr string `mapstructure:"gateway_addr"` 47 } 48 49 func init() { 50 registry.Register("machine", New) 51 } 52 53 // Configure parses the map conf 54 func (m *manager) Configure(conf map[string]interface{}) error { 55 err := mapstructure.Decode(conf, m) 56 if err != nil { 57 return errors.Wrap(err, "error decoding conf") 58 } 59 return nil 60 } 61 62 // New creates a new manager for the 'machine' authentication 63 func New(conf map[string]interface{}) (auth.Manager, error) { 64 m := &manager{} 65 err := m.Configure(conf) 66 if err != nil { 67 return nil, err 68 } 69 return m, nil 70 } 71 72 // Authenticate impersonate an user if the provided secret is equal to the api-key 73 func (m *manager) Authenticate(ctx context.Context, user, secret string) (*userpb.User, map[string]*authpb.Scope, error) { 74 if m.APIKey != secret { 75 return nil, nil, errtypes.InvalidCredentials("") 76 } 77 78 gtw, err := pool.GetGatewayServiceClient(m.GatewayAddr) 79 if err != nil { 80 return nil, nil, err 81 } 82 83 // username could be either a normal username or a string <claim>:<value> 84 // in the first case the claim is "username" 85 claim, value := parseUser(user) 86 87 userResponse, err := gtw.GetUserByClaim(ctx, &userpb.GetUserByClaimRequest{ 88 Claim: claim, 89 Value: value, 90 }) 91 92 switch { 93 case err != nil: 94 return nil, nil, err 95 case userResponse.Status.Code == rpc.Code_CODE_NOT_FOUND: 96 return nil, nil, errtypes.NotFound(userResponse.Status.Message) 97 case userResponse.Status.Code != rpc.Code_CODE_OK: 98 return nil, nil, errtypes.InternalError(userResponse.Status.Message) 99 } 100 101 scope, err := scope.AddOwnerScope(nil) 102 if err != nil { 103 return nil, nil, err 104 } 105 106 return userResponse.GetUser(), scope, nil 107 108 } 109 110 func contains(lst []string, s string) bool { 111 for _, e := range lst { 112 if e == s { 113 return true 114 } 115 } 116 return false 117 } 118 119 func parseUser(user string) (string, string) { 120 s := strings.SplitN(user, ":", 2) 121 if len(s) == 2 && contains(claims, s[0]) { 122 return s[0], s[1] 123 } 124 return "username", user 125 }