github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/hyperledger/fabric-config/configtx/internal/policydsl/policyparser_test.go (about) 1 /* 2 Copyright IBM Corp. 2017 All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package policydsl_test 8 9 import ( 10 "github.com/hellobchain/third_party/hyperledger/fabric-config/configtx/internal/policydsl" 11 "testing" 12 13 "github.com/golang/protobuf/proto" 14 cb "github.com/hyperledger/fabric-protos-go/common" 15 mb "github.com/hyperledger/fabric-protos-go/msp" 16 17 . "github.com/onsi/gomega" 18 ) 19 20 func TestOutOf1(t *testing.T) { 21 gt := NewGomegaWithT(t) 22 23 p1, err := policydsl.FromString("OutOf(1, 'A.member', 'B.member')") 24 gt.Expect(err).NotTo(HaveOccurred()) 25 26 principals := make([]*mb.MSPPrincipal, 0) 27 28 principals = append(principals, &mb.MSPPrincipal{ 29 PrincipalClassification: mb.MSPPrincipal_ROLE, 30 Principal: protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_MEMBER, MspIdentifier: "A"}), 31 }) 32 33 principals = append(principals, &mb.MSPPrincipal{ 34 PrincipalClassification: mb.MSPPrincipal_ROLE, 35 Principal: protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_MEMBER, MspIdentifier: "B"}), 36 }) 37 38 p2 := &cb.SignaturePolicyEnvelope{ 39 Version: 0, 40 Rule: policydsl.NOutOf(1, []*cb.SignaturePolicy{policydsl.SignedBy(0), policydsl.SignedBy(1)}), 41 Identities: principals, 42 } 43 44 gt.Expect(p1).To(Equal(p2)) 45 } 46 47 func TestOutOf2(t *testing.T) { 48 gt := NewGomegaWithT(t) 49 50 p1, err := policydsl.FromString("OutOf(2, 'A.member', 'B.member')") 51 gt.Expect(err).NotTo(HaveOccurred()) 52 53 principals := make([]*mb.MSPPrincipal, 0) 54 55 principals = append(principals, &mb.MSPPrincipal{ 56 PrincipalClassification: mb.MSPPrincipal_ROLE, 57 Principal: protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_MEMBER, MspIdentifier: "A"}), 58 }) 59 60 principals = append(principals, &mb.MSPPrincipal{ 61 PrincipalClassification: mb.MSPPrincipal_ROLE, 62 Principal: protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_MEMBER, MspIdentifier: "B"}), 63 }) 64 65 p2 := &cb.SignaturePolicyEnvelope{ 66 Version: 0, 67 Rule: policydsl.NOutOf(2, []*cb.SignaturePolicy{policydsl.SignedBy(0), policydsl.SignedBy(1)}), 68 Identities: principals, 69 } 70 71 gt.Expect(p1).To(Equal(p2)) 72 } 73 74 func TestAnd(t *testing.T) { 75 gt := NewGomegaWithT(t) 76 77 p1, err := policydsl.FromString("AND('A.member', 'B.member')") 78 gt.Expect(err).NotTo(HaveOccurred()) 79 80 principals := make([]*mb.MSPPrincipal, 0) 81 82 principals = append(principals, &mb.MSPPrincipal{ 83 PrincipalClassification: mb.MSPPrincipal_ROLE, 84 Principal: protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_MEMBER, MspIdentifier: "A"}), 85 }) 86 87 principals = append(principals, &mb.MSPPrincipal{ 88 PrincipalClassification: mb.MSPPrincipal_ROLE, 89 Principal: protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_MEMBER, MspIdentifier: "B"}), 90 }) 91 92 p2 := &cb.SignaturePolicyEnvelope{ 93 Version: 0, 94 Rule: policydsl.And(policydsl.SignedBy(0), policydsl.SignedBy(1)), 95 Identities: principals, 96 } 97 98 gt.Expect(p1).To(Equal(p2)) 99 } 100 101 func TestAndClientPeerOrderer(t *testing.T) { 102 gt := NewGomegaWithT(t) 103 104 p1, err := policydsl.FromString("AND('A.client', 'B.peer')") 105 gt.Expect(err).NotTo(HaveOccurred()) 106 107 principals := make([]*mb.MSPPrincipal, 0) 108 109 principals = append(principals, &mb.MSPPrincipal{ 110 PrincipalClassification: mb.MSPPrincipal_ROLE, 111 Principal: protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_CLIENT, MspIdentifier: "A"}), 112 }) 113 114 principals = append(principals, &mb.MSPPrincipal{ 115 PrincipalClassification: mb.MSPPrincipal_ROLE, 116 Principal: protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_PEER, MspIdentifier: "B"}), 117 }) 118 119 p2 := &cb.SignaturePolicyEnvelope{ 120 Version: 0, 121 Rule: policydsl.And(policydsl.SignedBy(0), policydsl.SignedBy(1)), 122 Identities: principals, 123 } 124 125 gt.Expect(p1).To(Equal(p2)) 126 } 127 128 func TestOr(t *testing.T) { 129 gt := NewGomegaWithT(t) 130 131 p1, err := policydsl.FromString("OR('A.member', 'B.member')") 132 gt.Expect(err).NotTo(HaveOccurred()) 133 134 principals := make([]*mb.MSPPrincipal, 0) 135 136 principals = append(principals, &mb.MSPPrincipal{ 137 PrincipalClassification: mb.MSPPrincipal_ROLE, 138 Principal: protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_MEMBER, MspIdentifier: "A"}), 139 }) 140 141 principals = append(principals, &mb.MSPPrincipal{ 142 PrincipalClassification: mb.MSPPrincipal_ROLE, 143 Principal: protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_MEMBER, MspIdentifier: "B"}), 144 }) 145 146 p2 := &cb.SignaturePolicyEnvelope{ 147 Version: 0, 148 Rule: policydsl.Or(policydsl.SignedBy(0), policydsl.SignedBy(1)), 149 Identities: principals, 150 } 151 152 gt.Expect(p1).To(Equal(p2)) 153 } 154 155 func TestComplex1(t *testing.T) { 156 gt := NewGomegaWithT(t) 157 158 p1, err := policydsl.FromString("OR('A.member', AND('B.member', 'C.member'))") 159 gt.Expect(err).NotTo(HaveOccurred()) 160 161 principals := make([]*mb.MSPPrincipal, 0) 162 163 principals = append(principals, &mb.MSPPrincipal{ 164 PrincipalClassification: mb.MSPPrincipal_ROLE, 165 Principal: protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_MEMBER, MspIdentifier: "B"}), 166 }) 167 168 principals = append(principals, &mb.MSPPrincipal{ 169 PrincipalClassification: mb.MSPPrincipal_ROLE, 170 Principal: protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_MEMBER, MspIdentifier: "C"}), 171 }) 172 173 principals = append(principals, &mb.MSPPrincipal{ 174 PrincipalClassification: mb.MSPPrincipal_ROLE, 175 Principal: protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_MEMBER, MspIdentifier: "A"}), 176 }) 177 178 p2 := &cb.SignaturePolicyEnvelope{ 179 Version: 0, 180 Rule: policydsl.Or(policydsl.SignedBy(2), policydsl.And(policydsl.SignedBy(0), policydsl.SignedBy(1))), 181 Identities: principals, 182 } 183 184 gt.Expect(p1).To(Equal(p2)) 185 } 186 187 func TestComplex2(t *testing.T) { 188 gt := NewGomegaWithT(t) 189 190 p1, err := policydsl.FromString("OR(AND('A.member', 'B.member'), OR('C.admin', 'D.member'))") 191 gt.Expect(err).NotTo(HaveOccurred()) 192 193 principals := make([]*mb.MSPPrincipal, 0) 194 195 principals = append(principals, &mb.MSPPrincipal{ 196 PrincipalClassification: mb.MSPPrincipal_ROLE, 197 Principal: protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_MEMBER, MspIdentifier: "A"}), 198 }) 199 200 principals = append(principals, &mb.MSPPrincipal{ 201 PrincipalClassification: mb.MSPPrincipal_ROLE, 202 Principal: protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_MEMBER, MspIdentifier: "B"}), 203 }) 204 205 principals = append(principals, &mb.MSPPrincipal{ 206 PrincipalClassification: mb.MSPPrincipal_ROLE, 207 Principal: protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_ADMIN, MspIdentifier: "C"}), 208 }) 209 210 principals = append(principals, &mb.MSPPrincipal{ 211 PrincipalClassification: mb.MSPPrincipal_ROLE, 212 Principal: protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_MEMBER, MspIdentifier: "D"}), 213 }) 214 215 p2 := &cb.SignaturePolicyEnvelope{ 216 Version: 0, 217 Rule: policydsl.Or(policydsl.And(policydsl.SignedBy(0), policydsl.SignedBy(1)), policydsl.Or(policydsl.SignedBy(2), policydsl.SignedBy(3))), 218 Identities: principals, 219 } 220 221 gt.Expect(p1).To(Equal(p2)) 222 } 223 224 func TestMSPIDWIthSpecialChars(t *testing.T) { 225 gt := NewGomegaWithT(t) 226 227 p1, err := policydsl.FromString("OR('MSP.member', 'MSP.WITH.DOTS.member', 'MSP-WITH-DASHES.member')") 228 gt.Expect(err).NotTo(HaveOccurred()) 229 230 principals := make([]*mb.MSPPrincipal, 0) 231 232 principals = append(principals, &mb.MSPPrincipal{ 233 PrincipalClassification: mb.MSPPrincipal_ROLE, 234 Principal: protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_MEMBER, MspIdentifier: "MSP"}), 235 }) 236 237 principals = append(principals, &mb.MSPPrincipal{ 238 PrincipalClassification: mb.MSPPrincipal_ROLE, 239 Principal: protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_MEMBER, MspIdentifier: "MSP.WITH.DOTS"}), 240 }) 241 242 principals = append(principals, &mb.MSPPrincipal{ 243 PrincipalClassification: mb.MSPPrincipal_ROLE, 244 Principal: protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_MEMBER, MspIdentifier: "MSP-WITH-DASHES"}), 245 }) 246 247 p2 := &cb.SignaturePolicyEnvelope{ 248 Version: 0, 249 Rule: policydsl.NOutOf(1, []*cb.SignaturePolicy{policydsl.SignedBy(0), policydsl.SignedBy(1), policydsl.SignedBy(2)}), 250 Identities: principals, 251 } 252 253 gt.Expect(p1).To(Equal(p2)) 254 } 255 256 func TestBadStringsNoPanic(t *testing.T) { 257 gt := NewGomegaWithT(t) 258 259 _, err := policydsl.FromString("OR('A.member', Bmember)") // error after 1st Evaluate() 260 gt.Expect(err).To(MatchError("unrecognized token 'Bmember' in policy string")) 261 262 _, err = policydsl.FromString("OR('A.member', 'Bmember')") // error after 2nd Evalute() 263 gt.Expect(err).To(MatchError("unrecognized token 'Bmember' in policy string")) 264 265 _, err = policydsl.FromString(`OR('A.member', '\'Bmember\'')`) // error after 3rd Evalute() 266 gt.Expect(err).To(MatchError("unrecognized token 'Bmember' in policy string")) 267 } 268 269 func TestNodeOUs(t *testing.T) { 270 gt := NewGomegaWithT(t) 271 272 p1, err := policydsl.FromString("OR('A.peer', 'B.admin', 'C.orderer', 'D.client')") 273 gt.Expect(err).NotTo(HaveOccurred()) 274 275 principals := make([]*mb.MSPPrincipal, 0) 276 277 principals = append(principals, &mb.MSPPrincipal{ 278 PrincipalClassification: mb.MSPPrincipal_ROLE, 279 Principal: protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_PEER, MspIdentifier: "A"}), 280 }) 281 282 principals = append(principals, &mb.MSPPrincipal{ 283 PrincipalClassification: mb.MSPPrincipal_ROLE, 284 Principal: protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_ADMIN, MspIdentifier: "B"}), 285 }) 286 287 principals = append(principals, &mb.MSPPrincipal{ 288 PrincipalClassification: mb.MSPPrincipal_ROLE, 289 Principal: protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_ORDERER, MspIdentifier: "C"}), 290 }) 291 292 principals = append(principals, &mb.MSPPrincipal{ 293 PrincipalClassification: mb.MSPPrincipal_ROLE, 294 Principal: protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_CLIENT, MspIdentifier: "D"}), 295 }) 296 297 p2 := &cb.SignaturePolicyEnvelope{ 298 Version: 0, 299 Rule: policydsl.NOutOf(1, []*cb.SignaturePolicy{policydsl.SignedBy(0), policydsl.SignedBy(1), policydsl.SignedBy(2), policydsl.SignedBy(3)}), 300 Identities: principals, 301 } 302 303 gt.Expect(p1).To(Equal(p2)) 304 } 305 306 func TestOutOfNumIsString(t *testing.T) { 307 gt := NewGomegaWithT(t) 308 309 p1, err := policydsl.FromString("OutOf('1', 'A.member', 'B.member')") 310 gt.Expect(err).NotTo(HaveOccurred()) 311 312 principals := make([]*mb.MSPPrincipal, 0) 313 314 principals = append(principals, &mb.MSPPrincipal{ 315 PrincipalClassification: mb.MSPPrincipal_ROLE, 316 Principal: protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_MEMBER, MspIdentifier: "A"}), 317 }) 318 319 principals = append(principals, &mb.MSPPrincipal{ 320 PrincipalClassification: mb.MSPPrincipal_ROLE, 321 Principal: protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_MEMBER, MspIdentifier: "B"}), 322 }) 323 324 p2 := &cb.SignaturePolicyEnvelope{ 325 Version: 0, 326 Rule: policydsl.NOutOf(1, []*cb.SignaturePolicy{policydsl.SignedBy(0), policydsl.SignedBy(1)}), 327 Identities: principals, 328 } 329 330 gt.Expect(p1).To(Equal(p2)) 331 } 332 333 func TestOutOfErrorCase(t *testing.T) { 334 tests := []struct { 335 testName string 336 policyString string 337 expectedErr string 338 }{ 339 { 340 testName: "1st NewEvaluableExpressionWithFunctions() returns an error", 341 policyString: "", 342 expectedErr: "Unexpected end of expression", 343 }, 344 { 345 testName: "outof() if len(args)<2", 346 policyString: "OutOf(1)", 347 expectedErr: "expected at least two arguments to NOutOf. Given 1", 348 }, 349 { 350 testName: "outof() }else{. 1st arg is non of float, int, string", 351 policyString: "OutOf(true, 'A.member')", 352 expectedErr: "unexpected type bool", 353 }, 354 { 355 testName: "oufof() switch default. 2nd arg is not string.", 356 policyString: "OutOf(1, 2)", 357 expectedErr: "unexpected type float64", 358 }, 359 { 360 testName: "firstPass() switch default", 361 policyString: "OutOf(1, 'true')", 362 expectedErr: "unexpected type bool", 363 }, 364 { 365 testName: "secondPass() switch args[1].(type) default", 366 policyString: `OutOf('\'\\\'A\\\'\'', 'B.member')`, 367 expectedErr: "unrecognized type, expected a number, got string", 368 }, 369 { 370 testName: "secondPass() switch args[1].(type) default", 371 policyString: `OutOf(1, '\'1\'')`, 372 expectedErr: "unrecognized type, expected a principal or a policy, got float64", 373 }, 374 { 375 testName: "2nd NewEvaluateExpressionWithFunction() returns an error", 376 policyString: `''`, 377 expectedErr: "Unexpected end of expression", 378 }, 379 { 380 testName: "3rd NewEvaluateExpressionWithFunction() returns an error", 381 policyString: `'\'\''`, 382 expectedErr: "Unexpected end of expression", 383 }, 384 } 385 386 for _, tt := range tests { 387 t.Run(tt.testName, func(t *testing.T) { 388 gt := NewGomegaWithT(t) 389 390 p, err := policydsl.FromString(tt.policyString) 391 gt.Expect(p).To(BeNil()) 392 gt.Expect(err).To(MatchError(tt.expectedErr)) 393 }) 394 } 395 } 396 397 func TestBadStringBeforeFAB11404_ThisCanDeleteAfterFAB11404HasMerged(t *testing.T) { 398 tests := []struct { 399 testName string 400 policyString string 401 expectedErr string 402 }{ 403 { 404 testName: "integer in string", 405 policyString: "1", 406 expectedErr: `invalid policy string '1'`, 407 }, 408 { 409 testName: "quoted integer in string", 410 policyString: "'1'", 411 expectedErr: `invalid policy string ''1''`, 412 }, 413 { 414 testName: "nested quoted integer in string", 415 policyString: `'\'1\''`, 416 expectedErr: `invalid policy string ''\'1\'''`, 417 }, 418 } 419 420 for _, tt := range tests { 421 t.Run(tt.testName, func(t *testing.T) { 422 gt := NewGomegaWithT(t) 423 424 p, err := policydsl.FromString(tt.policyString) 425 gt.Expect(p).To(BeNil()) 426 gt.Expect(err).To(MatchError(tt.expectedErr)) 427 }) 428 } 429 } 430 431 func TestSecondPassBoundaryCheck(t *testing.T) { 432 gt := NewGomegaWithT(t) 433 434 // Check lower boundary 435 // Prohibit t<0 436 p0, err0 := policydsl.FromString("OutOf(-1, 'A.member', 'B.member')") 437 gt.Expect(p0).To(BeNil()) 438 gt.Expect(err0).To(MatchError("invalid t-out-of-n predicate, t -1, n 2")) 439 440 // Permit t==0 : always satisfied policy 441 // There is no clear usecase of t=0, but somebody may already use it, so we don't treat as an error. 442 p1, err1 := policydsl.FromString("OutOf(0, 'A.member', 'B.member')") 443 gt.Expect(err1).NotTo(HaveOccurred()) 444 principals := make([]*mb.MSPPrincipal, 0) 445 principals = append(principals, &mb.MSPPrincipal{ 446 PrincipalClassification: mb.MSPPrincipal_ROLE, 447 Principal: protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_MEMBER, MspIdentifier: "A"}), 448 }) 449 principals = append(principals, &mb.MSPPrincipal{ 450 PrincipalClassification: mb.MSPPrincipal_ROLE, 451 Principal: protoMarshalOrPanic(&mb.MSPRole{Role: mb.MSPRole_MEMBER, MspIdentifier: "B"}), 452 }) 453 expected1 := &cb.SignaturePolicyEnvelope{ 454 Version: 0, 455 Rule: policydsl.NOutOf(0, []*cb.SignaturePolicy{policydsl.SignedBy(0), policydsl.SignedBy(1)}), 456 Identities: principals, 457 } 458 gt.Expect(p1).To(Equal(expected1)) 459 460 // Check upper boundary 461 // Permit t==n+1 : never satisfied policy 462 // Usecase: To create immutable ledger key 463 p2, err2 := policydsl.FromString("OutOf(3, 'A.member', 'B.member')") 464 gt.Expect(err2).NotTo(HaveOccurred()) 465 expected2 := &cb.SignaturePolicyEnvelope{ 466 Version: 0, 467 Rule: policydsl.NOutOf(3, []*cb.SignaturePolicy{policydsl.SignedBy(0), policydsl.SignedBy(1)}), 468 Identities: principals, 469 } 470 gt.Expect(p2).To(Equal(expected2)) 471 472 // Prohibit t>n + 1 473 p3, err3 := policydsl.FromString("OutOf(4, 'A.member', 'B.member')") 474 gt.Expect(p3).To(BeNil()) 475 gt.Expect(err3).To(MatchError("invalid t-out-of-n predicate, t 4, n 2")) 476 } 477 478 // protoMarshalOrPanic serializes a protobuf message and panics if this 479 // operation fails 480 func protoMarshalOrPanic(pb proto.Message) []byte { 481 data, err := proto.Marshal(pb) 482 if err != nil { 483 panic(err) 484 } 485 486 return data 487 }