Skip to content

Commit 218a9bd

Browse files
Anil AmbatiKeith Smith
authored andcommitted
[FAB-6089] ABAC chaincode library
Added library API for Attribute-Based Access Control. See the README.md for an overall description. Change-Id: I487afc57c597a17c6baacf3987527eee8a0978c9 Signed-off-by: Anil Ambati <aambati@us.ibm.com> Signed-off-by: Keith Smith <bksmith@us.ibm.com>
1 parent 3a7f893 commit 218a9bd

File tree

5 files changed

+665
-1
lines changed

5 files changed

+665
-1
lines changed

core/chaincode/lib/cid/README.md

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
# Client Identity Chaincode Library
2+
3+
The client identity chaincode library enables you to write chaincode which
4+
makes access control decisions based on the identity of the client
5+
(i.e. the invoker of the chaincode). In particular, you may make access
6+
control decisions based on either or both of the following associated with
7+
the client:
8+
9+
* the client identity's MSP (Membership Service Provider) ID
10+
* an attribute associated with the client identity
11+
12+
Attributes are simply name and value pairs associated with an identity.
13+
For example, `email=me@gmail.com` indicates an identity has the `email`
14+
attribute with a value of `me@gmail.com`.
15+
16+
17+
## Using the client identity chaincode library
18+
19+
This section describes how to use the client identity chaincode library.
20+
21+
All code samples below assume two things:
22+
1. The type of the `stub` variable is `ChaincodeStubInterface` as passed
23+
to your chaincode.
24+
2. You have added the following import statement to your chaincode.
25+
```
26+
import "github.com/hyperledger/fabric/core/chaincode/lib/cid"
27+
```
28+
#### Getting the client's ID
29+
30+
The following demonstrates how to get an ID for the client which is guaranteed
31+
to be unique within the MSP:
32+
33+
```
34+
id, err := cid.GetID(stub)
35+
```
36+
37+
#### Getting the MSP ID
38+
39+
The following demonstrates how to get the MSP ID of the client's identity:
40+
41+
```
42+
mspid, err := cid.GetMSPID(stub)
43+
```
44+
45+
#### Getting an attribute value
46+
47+
The following demonstrates how to get the value of the *attr1* attribute:
48+
49+
```
50+
val, ok, err := cid.GetAttributeValue(stub, "attr1")
51+
if err != nil {
52+
// There was an error trying to retrieve the attribute
53+
}
54+
if !ok {
55+
// The client identity does not possess the attribute
56+
}
57+
// Do something with the value of 'val'
58+
```
59+
60+
#### Asserting an attribute value
61+
62+
Often all you want to do is to make an access control decision based on the value
63+
of an attribute, i.e. to assert the value of an attribute. For example, the following
64+
will return an error if the client does not have the `myapp.admin` attribute
65+
with a value of `true`:
66+
67+
```
68+
err := cid.AssertAttributeValue(stub, "myapp.admin", "true")
69+
if err != nil {
70+
// Return an error
71+
}
72+
```
73+
74+
This is effectively using attributes to implement role-based access control,
75+
or RBAC for short.
76+
77+
#### Getting the client's X509 certificate
78+
79+
The following demonstrates how to get the X509 certificate of the client, or
80+
nil if the client's identity was not based on an X509 certificate:
81+
82+
```
83+
cert, err := cid.GetX509Certificate(stub)
84+
```
85+
86+
Note that both `cert` and `err` may be nil as will be the case if the identity
87+
is not using an X509 certificate.
88+
89+
#### Performing multiple operations more efficiently
90+
91+
Sometimes you may need to perform multiple operations in order to make an access
92+
decision. For example, the following demonstrates how to grant access to
93+
identities with MSP *org1MSP* and *attr1* OR with MSP *org1MSP* and *attr2*.
94+
95+
```
96+
// Get the client ID object
97+
id, err := cid.New(stub)
98+
if err != nil {
99+
// Handle error
100+
}
101+
mspid, err := id.GetMSPID()
102+
if err != nil {
103+
// Handle error
104+
}
105+
switch mspid {
106+
case "org1MSP":
107+
err = id.AssertAttributeValue("attr1", "true")
108+
case "org2MSP":
109+
err = id.AssertAttributeValue("attr2", "true")
110+
default:
111+
err = errors.New("Wrong MSP")
112+
}
113+
```
114+
Although it is not required, it is more efficient to make the `cid.New` call
115+
to get the ClientIdentity object if you need to perform multiple operations,
116+
as demonstrated above.
117+
118+
## Adding Attributes to Identities
119+
120+
This section describes how to add custom attributes to certificates when
121+
using Hyperledger Fabric CA as well as when using an external CA.
122+
123+
#### Managing attributes with Fabric CA
124+
125+
There are two methods of adding attributes to an enrollment certificate
126+
with fabric-ca:
127+
128+
1. When you register an identity, you can specify that an enrollment certificate
129+
issued for the identity should by default contain an attribute. This behavior
130+
can be overridden at enrollment time, but this is useful for establishing
131+
default behavior and, assuming registration occurs outside of your application,
132+
does not require any application change.
133+
134+
The following shows how to register *user1* with two attributes:
135+
*app1Admin* and *email*.
136+
The ":ecert" suffix causes the *appAdmin* attribute to be inserted into user1's
137+
enrollment certificate by default. The *email* attribute is not added
138+
to the enrollment certificate by default.
139+
140+
```
141+
fabric-ca-client register --id.name user1 --id.secret user1pw --id.type user --id.affiliation org1 --id.attrs 'app1Admin=true:ecert,email=user1@gmail.com'
142+
```
143+
144+
2. When you enroll an identity, you may request that one or more attributes
145+
be added to the certificate.
146+
For each attribute requested, you may specify whether the attribute is
147+
optional or not. If it is not optional but does not exist for the identity,
148+
enrollment fails.
149+
150+
The following shows how to enroll *user1* with the *email* attribute,
151+
without the *app1Admin* attribute and optionally with the *phone* attribute
152+
(if the user possesses *phone* attribute).
153+
```
154+
fabric-ca-client enroll -u http://user1:user1pw@localhost:7054 --enrollment.attrs "email,phone:opt"
155+
```
156+
#### Attribute format in a certificate
157+
158+
Attributes are stored inside an X509 certificate as an extension with an
159+
ASN.1 OID (Abstract Syntax Notation Object IDentifier)
160+
of `1.2.3.4.5.6.7.8.1`. The value of the extension is a JSON string of the
161+
form `{"attrs":{<attrName>:<attrValue}}`. The following is a sample of a
162+
certificate which contains the `attr1` attribute with a value of `val1`.
163+
See the final entry in the *X509v3 extensions* section. Note also that the JSON
164+
entry could contain multiple attributes, though this sample shows only one.
165+
166+
```
167+
Certificate:
168+
Data:
169+
Version: 3 (0x2)
170+
Serial Number:
171+
1e:49:98:e9:f4:4f:d0:03:53:bf:36:81:c0:a0:a4:31:96:4f:52:75
172+
Signature Algorithm: ecdsa-with-SHA256
173+
Issuer: CN=fabric-ca-server
174+
Validity
175+
Not Before: Sep 8 03:42:00 2017 GMT
176+
Not After : Sep 8 03:42:00 2018 GMT
177+
Subject: CN=MyTestUserWithAttrs
178+
Subject Public Key Info:
179+
Public Key Algorithm: id-ecPublicKey
180+
EC Public Key:
181+
pub:
182+
04:e6:07:5a:f7:09:d5:af:38:e3:f7:a2:90:77:0e:
183+
32:67:5b:70:a7:37:ca:b5:c9:d8:91:77:39:ae:03:
184+
a0:36:ad:72:b3:3c:89:6d:1e:f6:1b:6d:2a:88:49:
185+
92:6e:6e:cc:bc:81:52:fa:19:88:18:5c:d7:6e:eb:
186+
d4:73:cc:51:79
187+
ASN1 OID: prime256v1
188+
X509v3 extensions:
189+
X509v3 Key Usage: critical
190+
Certificate Sign
191+
X509v3 Basic Constraints: critical
192+
CA:FALSE
193+
X509v3 Subject Key Identifier:
194+
D8:28:B4:C0:BC:92:4A:D3:C3:8C:54:6C:08:86:33:10:A6:8D:83:AE
195+
X509v3 Authority Key Identifier:
196+
keyid:C4:B3:FE:76:0D:E2:DE:3C:FC:75:FB:AE:55:86:04:F0:BB:7F:F6:01
197+
198+
X509v3 Subject Alternative Name:
199+
DNS:Anils-MacBook-Pro.local
200+
1.2.3.4.5.6.7.8.1:
201+
{"attrs":{"attr1":"val1"}}
202+
Signature Algorithm: ecdsa-with-SHA256
203+
30:45:02:21:00:fb:84:a9:65:29:b2:f4:d3:bc:1a:8b:47:92:
204+
5e:41:27:2d:26:ec:f7:cd:aa:86:46:a4:ac:da:25:be:40:1d:
205+
c5:02:20:08:3f:49:86:58:a7:20:48:64:4c:30:1b:da:a9:a2:
206+
f2:b4:16:28:f6:fd:e1:46:dd:6b:f2:3f:2f:37:4a:4c:72
207+
```
208+
209+
If you want to use the client identity library to extract or assert attribute
210+
values as described previously but you are not using Hyperledger Fabric CA,
211+
then you must ensure that the certificates which are issued by your external CA
212+
contain attributes of the form shown above. In particular, the certificates
213+
must contain the `1.2.3.4.5.6.7.8.1` X509v3 extension with a JSON value
214+
containing the attribute names and values for the identity.

0 commit comments

Comments
 (0)