github.com/kisexp/xdchain@v0.0.0-20211206025815-490d6b732aa7/multitenancy/authorization_test.go (about) 1 package multitenancy 2 3 import ( 4 "net/url" 5 "os" 6 "testing" 7 8 "github.com/kisexp/xdchain/common" 9 "github.com/kisexp/xdchain/core/types" 10 "github.com/kisexp/xdchain/log" 11 "github.com/jpmorganchase/quorum-security-plugin-sdk-go/proto" 12 "github.com/stretchr/testify/assert" 13 ) 14 15 func init() { 16 log.Root().SetHandler(log.StreamHandler(os.Stdout, log.TerminalFormat(false))) 17 } 18 19 type testCase struct { 20 msg string 21 granted []string 22 ask *PrivateStateSecurityAttribute 23 isAuthorized bool 24 } 25 26 func TestMatch_whenTypical(t *testing.T) { 27 granted, _ := url.Parse("psi://arbitrary.psi1?node.eoa=0xaaa") 28 ask, _ := url.Parse("psi://arbitrary.psi1?node.eoa=0xaaa") 29 30 assert.True(t, match(ask, granted)) 31 } 32 33 func TestMatch_whenNoEOA(t *testing.T) { 34 granted, _ := url.Parse("psi://arbitrary.psi1") 35 ask, _ := url.Parse("psi://arbitrary.psi1") 36 37 assert.False(t, match(ask, granted)) 38 } 39 40 func TestMatch_whenAskWithNoEOA(t *testing.T) { 41 granted, _ := url.Parse("psi://arbitrary.psi1?node.eoa=0xaaa") 42 ask, _ := url.Parse("psi://arbitrary.psi1") 43 44 assert.False(t, match(ask, granted)) 45 } 46 47 func TestMatch_whenGrantWithNoEOA(t *testing.T) { 48 granted, _ := url.Parse("psi://arbitrary.psi1") 49 ask, _ := url.Parse("psi://arbitrary.psi1?node.eoa=0xaaa") 50 51 assert.False(t, match(ask, granted)) 52 } 53 54 func TestMatch_whenGrantWithDifferentEOA(t *testing.T) { 55 granted, _ := url.Parse("psi://arbitrary.psi1?node.eoa=0xaaa") 56 ask, _ := url.Parse("psi://arbitrary.psi1?self.eoa=0xaaa") 57 58 assert.False(t, match(ask, granted)) 59 } 60 61 func TestMatch_whenAskMultipleEOA(t *testing.T) { 62 granted, _ := url.Parse("psi://arbitrary.psi1?node.eoa=0xaaa") 63 ask, _ := url.Parse("psi://arbitrary.psi1?node.eoa=0xaaa&node.eoa=0xbbb") 64 65 assert.False(t, match(ask, granted)) 66 } 67 68 func TestMatch_whenGrantMultipleEOA(t *testing.T) { 69 granted, _ := url.Parse("psi://arbitrary.psi1?node.eoa=0x111&self.eoa=0xaaa&self.eoa=0xbbb&self.eoa=0xccc") 70 ask, _ := url.Parse("psi://arbitrary.psi1?self.eoa=0xaaa&self.eoa=0xbbb") 71 72 assert.True(t, match(ask, granted)) 73 } 74 75 func TestMatch_whenGrantWithWildCardEOA(t *testing.T) { 76 granted, _ := url.Parse("psi://arbitrary.psi1?node.eoa=0x0") 77 ask, _ := url.Parse("psi://arbitrary.psi1?node.eoa=0xaaa&node.eoa=0xbbb") 78 79 assert.True(t, match(ask, granted)) 80 } 81 82 func TestMatch_whenDiffScheme(t *testing.T) { 83 granted, _ := url.Parse("rpc://eth_sendTransaction") 84 ask, _ := url.Parse("psi://arbitrary.psi1?node.eoa=0xaaa&node.eoa=0xbbb") 85 86 assert.False(t, match(ask, granted)) 87 } 88 89 func TestMatch_whenDiffPSI(t *testing.T) { 90 granted, _ := url.Parse("psi://arbitrary.psi1?node.eoa=0x0") 91 ask, _ := url.Parse("psi://arbitrary.psi2?node.eoa=0xaaa&node.eoa=0xbbb") 92 93 assert.False(t, match(ask, granted)) 94 } 95 96 func TestMatch_whenDiffPSIAndNoEOA(t *testing.T) { 97 granted, _ := url.Parse("psi://arbitrary.psi1") 98 ask, _ := url.Parse("psi://arbitrary.psi2") 99 100 assert.False(t, match(ask, granted)) 101 } 102 103 func TestAuthorizePSI(t *testing.T) { 104 testCases := []struct { 105 msg string 106 granted []string 107 ask types.PrivateStateIdentifier 108 isAuthorized bool 109 }{ 110 { 111 msg: "Granting PSI with no EOA", 112 granted: []string{ 113 "psi://arbitrary.ps1", 114 }, 115 ask: "arbitrary.ps1", 116 isAuthorized: true, 117 }, 118 { 119 msg: "Granting PSI with EOA", 120 granted: []string{ 121 "psi://arbitrary.ps1?node.eoa=0x0", 122 }, 123 ask: "arbitrary.ps1", 124 isAuthorized: true, 125 }, 126 { 127 msg: "Different scheme", 128 granted: []string{ 129 "rpc://arbitrary.ps1", 130 }, 131 ask: "arbitrary.ps1", 132 isAuthorized: false, 133 }, 134 } 135 136 for _, tc := range testCases { 137 log.Debug("Test case :: " + tc.msg) 138 actual, err := IsPSIAuthorized(toToken(tc.granted), tc.ask) 139 assert.NoError(t, err, tc.msg) 140 assert.Equal(t, tc.isAuthorized, actual, tc.msg) 141 } 142 } 143 144 func TestAuthorize(t *testing.T) { 145 testCases := []testCase{ 146 { 147 msg: "Granting PSI with no EOA", 148 granted: []string{ 149 "psi://arbitrary.ps1", 150 }, 151 ask: (&PrivateStateSecurityAttribute{}). 152 WithPSI("arbitrary.ps1"). 153 WithNodeEOA(common.HexToAddress("0x000000000000000000000000000000000000aaaa")), 154 isAuthorized: false, 155 }, 156 { 157 msg: "Granted with default wild card EOA, inadequate ask", 158 granted: []string{ 159 "psi://arbitrary.ps1", 160 }, 161 ask: (&PrivateStateSecurityAttribute{}). 162 WithPSI("arbitrary.ps1"), 163 isAuthorized: false, 164 }, 165 { 166 msg: "Node-managed: Granted with wild card EOA, ask for specific", 167 granted: []string{ 168 "psi://arbitrary.ps1?node.eoa=0x0&self.eoa=0x000000000000000000000000000000000000aaaa", 169 }, 170 ask: (&PrivateStateSecurityAttribute{}). 171 WithPSI("arbitrary.ps1"). 172 WithNodeEOA(common.StringToAddress("0xc")), 173 isAuthorized: true, 174 }, 175 { 176 msg: "Different EOA grant", 177 granted: []string{ 178 "psi://arbitrary.ps1?self.eoa=0x000000000000000000000000000000000000aaaa", 179 }, 180 ask: (&PrivateStateSecurityAttribute{}). 181 WithPSI("arbitrary.ps1"). 182 WithNodeEOA(common.StringToAddress("0xc")), 183 isAuthorized: false, 184 }, 185 { 186 msg: "Self-managed: Granted with wild card EOA, ask for specific", 187 granted: []string{ 188 "psi://arbitrary.ps1?self.eoa=0x0", 189 }, 190 ask: (&PrivateStateSecurityAttribute{}). 191 WithPSI("arbitrary.ps1"). 192 WithSelfEOA(common.StringToAddress("0xc")), 193 isAuthorized: true, 194 }, 195 { 196 msg: "Not granted to a PSI", 197 granted: []string{ 198 "psi://arbitrary.ps2?node.eoa=0x0&self.eoa=0x0", 199 }, 200 ask: (&PrivateStateSecurityAttribute{}). 201 WithPSI("arbitrary.ps1").WithNodeEOA(common.StringToAddress("arbitrary")), 202 isAuthorized: false, 203 }, 204 } 205 206 for _, tc := range testCases { 207 log.Debug("Test case :: " + tc.msg) 208 actual, err := IsAuthorized(toToken(tc.granted), tc.ask) 209 assert.NoError(t, err, tc.msg) 210 assert.Equal(t, tc.isAuthorized, actual, tc.msg) 211 } 212 } 213 214 func toToken(granted []string) *proto.PreAuthenticatedAuthenticationToken { 215 values := make([]*proto.GrantedAuthority, len(granted)) 216 for i, g := range granted { 217 values[i] = &proto.GrantedAuthority{ 218 Raw: g, 219 } 220 } 221 return &proto.PreAuthenticatedAuthenticationToken{ 222 Authorities: values, 223 } 224 } 225 226 func TestExtractPSI_whenTypical(t *testing.T) { 227 psi, err := ExtractPSI(toToken([]string{ 228 "psi://arbitrary.psi1", 229 "psi://arbitrary.psi1?node.eoa=0x0", 230 "rpc://eth_call", 231 })) 232 233 assert.NoError(t, err) 234 assert.Equal(t, types.ToPrivateStateIdentifier("arbitrary.psi1"), psi) 235 } 236 237 func TestExtractPSI_whenNotFound(t *testing.T) { 238 _, err := ExtractPSI(toToken([]string{ 239 "rpc://eth_call", 240 })) 241 242 assert.EqualError(t, err, ErrPSINotFound.Error()) 243 } 244 245 func TestExtractPSI_whenFoundMultiple(t *testing.T) { 246 _, err := ExtractPSI(toToken([]string{ 247 "psi://arbitrary.psi1", 248 "psi://arbitrary.psi2", 249 "psi://arbitrary.psi3", 250 })) 251 252 assert.EqualError(t, err, ErrPSIFoundMultiple.Error()) 253 }