-
Notifications
You must be signed in to change notification settings - Fork 0
/
Auithenticator.ts
299 lines (274 loc) · 8.4 KB
/
Auithenticator.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
import {Wallet, X509Identity} from 'fabric-network';
import FabricCAServices from 'fabric-ca-client';
import * as fs from 'fs';
import * as grpc from '@grpc/grpc-js';
import path from 'path';
import {
connect,
Gateway,
Identity,
Signer,
signers,
} from '@hyperledger/fabric-gateway';
import * as crypto from 'crypto';
const cryptoPath = envOrDefault('CRYPTO_PATH', path.resolve('certs'));
const certPath = envOrDefault(
'CERT_PATH',
path.resolve(cryptoPath, 'msp', 'signcerts', String(process.env.CERT_PATH))
);
const keyDirectoryPath = envOrDefault(
'KEY_DIRECTORY_PATH',
path.resolve(cryptoPath, 'msp', 'keystore')
);
const tlsCertPath = envOrDefault(
'TLS_CERT_PATH',
path.resolve(
cryptoPath,
'msp',
'tlscacerts',
String(process.env.TLS_CERT_PATH)
)
);
const peerEndpoint = envOrDefault(
'PEER_ENDPOINT',
String(process.env.PEER_ENDPOINT)
);
const peerHostAlias = envOrDefault('PEER_HOST_ALIAS', 'peer0.org1.example.com');
const mspId = envOrDefault('MSP_ID', 'Org1MSP');
/**
* envOrDefault() will return the value of an environment variable, or a default value if the variable is undefined.
*/
function envOrDefault(key: string, defaultValue: string): string {
return process.env[key] || defaultValue;
}
export class Authenticator {
private networkConfiguration: any;
private wallet: Wallet;
private certificateAuthorityInfo: any;
constructor(
walletInstance: Wallet,
networkConfiguration: any,
organizationId: string
) {
this.wallet = walletInstance;
this.networkConfiguration = networkConfiguration;
this.certificateAuthorityInfo = this.networkConfiguration;
}
/**
* @name getGatewayConnection
* @returns connected gateway to hyperledger blockchain
*/
public async getGatewayConnection(): Promise<Gateway> {
const client = await this.newGrpcConnection();
return connect({
client,
identity: await this.newIdentity(),
signer: await this.newSigner(),
// Default timeouts for different gRPC calls
evaluateOptions: () => {
return {deadline: Date.now() + 5000}; // 5 seconds
},
endorseOptions: () => {
return {deadline: Date.now() + 15000}; // 15 seconds
},
submitOptions: () => {
return {deadline: Date.now() + 5000}; // 5 seconds
},
commitStatusOptions: () => {
return {deadline: Date.now() + 60000}; // 1 minute
},
}); // Create a new gateway for connecting to our peer node.
}
private async newGrpcConnection(): Promise<grpc.Client> {
const tlsRootCert = fs.readFileSync(tlsCertPath);
const tlsCredentials = grpc.credentials.createSsl(tlsRootCert);
return new grpc.Client(peerEndpoint, tlsCredentials, {
'grpc.ssl_target_name_override': peerHostAlias,
});
}
async newIdentity(): Promise<Identity> {
const credentials = fs.readFileSync(certPath);
return {mspId, credentials};
}
async newSigner(): Promise<Signer> {
const files = fs.readdirSync(keyDirectoryPath);
const keyPath = path.resolve(keyDirectoryPath, files[0]);
const privateKeyPem = fs.readFileSync(keyPath);
// eslint-disable-next-line node/no-unsupported-features/node-builtins
const privateKey = crypto.createPrivateKey(privateKeyPem);
return signers.newPrivateKeySigner(privateKey);
}
// THESE FUNCTIONS BELLOW ARE PARTLY DEPRECATED, BUT KEPT SO WE CAN REFACTOR THEM
/**
* @method checkUserExists
* @async
* @description Checks if wallet address is registered on hyperledger network
* @param walletAddress
* @return boolean
*/
public async checkUserExists(walletAddress: string): Promise<boolean> {
const identity = await this.wallet.get(walletAddress);
if (identity) {
return true;
}
console.log(
'There is no identity for "' +
walletAddress +
'" does not exist in the network'
);
return false;
}
/**
* @method registerUser
* @async
* @param userWalletAddress
* @param organization
* @param mspid
* @description registers user wallet in network
*/
public async registerUser(
userWalletAddress: string,
organization: string,
mspId: string
) {
// Register the user, enroll the user, and import the new identity into the wallet.
// Organization = 'org1.department1'
try {
const certificateAuthority = new FabricCAServices(
this.certificateAuthorityInfo.url
);
//TODO check this logic
/*if (await this.checkUserExists(userWalletAddress))
throw new Error(
'A user is already registered with the following wallet address: ' +
userWalletAddress
);*/
const adminUser = await this.getAdminContext();
const secret = await certificateAuthority.register(
{
affiliation: organization,
enrollmentID: userWalletAddress,
role: 'client',
},
adminUser
);
return await this.enrollIdentity(
certificateAuthority,
userWalletAddress,
secret,
mspId
);
} catch (error: any) {
console.log('An error ocurred while registering user: ', error.message);
return false;
}
}
/**
* @method registerAdmin
* @async
* @param mspId
* @description registers admin wallet in network
*/
public async registerAdmin(mspId: string): Promise<boolean> {
try {
// organization = ca.org1.example.com
const TLSCertificate = this.certificateAuthorityInfo.tlsCACerts.pem;
const certificateAuthority: FabricCAServices = new FabricCAServices(
this.certificateAuthorityInfo.url,
{trustedRoots: TLSCertificate, verify: false},
this.certificateAuthorityInfo.caName
);
//await this.getAdminIdentity(); //Check identity exists
// Enroll the admin user, and import the new identity into the wallet.
return await this.enrollIdentity(
certificateAuthority,
String(process.env.ADMIN_WALLET),
String(process.env.ADMIN_WALLET_SECRET),
mspId
);
} catch (error) {
console.log('An issue ocurred while registering admin: ', error);
return false;
}
}
/**
* @method enrollIdentity
* @async
* @param (FabricCAServices) Ceritificate authority client
* @param (string) walletAddress - User id
* @param (string) secret
* @param (string) mspId
* @description enrolls an identiity into the network
* @returns boolean
*/
private async enrollIdentity(
client: FabricCAServices,
walletAddress: string,
secret: string,
mspId: string
): Promise<boolean> {
try {
//TODO issue with admin wallet address and secret
const enrollment = await client.enroll({
enrollmentID: walletAddress,
enrollmentSecret: secret,
});
const x509Identity: X509Identity = {
credentials: {
certificate: enrollment.certificate,
privateKey: enrollment.key.toBytes(),
},
mspId: mspId,
type: 'X.509',
};
await this.wallet.put(walletAddress, x509Identity);
console.log(
'Successfully enrolled wallet ' +
walletAddress +
' and imported it into the wallet'
);
return true;
} catch (error) {
console.log(
'An error ocurred while trying to enrol identity: ' + walletAddress
);
return false;
}
}
/**
* @method getAdminIdentity
* @async
* @description gets admin identity
*/
private async getAdminIdentity(): Promise<any> {
// Check to see if we've already enrolled the admin user.
const adminIdentity = await this.wallet.get(`${process.env.ADMIN_WALLET}`);
if (!adminIdentity)
throw new Error(
'There is not an admin identity registered with the foillowing address: ' +
String(process.env.ADMIN_WALLET)
);
return adminIdentity;
}
/**
* @method getAdminContext
* @async
* @description gets admin context
* @returns adminContext
*/
private async getAdminContext(): Promise<any> {
try {
const adminIdentity = await this.getAdminIdentity();
const provider = this.wallet
.getProviderRegistry()
.getProvider(adminIdentity.type);
return await provider.getUserContext(
adminIdentity,
`${process.env.ADMIN_WALLET}`
);
} catch (error) {
console.log('An error ocurred while getting admin context: ', error);
throw new Error("Coudln't get admin context.");
}
}
}