Skip to content

Commit ba63f75

Browse files
committed
Refactored membership logic in Fabric Interoperation Chaincode to extract common functions
Signed-off-by: VRamakrishna <[email protected]>
1 parent 7aa7485 commit ba63f75

File tree

1 file changed

+93
-129
lines changed

1 file changed

+93
-129
lines changed

core/network/fabric-interop-cc/contracts/interop/membership.go

Lines changed: 93 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,88 @@ func validateAttestation(attestation *identity.Attestation, messageBytes string)
6161
return nil
6262
}
6363

64+
// Parse 'identity.CounterAttestedMembership' object and extract structures
65+
func parseCounterAttestedMembership(counterAttestedMembershipSerialized string) (*identity.CounterAttestedMembership, *identity.CounterAttestedMembership_AttestedMembershipSet, *common.Membership, error) {
66+
counterAttestedMembership, err := decodeCounterAttestedMembership(counterAttestedMembershipSerialized)
67+
if err != nil {
68+
return nil, nil, nil, fmt.Errorf("Counter Attested Membership Unmarshal error: %s", err)
69+
}
70+
decodedAttestedMembershipSet, err := base64.StdEncoding.DecodeString(counterAttestedMembership.AttestedMembershipSet)
71+
if err != nil {
72+
return nil, nil, nil, fmt.Errorf("Attested membership set could not be decoded from base64: %s", err.Error())
73+
}
74+
var attestedMembershipSet identity.CounterAttestedMembership_AttestedMembershipSet
75+
err = protoV2.Unmarshal(decodedAttestedMembershipSet, &attestedMembershipSet)
76+
if err != nil {
77+
return nil, nil, nil, fmt.Errorf("Unable to unmarshal attested membership set: %s", err.Error())
78+
}
79+
decodedForeignMembership, err := base64.StdEncoding.DecodeString(attestedMembershipSet.Membership)
80+
if err != nil {
81+
return nil, nil, nil, fmt.Errorf("Foreign membership could not be decoded from base64: %s", err.Error())
82+
}
83+
var foreignMembership common.Membership
84+
err = protoV2.Unmarshal(decodedForeignMembership, &foreignMembership)
85+
if err != nil {
86+
return nil, nil, nil, fmt.Errorf("Unable to unmarshal membership: %s", err.Error())
87+
}
88+
return counterAttestedMembership, &attestedMembershipSet, &foreignMembership, nil
89+
}
90+
91+
// Validate 'identity.CounterAttestedMembership' object and its embedded structures
92+
func validateCounterAttestedMembership(s *SmartContract, ctx contractapi.TransactionContextInterface, counterAttestedMembership *identity.CounterAttestedMembership, attestedMembershipSet *identity.CounterAttestedMembership_AttestedMembershipSet, foreignMembership *common.Membership) error {
93+
var err error
94+
95+
// Match nonces across all attestations, local and foreign
96+
matchedNonce := ""
97+
for _, attestation := range append(counterAttestedMembership.Attestations, attestedMembershipSet.Attestations...) {
98+
if matchedNonce == "" {
99+
matchedNonce = attestation.Nonce
100+
} else {
101+
if matchedNonce != attestation.Nonce {
102+
return fmt.Errorf("Mismatched nonces across two attestations: %s, %s", matchedNonce, attestation.Nonce)
103+
}
104+
}
105+
}
106+
107+
// Ensure valid attestations from all local IIN Agents
108+
for _, attestation := range counterAttestedMembership.Attestations {
109+
err = validateAttestation(attestation, counterAttestedMembership.AttestedMembershipSet + attestation.Nonce)
110+
if err != nil {
111+
return err
112+
}
113+
}
114+
115+
// Validate foreign membership cert chains
116+
err = validateMemberCertChains(foreignMembership)
117+
if err != nil {
118+
return err
119+
}
120+
121+
// Ensure authentic and valid attestations from all foreign IIN Agents
122+
for _, attestation := range attestedMembershipSet.Attestations {
123+
if attestation.UnitIdentity.SecurityDomain != foreignMembership.SecurityDomain {
124+
return fmt.Errorf("Foreign agent security domain %s does not match attested membership security domain %s",
125+
attestation.UnitIdentity.SecurityDomain, foreignMembership.SecurityDomain)
126+
}
127+
attesterCert, err := parseCert(attestation.Certificate)
128+
if err != nil {
129+
return fmt.Errorf("Unable to parse attester certificate")
130+
}
131+
err = verifyMemberInSecurityDomain2(s, ctx, "", attesterCert, foreignMembership, attestation.UnitIdentity.MemberId)
132+
if err != nil {
133+
return fmt.Errorf("Attester with certificate %+v is not a designated IIN Agent of org %s in security domain %s: %+v",
134+
attesterCert, attestation.UnitIdentity.MemberId, attestation.UnitIdentity.SecurityDomain, err)
135+
}
136+
// Validate signature
137+
err = validateAttestation(attestation, attestedMembershipSet.Membership + attestation.Nonce)
138+
if err != nil {
139+
return err
140+
}
141+
}
142+
143+
return nil
144+
}
145+
64146
// CreateLocalMembership cc is used to store the local security domain's Membership in the ledger
65147
func (s *SmartContract) CreateLocalMembership(ctx contractapi.TransactionContextInterface, membershipJSON string) error {
66148
// Check if the caller has network admin privileges
@@ -162,27 +244,10 @@ func (s *SmartContract) CreateMembership(ctx contractapi.TransactionContextInter
162244
return fmt.Errorf("Caller with identity %+v is not a designated IIN Agent of org %s: %+v", callerId, callerMemberUnit, err)
163245
}
164246

165-
counterAttestedMembership, err := decodeCounterAttestedMembership(counterAttestedMembershipSerialized)
247+
// Parse the counter attested membership structure and extract the relevant objects
248+
counterAttestedMembership, attestedMembershipSet, foreignMembership, err := parseCounterAttestedMembership(counterAttestedMembershipSerialized)
166249
if err != nil {
167-
return fmt.Errorf("Counter Attested Membership Unmarshal error: %s", err)
168-
}
169-
decodedAttestedMembershipSet, err := base64.StdEncoding.DecodeString(counterAttestedMembership.AttestedMembershipSet)
170-
if err != nil {
171-
return fmt.Errorf("Attested membership set could not be decoded from base64: %s", err.Error())
172-
}
173-
var attestedMembershipSet identity.CounterAttestedMembership_AttestedMembershipSet
174-
err = protoV2.Unmarshal(decodedAttestedMembershipSet, &attestedMembershipSet)
175-
if err != nil {
176-
return fmt.Errorf("Unable to unmarshal attested membership set: %s", err.Error())
177-
}
178-
decodedForeignMembership, err := base64.StdEncoding.DecodeString(attestedMembershipSet.Membership)
179-
if err != nil {
180-
return fmt.Errorf("Foreign membership could not be decoded from base64: %s", err.Error())
181-
}
182-
var foreignMembership common.Membership
183-
err = protoV2.Unmarshal(decodedForeignMembership, &foreignMembership)
184-
if err != nil {
185-
return fmt.Errorf("Unable to unmarshal membership: %s", err.Error())
250+
return err
186251
}
187252

188253
// Check presence of membership on ledger first
@@ -195,54 +260,12 @@ func (s *SmartContract) CreateMembership(ctx contractapi.TransactionContextInter
195260
return fmt.Errorf("Membership already exists for membership id: %s. Use 'UpdateMembership' to update.", foreignMembership.SecurityDomain)
196261
}
197262

198-
// Match nonces across all attestations, local and foreign
199-
matchedNonce := ""
200-
for _, attestation := range append(counterAttestedMembership.Attestations, attestedMembershipSet.Attestations...) {
201-
if matchedNonce == "" {
202-
matchedNonce = attestation.Nonce
203-
} else {
204-
if matchedNonce != attestation.Nonce {
205-
return fmt.Errorf("Mismatched nonces across two attestations: %s, %s", matchedNonce, attestation.Nonce)
206-
}
207-
}
208-
}
209-
210-
// Ensure valid attestations from all local IIN Agents
211-
for _, attestation := range counterAttestedMembership.Attestations {
212-
err = validateAttestation(attestation, counterAttestedMembership.AttestedMembershipSet + attestation.Nonce)
213-
if err != nil {
214-
return err
215-
}
216-
}
217-
218-
// Validate foreign membership cert chains
219-
err = validateMemberCertChains(&foreignMembership)
263+
// Validate the counter attested membership structure and the structures embedded in it
264+
err = validateCounterAttestedMembership(s, ctx, counterAttestedMembership, attestedMembershipSet, foreignMembership)
220265
if err != nil {
221266
return err
222267
}
223268

224-
// Ensure authentic and valid attestations from all foreign IIN Agents
225-
for _, attestation := range attestedMembershipSet.Attestations {
226-
if attestation.UnitIdentity.SecurityDomain != foreignMembership.SecurityDomain {
227-
return fmt.Errorf("Foreign agent security domain %s does not match attested membership security domain %s",
228-
attestation.UnitIdentity.SecurityDomain, foreignMembership.SecurityDomain)
229-
}
230-
attesterCert, err := parseCert(attestation.Certificate)
231-
if err != nil {
232-
return fmt.Errorf("Unable to parse attester certificate")
233-
}
234-
err = verifyMemberInSecurityDomain2(s, ctx, "", attesterCert, &foreignMembership, attestation.UnitIdentity.MemberId)
235-
if err != nil {
236-
return fmt.Errorf("Attester with certificate %+v is not a designated IIN Agent of org %s in security domain %s: %+v",
237-
attesterCert, attestation.UnitIdentity.MemberId, attestation.UnitIdentity.SecurityDomain, err)
238-
}
239-
// Validate signature
240-
err = validateAttestation(attestation, attestedMembershipSet.Membership + attestation.Nonce)
241-
if err != nil {
242-
return err
243-
}
244-
}
245-
246269
membershipBytes, err := json.Marshal(foreignMembership)
247270
if err != nil {
248271
return fmt.Errorf("Marshal error: %s", err)
@@ -310,27 +333,10 @@ func (s *SmartContract) UpdateMembership(ctx contractapi.TransactionContextInter
310333
return fmt.Errorf("Caller with identity %+v is not a designated IIN Agent: %+v", callerId, err)
311334
}
312335

313-
counterAttestedMembership, err := decodeCounterAttestedMembership(counterAttestedMembershipSerialized)
314-
if err != nil {
315-
return fmt.Errorf("Counter Attested Membership Unmarshal error: %s", err)
316-
}
317-
decodedAttestedMembershipSet, err := base64.StdEncoding.DecodeString(counterAttestedMembership.AttestedMembershipSet)
318-
if err != nil {
319-
return fmt.Errorf("Attested membership set could not be decoded from base64: %s", err.Error())
320-
}
321-
var attestedMembershipSet identity.CounterAttestedMembership_AttestedMembershipSet
322-
err = protoV2.Unmarshal(decodedAttestedMembershipSet, &attestedMembershipSet)
323-
if err != nil {
324-
return fmt.Errorf("Unable to unmarshal attested membership set: %s", err.Error())
325-
}
326-
decodedForeignMembership, err := base64.StdEncoding.DecodeString(attestedMembershipSet.Membership)
327-
if err != nil {
328-
return fmt.Errorf("Foreign membership could not be decoded from base64: %s", err.Error())
329-
}
330-
var foreignMembership common.Membership
331-
err = protoV2.Unmarshal(decodedForeignMembership, &foreignMembership)
336+
// Parse the counter attested membership structure and extract the relevant objects
337+
counterAttestedMembership, attestedMembershipSet, foreignMembership, err := parseCounterAttestedMembership(counterAttestedMembershipSerialized)
332338
if err != nil {
333-
return fmt.Errorf("Unable to unmarshal membership: %s", err.Error())
339+
return err
334340
}
335341

336342
// Check presence of membership on ledger first
@@ -340,54 +346,12 @@ func (s *SmartContract) UpdateMembership(ctx contractapi.TransactionContextInter
340346
return getErr
341347
}
342348

343-
// Match nonces across all attestations, local and foreign
344-
matchedNonce := ""
345-
for _, attestation := range append(counterAttestedMembership.Attestations, attestedMembershipSet.Attestations...) {
346-
if matchedNonce == "" {
347-
matchedNonce = attestation.Nonce
348-
} else {
349-
if matchedNonce != attestation.Nonce {
350-
return fmt.Errorf("Mismatched nonces across two attestations: %s, %s", matchedNonce, attestation.Nonce)
351-
}
352-
}
353-
}
354-
355-
// Ensure valid attestations from all local IIN Agents
356-
for _, attestation := range counterAttestedMembership.Attestations {
357-
err = validateAttestation(attestation, counterAttestedMembership.AttestedMembershipSet + attestation.Nonce)
358-
if err != nil {
359-
return err
360-
}
361-
}
362-
363-
// Validate foreign membership cert chains
364-
err = validateMemberCertChains(&foreignMembership)
349+
// Validate the counter attested membership structure and the structures embedded in it
350+
err = validateCounterAttestedMembership(s, ctx, counterAttestedMembership, attestedMembershipSet, foreignMembership)
365351
if err != nil {
366352
return err
367353
}
368354

369-
// Ensure authentic and valid attestations from all foreign IIN Agents
370-
for _, attestation := range attestedMembershipSet.Attestations {
371-
if attestation.UnitIdentity.SecurityDomain != foreignMembership.SecurityDomain {
372-
return fmt.Errorf("Foreign agent security domain %s does not match attested membership security domain %s",
373-
attestation.UnitIdentity.SecurityDomain, foreignMembership.SecurityDomain)
374-
}
375-
attesterCert, err := parseCert(attestation.Certificate)
376-
if err != nil {
377-
return fmt.Errorf("Unable to parse attester certificate")
378-
}
379-
err = verifyMemberInSecurityDomain2(s, ctx, "", attesterCert, &foreignMembership, attestation.UnitIdentity.MemberId)
380-
if err != nil {
381-
return fmt.Errorf("Attester with certificate %+v is not a designated IIN Agent of org %s in security domain %s: %+v",
382-
attesterCert, attestation.UnitIdentity.MemberId, attestation.UnitIdentity.SecurityDomain, err)
383-
}
384-
// Validate signature
385-
err = validateAttestation(attestation, attestedMembershipSet.Membership + attestation.Nonce)
386-
if err != nil {
387-
return err
388-
}
389-
}
390-
391355
membershipBytes, err := json.Marshal(foreignMembership)
392356
if err != nil {
393357
return fmt.Errorf("Marshal error: %s", err)
@@ -521,7 +485,7 @@ func verifyMemberInSecurityDomain1(s *SmartContract, ctx contractapi.Transaction
521485
// This takes a decoded X.509 certificate as argument (and optionally the certificate in PEM format too).
522486
// It takes a membership structure as argument.
523487
func verifyMemberInSecurityDomain2(s *SmartContract, ctx contractapi.TransactionContextInterface, certPEM string, cert *x509.Certificate, membership *common.Membership, requestingOrg string) error {
524-
err := isCertificateWithinExpiry(cert)
488+
err := isCertificateWithinExpiry(cert)
525489
if err != nil {
526490
return err
527491
}

0 commit comments

Comments
 (0)