github.com/aergoio/aergo@v1.3.1/rpc/authentication.go (about) 1 /** 2 * @file 3 * @copyright defined in aergo/LICENSE.txt 4 */ 5 package rpc 6 7 import ( 8 "context" 9 "strings" 10 11 "github.com/aergoio/aergo/types" 12 13 "google.golang.org/grpc/codes" 14 "google.golang.org/grpc/credentials" 15 "google.golang.org/grpc/peer" 16 "google.golang.org/grpc/status" 17 ) 18 19 type Authentication = int 20 21 const ( 22 ReadBlockChain Authentication = 1 23 WriteBlockChain Authentication = 2 24 ShowNode Authentication = 4 25 ControlNode Authentication = 8 26 ) 27 28 func (rpc *AergoRPCService) setClientAuth(conf *types.EnterpriseConfig) { 29 rpc.clientAuthLock.Lock() 30 defer rpc.clientAuthLock.Unlock() 31 32 rpc.clientAuth, rpc.clientAuthOn = parseConf(conf) 33 } 34 35 func (rpc *AergoRPCService) setClientAuthOn(v bool) { 36 rpc.clientAuthLock.Lock() 37 defer rpc.clientAuthLock.Unlock() 38 39 logger.Info().Bool("value", v).Msg("rpc permission check") 40 rpc.clientAuthOn = v 41 } 42 43 func (rpc *AergoRPCService) setClientAuthMap(v []string) { 44 rpc.clientAuthLock.Lock() 45 46 for _, perm := range v { 47 key, value := parseValue(perm) 48 rpc.clientAuth[key] = value 49 } 50 rpc.clientAuthLock.Unlock() 51 } 52 53 func (rpc *AergoRPCService) checkAuth(ctx context.Context, auth Authentication) error { 54 rpc.clientAuthLock.RLock() 55 defer rpc.clientAuthLock.RUnlock() 56 57 if !rpc.clientAuthOn || len(rpc.clientAuth) == 0 { 58 return nil 59 } 60 61 p, ok := peer.FromContext(ctx) 62 if !ok { 63 return status.Error(codes.Unauthenticated, "no peer found") 64 } 65 66 tlsAuth, ok := p.AuthInfo.(credentials.TLSInfo) 67 if !ok { 68 return status.Error(codes.Unauthenticated, "unexpected peer transport credentials") 69 } 70 71 if len(tlsAuth.State.VerifiedChains) == 0 || len(tlsAuth.State.VerifiedChains[0]) == 0 { 72 return status.Error(codes.Unauthenticated, "could not verify peer certificate") 73 } 74 75 for _, id := range tlsAuth.State.PeerCertificates { 76 key := types.EncodeB64(id.Raw) 77 if (rpc.clientAuth[key] & auth) != 0 { 78 return nil 79 } 80 } 81 82 return status.Error(codes.Unauthenticated, "permission forbidden") 83 } 84 85 func parseValue(perm string) (string, int) { 86 v := strings.Split(perm, ":") 87 if len(v) != 2 { 88 logger.Warn().Str("value", perm).Msg("invalid rpc client config") 89 return "", 0 90 } 91 92 permission := 0 93 if strings.Contains(v[1], "R") { 94 permission |= ReadBlockChain 95 } 96 if strings.Contains(v[1], "W") { 97 permission |= WriteBlockChain 98 } 99 if strings.Contains(v[1], "C") { 100 permission |= ControlNode 101 } 102 if strings.Contains(v[1], "S") { 103 permission |= ShowNode 104 } 105 return v[0], permission 106 } 107 108 func parseConf(conf *types.EnterpriseConfig) (map[string]Authentication, bool) { 109 ret := map[string]Authentication{} 110 111 for _, perm := range conf.GetValues() { 112 key, value := parseValue(perm) 113 ret[key] = value 114 } 115 116 return ret, conf.GetOn() 117 }