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 }