github.com/RobustRoundRobin/quorum@v20.10.0+incompatible/rpc/security_test.go (about)

     1  package rpc
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"net/http"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/golang/protobuf/ptypes"
    11  	"github.com/jpmorganchase/quorum-security-plugin-sdk-go/proto"
    12  	testifyassert "github.com/stretchr/testify/assert"
    13  )
    14  
    15  func TestVerifyAccess_whenNotMatch(t *testing.T) {
    16  	assert := testifyassert.New(t)
    17  
    18  	assert.Error(verifyAccess("xyz", "abc", []*proto.GrantedAuthority{
    19  		{
    20  			Service: "bar",
    21  			Method:  "foo",
    22  		},
    23  	}))
    24  }
    25  
    26  func TestVerifyAccess_whenEmpty(t *testing.T) {
    27  	assert := testifyassert.New(t)
    28  
    29  	assert.Error(verifyAccess("xyz", "abc", nil))
    30  }
    31  
    32  func TestVerifyAccess_whenExactMatch(t *testing.T) {
    33  	assert := testifyassert.New(t)
    34  
    35  	assert.NoError(verifyAccess("bar", "foo", []*proto.GrantedAuthority{
    36  		{
    37  			Service: "xyz",
    38  			Method:  "abc",
    39  		},
    40  		{
    41  			Service: "bar",
    42  			Method:  "foo",
    43  		},
    44  	}))
    45  }
    46  
    47  func TestVerifyAccess_whenWildcardServiceMatch(t *testing.T) {
    48  	assert := testifyassert.New(t)
    49  
    50  	assert.NoError(verifyAccess("bar", "foo", []*proto.GrantedAuthority{
    51  		{
    52  			Service: "xyz",
    53  			Method:  "abc",
    54  		},
    55  		{
    56  			Service: "*",
    57  			Method:  "foo",
    58  		},
    59  	}))
    60  }
    61  
    62  func TestVerifyAccess_whenWildcardMethodMatch(t *testing.T) {
    63  	assert := testifyassert.New(t)
    64  
    65  	assert.NoError(verifyAccess("bar", "foo", []*proto.GrantedAuthority{
    66  		{
    67  			Service: "xyz",
    68  			Method:  "abc",
    69  		},
    70  		{
    71  			Service: "bar",
    72  			Method:  "*",
    73  		},
    74  	}))
    75  }
    76  
    77  func TestVerifyAccess_whenWildcardMatch(t *testing.T) {
    78  	assert := testifyassert.New(t)
    79  
    80  	assert.NoError(verifyAccess("bar", "foo", []*proto.GrantedAuthority{
    81  		{
    82  			Service: "*",
    83  			Method:  "*",
    84  		},
    85  	}))
    86  }
    87  
    88  func TestVerifyExpiration_whenTypical(t *testing.T) {
    89  	assert := testifyassert.New(t)
    90  	expiredAt, _ := ptypes.TimestampProto(time.Now().Add(1 * time.Minute))
    91  	assert.NoError(verifyExpiration(&proto.PreAuthenticatedAuthenticationToken{
    92  		ExpiredAt: expiredAt,
    93  	}))
    94  }
    95  
    96  func TestVerifyExpiration_whenExpired(t *testing.T) {
    97  	assert := testifyassert.New(t)
    98  	expiredAt, _ := ptypes.TimestampProto(time.Now().Add(-1 * time.Minute))
    99  	assert.Error(verifyExpiration(&proto.PreAuthenticatedAuthenticationToken{
   100  		ExpiredAt: expiredAt,
   101  	}))
   102  }
   103  
   104  func TestExtractToken_whenTypical(t *testing.T) {
   105  	assert := testifyassert.New(t)
   106  	req, _ := http.NewRequest("POST", "", nil)
   107  	arbitraryValue := "xyz"
   108  	req.Header.Set(HttpAuthorizationHeader, arbitraryValue)
   109  
   110  	token, ok := extractToken(req)
   111  
   112  	assert.True(ok)
   113  	assert.Equal(arbitraryValue, token)
   114  }
   115  
   116  func TestExtractToken_whenEmpty(t *testing.T) {
   117  	assert := testifyassert.New(t)
   118  	req, _ := http.NewRequest("POST", "", nil)
   119  
   120  	_, ok := extractToken(req)
   121  
   122  	assert.False(ok)
   123  }
   124  
   125  func TestSecureCall_whenThereIsAuthenticationError(t *testing.T) {
   126  	assert := testifyassert.New(t)
   127  	arbitraryError := errors.New("arbitrary error")
   128  	stubSecurityContextResolver := newStubSecurityContextResolver([]struct{ k, v interface{} }{
   129  		{ctxAuthenticationError, arbitraryError},
   130  	})
   131  
   132  	err := secureCall(stubSecurityContextResolver, &jsonrpcMessage{})
   133  
   134  	assert.EqualError(err, arbitraryError.Error())
   135  }
   136  
   137  func TestSecureCall_whenTokenExpired(t *testing.T) {
   138  	assert := testifyassert.New(t)
   139  	expiredAt, _ := ptypes.TimestampProto(time.Now().Add(-1 * time.Hour))
   140  	stubSecurityContextResolver := newStubSecurityContextResolver([]struct{ k, v interface{} }{
   141  		{ctxPreauthenticatedToken, &proto.PreAuthenticatedAuthenticationToken{
   142  			ExpiredAt: expiredAt,
   143  		}},
   144  	})
   145  
   146  	err := secureCall(stubSecurityContextResolver, &jsonrpcMessage{})
   147  
   148  	assert.EqualError(err, "token expired")
   149  }
   150  
   151  func TestSecureCall_whenTypical(t *testing.T) {
   152  	assert := testifyassert.New(t)
   153  	expiredAt, _ := ptypes.TimestampProto(time.Now().Add(1 * time.Hour))
   154  	stubSecurityContextResolver := newStubSecurityContextResolver([]struct{ k, v interface{} }{
   155  		{ctxPreauthenticatedToken, &proto.PreAuthenticatedAuthenticationToken{
   156  			ExpiredAt: expiredAt,
   157  			Authorities: []*proto.GrantedAuthority{
   158  				{
   159  					Service: "eth",
   160  					Method:  "blockNumber",
   161  				},
   162  			},
   163  		}},
   164  	})
   165  
   166  	err := secureCall(stubSecurityContextResolver, &jsonrpcMessage{Method: "eth_blockNumber"})
   167  
   168  	assert.NoError(err)
   169  }
   170  
   171  func TestSecureCall_whenAccessDenied(t *testing.T) {
   172  	assert := testifyassert.New(t)
   173  	expiredAt, _ := ptypes.TimestampProto(time.Now().Add(1 * time.Hour))
   174  	stubSecurityContextResolver := newStubSecurityContextResolver([]struct{ k, v interface{} }{
   175  		{ctxPreauthenticatedToken, &proto.PreAuthenticatedAuthenticationToken{
   176  			ExpiredAt: expiredAt,
   177  			Authorities: []*proto.GrantedAuthority{
   178  				{
   179  					Service: "eth",
   180  					Method:  "blockNumber",
   181  				},
   182  			},
   183  		}},
   184  	})
   185  
   186  	err := secureCall(stubSecurityContextResolver, &jsonrpcMessage{Method: "eth_someMethod"})
   187  
   188  	assert.EqualError(err, "eth_someMethod - access denied")
   189  }
   190  
   191  func TestSecureCall_whenMethodInJSONMessageIsNotSupported(t *testing.T) {
   192  	assert := testifyassert.New(t)
   193  	expiredAt, _ := ptypes.TimestampProto(time.Now().Add(1 * time.Hour))
   194  	stubSecurityContextResolver := newStubSecurityContextResolver([]struct{ k, v interface{} }{
   195  		{ctxPreauthenticatedToken, &proto.PreAuthenticatedAuthenticationToken{
   196  			ExpiredAt: expiredAt,
   197  		}},
   198  	})
   199  
   200  	err := secureCall(stubSecurityContextResolver, &jsonrpcMessage{Method: "arbitrary method"})
   201  
   202  	assert.NoError(err)
   203  }
   204  
   205  type stubSecurityContextResolver struct {
   206  	ctx securityContext
   207  }
   208  
   209  func newStubSecurityContextResolver(ctx []struct{ k, v interface{} }) *stubSecurityContextResolver {
   210  	sc := securityContext(context.Background())
   211  	for _, kv := range ctx {
   212  		sc = context.WithValue(sc, kv.k, kv.v)
   213  	}
   214  	return &stubSecurityContextResolver{sc}
   215  }
   216  
   217  func (sr *stubSecurityContextResolver) Resolve() securityContext {
   218  	return sr.ctx
   219  }