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  }