@alternative-path/testlens-playwright-reporter 0.3.8 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.d.ts CHANGED
@@ -157,6 +157,17 @@ export interface SpecData {
157
157
  export declare class TestLensReporter implements Reporter {
158
158
  private config;
159
159
  private axiosInstance;
160
+ /**
161
+ * Get bundled CA certificates for TestLens
162
+ * Uses custom CA bundle packaged with the reporter
163
+ * This ensures SSL works out-of-the-box without relying on system certificates
164
+ */
165
+ private static getBundledCaCertificates;
166
+ /**
167
+ * Automatically detect and load system CA certificates
168
+ * Uses bundled certificates as primary source, falls back to system certificates
169
+ */
170
+ private static getSystemCaCertificates;
160
171
  private runId;
161
172
  private runMetadata;
162
173
  private specMap;
package/index.js CHANGED
@@ -7,6 +7,7 @@ const os = tslib_1.__importStar(require("os"));
7
7
  const path = tslib_1.__importStar(require("path"));
8
8
  const fs = tslib_1.__importStar(require("fs"));
9
9
  const https = tslib_1.__importStar(require("https"));
10
+ const tls = tslib_1.__importStar(require("tls"));
10
11
  const axios_1 = tslib_1.__importDefault(require("axios"));
11
12
  const child_process_1 = require("child_process");
12
13
  // Lazy-load mime module to support ESM
@@ -20,25 +21,65 @@ async function getMime() {
20
21
  return mimeModule;
21
22
  }
22
23
  class TestLensReporter {
24
+ /**
25
+ * Get bundled CA certificates for TestLens
26
+ * Uses custom CA bundle packaged with the reporter
27
+ * This ensures SSL works out-of-the-box without relying on system certificates
28
+ */
29
+ static getBundledCaCertificates() {
30
+ try {
31
+ // Load the bundled CA certificate file for testlens.qa-path.com
32
+ const certPath = path.join(__dirname, 'testlens-ca-bundle.pem');
33
+ if (fs.existsSync(certPath)) {
34
+ const certData = fs.readFileSync(certPath, 'utf8');
35
+ // Split the bundle into individual certificates
36
+ const certs = certData.match(/-----BEGIN CERTIFICATE-----[\s\S]+?-----END CERTIFICATE-----/g);
37
+ if (certs && certs.length > 0) {
38
+ const buffers = certs.map(cert => Buffer.from(cert, 'utf8'));
39
+ if (process.env.DEBUG) {
40
+ console.log(`✓ Using bundled TestLens CA certificates (${buffers.length} certificate(s))`);
41
+ }
42
+ return buffers;
43
+ }
44
+ }
45
+ }
46
+ catch (error) {
47
+ if (process.env.DEBUG) {
48
+ console.log('⚠️ Bundled CA certificate not available, will use fallback');
49
+ }
50
+ }
51
+ // Fallback to Node.js built-in root certificates
52
+ try {
53
+ if (tls.rootCertificates && Array.isArray(tls.rootCertificates) && tls.rootCertificates.length > 0) {
54
+ const rootCerts = tls.rootCertificates.map(cert => Buffer.from(cert, 'utf8'));
55
+ if (process.env.DEBUG) {
56
+ console.log(`✓ Using Node.js built-in root certificates (${rootCerts.length} certificates)`);
57
+ }
58
+ return rootCerts;
59
+ }
60
+ }
61
+ catch (error) {
62
+ if (process.env.DEBUG) {
63
+ console.log('⚠️ Node.js built-in root certificates not available');
64
+ }
65
+ }
66
+ return undefined;
67
+ }
23
68
  /**
24
69
  * Automatically detect and load system CA certificates
25
- * Tries multiple common system certificate locations
70
+ * Uses bundled certificates as primary source, falls back to system certificates
26
71
  */
27
72
  static getSystemCaCertificates() {
28
- const certificates = [];
73
+ // First, try to use our bundled certificates (Node.js rootCertificates)
74
+ const bundledCerts = TestLensReporter.getBundledCaCertificates();
75
+ if (bundledCerts && bundledCerts.length > 0) {
76
+ return bundledCerts;
77
+ }
78
+ // Fallback: Try to load from file system (for older Node.js versions or special cases)
29
79
  const platform = os.platform();
30
- // Common certificate store locations by platform
80
+ const certificates = [];
31
81
  const certPaths = [];
32
- if (platform === 'win32') {
33
- // Windows: Node.js uses Windows certificate store automatically
34
- // But we can also check common locations
35
- const winPaths = [
36
- process.env.CERT_PATH,
37
- 'C:\\Windows\\System32\\certmgr.msc', // Not a file, but indicates cert store
38
- ];
39
- certPaths.push(...winPaths.filter(Boolean));
40
- }
41
- else if (platform === 'darwin') {
82
+ if (platform === 'darwin') {
42
83
  // macOS: Common certificate locations
43
84
  certPaths.push('/etc/ssl/cert.pem', '/usr/local/etc/openssl/cert.pem', '/opt/homebrew/etc/openssl/cert.pem', '/System/Library/OpenSSL/certs/cert.pem');
44
85
  }
@@ -63,7 +104,9 @@ class TestLensReporter {
63
104
  // This is expected as not all paths will exist on every system
64
105
  }
65
106
  }
66
- return certificates;
107
+ // Return undefined if no certificates found (let Node.js use defaults)
108
+ // Return certificates array if we found any
109
+ return certificates.length > 0 ? certificates : undefined;
67
110
  }
68
111
  /**
69
112
  * Parse custom metadata from environment variables
@@ -143,35 +186,44 @@ class TestLensReporter {
143
186
  // Determine SSL validation behavior
144
187
  let rejectUnauthorized = true; // Default to secure
145
188
  let ca = undefined;
146
- // Automatically detect and load system CA certificates
147
- // This helps resolve "unable to get local issuer certificate" errors
148
- const systemCerts = TestLensReporter.getSystemCaCertificates();
189
+ // Use bundled CA certificates as primary source (Node.js rootCertificates)
190
+ // This ensures consistent behavior across all platforms
191
+ const bundledCerts = TestLensReporter.getBundledCaCertificates();
149
192
  // Load custom CA certificate if explicitly provided (for advanced users)
193
+ // Custom certificates will be combined with bundled certificates
150
194
  if (this.config.caCertificate) {
151
195
  try {
152
196
  if (fs.existsSync(this.config.caCertificate)) {
153
197
  const customCert = fs.readFileSync(this.config.caCertificate);
154
- // Combine system certs with custom cert
155
- ca = systemCerts.length > 0 ? [...systemCerts, customCert] : customCert;
156
- console.log(`✓ Using custom CA certificate: ${this.config.caCertificate}`);
198
+ // Combine bundled certs with custom cert
199
+ if (bundledCerts && Array.isArray(bundledCerts) && bundledCerts.length > 0) {
200
+ ca = [...bundledCerts, customCert];
201
+ console.log(`✓ Using bundled CA certificates + custom certificate: ${this.config.caCertificate}`);
202
+ }
203
+ else {
204
+ ca = customCert;
205
+ console.log(`✓ Using custom CA certificate: ${this.config.caCertificate}`);
206
+ }
157
207
  }
158
208
  else {
159
209
  console.warn(`⚠️ CA certificate file not found: ${this.config.caCertificate}`);
160
- // Fall back to system certs if custom cert not found
161
- ca = systemCerts.length > 0 ? systemCerts : undefined;
210
+ // Fall back to bundled certs if custom cert not found
211
+ ca = bundledCerts || undefined;
162
212
  }
163
213
  }
164
214
  catch (error) {
165
215
  console.warn(`⚠️ Failed to read CA certificate file: ${this.config.caCertificate}`, error.message);
166
- // Fall back to system certs if custom cert read fails
167
- ca = systemCerts.length > 0 ? systemCerts : undefined;
216
+ // Fall back to bundled certs if custom cert read fails
217
+ ca = bundledCerts || undefined;
168
218
  }
169
219
  }
170
220
  else {
171
- // Use automatically detected system certificates
172
- ca = systemCerts.length > 0 ? systemCerts : undefined;
173
- // Node.js will use system default CA store if we don't specify 'ca'
174
- // But providing system certs explicitly can help in some environments
221
+ // Use bundled certificates as primary source
222
+ // This works reliably across all platforms (Windows, macOS, Linux)
223
+ ca = bundledCerts || undefined;
224
+ if (ca && process.env.DEBUG) {
225
+ console.log(`✓ Using bundled CA certificates (${Array.isArray(ca) ? ca.length : 1} certificates)`);
226
+ }
175
227
  }
176
228
  // Check various ways SSL validation can be disabled (in order of precedence)
177
229
  if (this.config.ignoreSslErrors) {
@@ -196,10 +248,17 @@ class TestLensReporter {
196
248
  minVersion: 'TLSv1.2',
197
249
  maxVersion: 'TLSv1.3'
198
250
  };
199
- // Add CA certificates if available (Node.js will use system defaults if not specified)
200
- // Explicitly setting 'ca' can help in environments where Node.js doesn't find certs automatically
201
- if (ca && ca.length > 0) {
202
- httpsAgentOptions.ca = ca;
251
+ // Add CA certificates if available
252
+ // On Windows, ca will be undefined to let Node.js use Windows certificate store automatically
253
+ // On Unix systems, ca will contain certificates if found, or undefined to use Node.js defaults
254
+ if (ca !== undefined) {
255
+ if (Array.isArray(ca) && ca.length > 0) {
256
+ httpsAgentOptions.ca = ca;
257
+ }
258
+ else if (typeof ca === 'string' || Buffer.isBuffer(ca)) {
259
+ httpsAgentOptions.ca = ca;
260
+ }
261
+ // If ca is undefined, we don't set it, allowing Node.js to use its default certificate store
203
262
  }
204
263
  this.axiosInstance = axios_1.default.create({
205
264
  baseURL: this.config.apiEndpoint,
package/index.ts CHANGED
@@ -3,6 +3,7 @@ import * as os from 'os';
3
3
  import * as path from 'path';
4
4
  import * as fs from 'fs';
5
5
  import * as https from 'https';
6
+ import * as tls from 'tls';
6
7
  import axios, { AxiosInstance } from 'axios';
7
8
  import type { Reporter, TestCase, TestResult, FullConfig, Suite } from '@playwright/test/reporter';
8
9
  import { execSync } from 'child_process';
@@ -183,26 +184,67 @@ export class TestLensReporter implements Reporter {
183
184
  private config: Required<TestLensReporterConfig>;
184
185
  private axiosInstance: AxiosInstance;
185
186
 
187
+ /**
188
+ * Get bundled CA certificates for TestLens
189
+ * Uses custom CA bundle packaged with the reporter
190
+ * This ensures SSL works out-of-the-box without relying on system certificates
191
+ */
192
+ private static getBundledCaCertificates(): Buffer[] | undefined {
193
+ try {
194
+ // Load the bundled CA certificate file for testlens.qa-path.com
195
+ const certPath = path.join(__dirname, 'testlens-ca-bundle.pem');
196
+ if (fs.existsSync(certPath)) {
197
+ const certData = fs.readFileSync(certPath, 'utf8');
198
+ // Split the bundle into individual certificates
199
+ const certs = certData.match(/-----BEGIN CERTIFICATE-----[\s\S]+?-----END CERTIFICATE-----/g);
200
+ if (certs && certs.length > 0) {
201
+ const buffers = certs.map(cert => Buffer.from(cert, 'utf8'));
202
+ if (process.env.DEBUG) {
203
+ console.log(`✓ Using bundled TestLens CA certificates (${buffers.length} certificate(s))`);
204
+ }
205
+ return buffers;
206
+ }
207
+ }
208
+ } catch (error) {
209
+ if (process.env.DEBUG) {
210
+ console.log('⚠️ Bundled CA certificate not available, will use fallback');
211
+ }
212
+ }
213
+
214
+ // Fallback to Node.js built-in root certificates
215
+ try {
216
+ if (tls.rootCertificates && Array.isArray(tls.rootCertificates) && tls.rootCertificates.length > 0) {
217
+ const rootCerts = tls.rootCertificates.map(cert => Buffer.from(cert, 'utf8'));
218
+ if (process.env.DEBUG) {
219
+ console.log(`✓ Using Node.js built-in root certificates (${rootCerts.length} certificates)`);
220
+ }
221
+ return rootCerts;
222
+ }
223
+ } catch (error) {
224
+ if (process.env.DEBUG) {
225
+ console.log('⚠️ Node.js built-in root certificates not available');
226
+ }
227
+ }
228
+ return undefined;
229
+ }
230
+
186
231
  /**
187
232
  * Automatically detect and load system CA certificates
188
- * Tries multiple common system certificate locations
233
+ * Uses bundled certificates as primary source, falls back to system certificates
189
234
  */
190
- private static getSystemCaCertificates(): Buffer[] {
191
- const certificates: Buffer[] = [];
192
- const platform = os.platform();
235
+ private static getSystemCaCertificates(): Buffer[] | undefined {
236
+ // First, try to use our bundled certificates (Node.js rootCertificates)
237
+ const bundledCerts = TestLensReporter.getBundledCaCertificates();
238
+ if (bundledCerts && bundledCerts.length > 0) {
239
+ return bundledCerts;
240
+ }
193
241
 
194
- // Common certificate store locations by platform
242
+ // Fallback: Try to load from file system (for older Node.js versions or special cases)
243
+ const platform = os.platform();
244
+ const certificates: Buffer[] = [];
195
245
  const certPaths: string[] = [];
196
246
 
197
- if (platform === 'win32') {
198
- // Windows: Node.js uses Windows certificate store automatically
199
- // But we can also check common locations
200
- const winPaths = [
201
- process.env.CERT_PATH,
202
- 'C:\\Windows\\System32\\certmgr.msc', // Not a file, but indicates cert store
203
- ];
204
- certPaths.push(...winPaths.filter(Boolean) as string[]);
205
- } else if (platform === 'darwin') {
247
+ if (platform === 'darwin') {
206
248
  // macOS: Common certificate locations
207
249
  certPaths.push(
208
250
  '/etc/ssl/cert.pem',
@@ -240,7 +282,9 @@ export class TestLensReporter implements Reporter {
240
282
  }
241
283
  }
242
284
 
243
- return certificates;
285
+ // Return undefined if no certificates found (let Node.js use defaults)
286
+ // Return certificates array if we found any
287
+ return certificates.length > 0 ? certificates : undefined;
244
288
  }
245
289
  private runId: string;
246
290
  private runMetadata: RunMetadata;
@@ -334,33 +378,41 @@ export class TestLensReporter implements Reporter {
334
378
  let rejectUnauthorized = true; // Default to secure
335
379
  let ca: Buffer | string | Buffer[] | undefined = undefined;
336
380
 
337
- // Automatically detect and load system CA certificates
338
- // This helps resolve "unable to get local issuer certificate" errors
339
- const systemCerts = TestLensReporter.getSystemCaCertificates();
381
+ // Use bundled CA certificates as primary source (Node.js rootCertificates)
382
+ // This ensures consistent behavior across all platforms
383
+ const bundledCerts = TestLensReporter.getBundledCaCertificates();
340
384
 
341
385
  // Load custom CA certificate if explicitly provided (for advanced users)
386
+ // Custom certificates will be combined with bundled certificates
342
387
  if (this.config.caCertificate) {
343
388
  try {
344
389
  if (fs.existsSync(this.config.caCertificate)) {
345
390
  const customCert = fs.readFileSync(this.config.caCertificate);
346
- // Combine system certs with custom cert
347
- ca = systemCerts.length > 0 ? [...systemCerts, customCert] : customCert;
348
- console.log(`✓ Using custom CA certificate: ${this.config.caCertificate}`);
391
+ // Combine bundled certs with custom cert
392
+ if (bundledCerts && Array.isArray(bundledCerts) && bundledCerts.length > 0) {
393
+ ca = [...bundledCerts, customCert];
394
+ console.log(`✓ Using bundled CA certificates + custom certificate: ${this.config.caCertificate}`);
395
+ } else {
396
+ ca = customCert;
397
+ console.log(`✓ Using custom CA certificate: ${this.config.caCertificate}`);
398
+ }
349
399
  } else {
350
400
  console.warn(`⚠️ CA certificate file not found: ${this.config.caCertificate}`);
351
- // Fall back to system certs if custom cert not found
352
- ca = systemCerts.length > 0 ? systemCerts : undefined;
401
+ // Fall back to bundled certs if custom cert not found
402
+ ca = bundledCerts || undefined;
353
403
  }
354
404
  } catch (error) {
355
405
  console.warn(`⚠️ Failed to read CA certificate file: ${this.config.caCertificate}`, (error as Error).message);
356
- // Fall back to system certs if custom cert read fails
357
- ca = systemCerts.length > 0 ? systemCerts : undefined;
406
+ // Fall back to bundled certs if custom cert read fails
407
+ ca = bundledCerts || undefined;
358
408
  }
359
409
  } else {
360
- // Use automatically detected system certificates
361
- ca = systemCerts.length > 0 ? systemCerts : undefined;
362
- // Node.js will use system default CA store if we don't specify 'ca'
363
- // But providing system certs explicitly can help in some environments
410
+ // Use bundled certificates as primary source
411
+ // This works reliably across all platforms (Windows, macOS, Linux)
412
+ ca = bundledCerts || undefined;
413
+ if (ca && process.env.DEBUG) {
414
+ console.log(`✓ Using bundled CA certificates (${Array.isArray(ca) ? ca.length : 1} certificates)`);
415
+ }
364
416
  }
365
417
 
366
418
  // Check various ways SSL validation can be disabled (in order of precedence)
@@ -386,10 +438,16 @@ export class TestLensReporter implements Reporter {
386
438
  maxVersion: 'TLSv1.3'
387
439
  };
388
440
 
389
- // Add CA certificates if available (Node.js will use system defaults if not specified)
390
- // Explicitly setting 'ca' can help in environments where Node.js doesn't find certs automatically
391
- if (ca && ca.length > 0) {
392
- httpsAgentOptions.ca = ca;
441
+ // Add CA certificates if available
442
+ // On Windows, ca will be undefined to let Node.js use Windows certificate store automatically
443
+ // On Unix systems, ca will contain certificates if found, or undefined to use Node.js defaults
444
+ if (ca !== undefined) {
445
+ if (Array.isArray(ca) && ca.length > 0) {
446
+ httpsAgentOptions.ca = ca;
447
+ } else if (typeof ca === 'string' || Buffer.isBuffer(ca)) {
448
+ httpsAgentOptions.ca = ca;
449
+ }
450
+ // If ca is undefined, we don't set it, allowing Node.js to use its default certificate store
393
451
  }
394
452
 
395
453
  this.axiosInstance = axios.create({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alternative-path/testlens-playwright-reporter",
3
- "version": "0.3.8",
3
+ "version": "0.4.0",
4
4
  "description": "Universal Playwright reporter for TestLens - works with both TypeScript and JavaScript projects",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -14,6 +14,7 @@
14
14
  "lib/",
15
15
  "postinstall.js",
16
16
  "cross-env.js",
17
+ "testlens-ca-bundle.pem",
17
18
  "README.md",
18
19
  "CHANGELOG.md"
19
20
  ],
@@ -0,0 +1,88 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIFvDCCBKSgAwIBAgIQCCpc5jpiqFvmHWmaKaa8zTANBgkqhkiG9w0BAQsFADA8
3
+ MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRwwGgYDVQQDExNBbWF6b24g
4
+ UlNBIDIwNDggTTA0MB4XDTI1MTExNDAwMDAwMFoXDTI2MTIxMzIzNTk1OVowGDEW
5
+ MBQGA1UEAwwNKi5xYS1wYXRoLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
6
+ AQoCggEBAMFsdDGpKLNQ9GayoFXQpE9VLNxEZ/76AaiJMj30Nkuf245KxcPdmPMQ
7
+ rklyBsKv2r4vGwqIrIh4ey59Zpi5z/GMtSP6DwPU/MGGRQGJ9Mpc2dhpxNvka7hW
8
+ 9+t/uFAMbwvAhAe82fahsd6q/jtRMChkKQ2Ndln41PPnTPzqqoc2GWdYJO69W1x0
9
+ 5CbovMOOoGKkskrS2TNe5+vYp8c8AWR6ga3zR2lxMVDAAXKcD/ejMq/FMR8TD9rf
10
+ 6pWnsalQE7UAIgSltu9hrJRttCnyC6343WIQKspd3x+fZ6WdqtR4YywLij9DMBgJ
11
+ KwYUHMjoY4lfkSgowhgnuCUFeqVhBrsCAwEAAaOCAtwwggLYMB8GA1UdIwQYMBaA
12
+ FB9SkmFWglR/gWbYHT0KqjJch90IMB0GA1UdDgQWBBSsbNiBXRvG7yzfgQnHA4Fm
13
+ Gvve1TAYBgNVHREEETAPgg0qLnFhLXBhdGguY29tMBMGA1UdIAQMMAowCAYGZ4EM
14
+ AQIBMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDATA7BgNVHR8E
15
+ NDAyMDCgLqAshipodHRwOi8vY3JsLnIybTA0LmFtYXpvbnRydXN0LmNvbS9yMm0w
16
+ NC5jcmwwdQYIKwYBBQUHAQEEaTBnMC0GCCsGAQUFBzABhiFodHRwOi8vb2NzcC5y
17
+ Mm0wNC5hbWF6b250cnVzdC5jb20wNgYIKwYBBQUHMAKGKmh0dHA6Ly9jcnQucjJt
18
+ MDQuYW1hem9udHJ1c3QuY29tL3IybTA0LmNlcjAMBgNVHRMBAf8EAjAAMIIBfgYK
19
+ KwYBBAHWeQIEAgSCAW4EggFqAWgAdgDYCVU7lE96/8gWGW+UT4WrsPj8XodVJg8V
20
+ 0S5yu0VLFAAAAZqBmF/qAAAEAwBHMEUCIHg3mktTsuS8r57mR014haS8fqwcbqa1
21
+ P3so9Qd02JFBAiEAsHQf6eH9AL0HoG5jEVfz4aZdNp/Y8unnDO+ZWSfW/wcAdgDC
22
+ MX5XRRmjRe5/ON6ykEHrx8IhWiK/f9W1rXaa2Q5SzQAAAZqBmF/lAAAEAwBHMEUC
23
+ IQCZhIaG3vpxTThIdHhvNCymkHGKFLggUBcPCqYMdYVFpAIgW+BszH9Kdon3IKNJ
24
+ xKx5e4K+XZ+NhfXqqnCmPYeCwzQAdgCUTkOH+uzB74HzGSQmqBhlAcfTXzgCAT9y
25
+ Z31VNy4Z2AAAAZqBmF/1AAAEAwBHMEUCIQDGh+jKNI6NO30js2yl0ItBltCDGA5d
26
+ 3A1qoPf81FCF8wIgFTxoXXotS8nhDzOeyJh1wL6wKMxcwKXUUMcOKEjFsH4wDQYJ
27
+ KoZIhvcNAQELBQADggEBAMY6zXuf7YSu4s/nHd4qSjOq7mAPvWKSumPMXcRp4FfX
28
+ 16dAyqaiasX2B7dXccks4QeCUyNxCjh89irTYwgDcde8J05PEM9dpxUglyWE6gEB
29
+ r+pp8xJzT9hP2TmLhkNsFKhiT8aR+wz9fiALVDeQLyUS1GOSmnAXbH8MjZkm5Cxb
30
+ Taqb+N8alKrMf7Y9Cwf77KRFpKqm+b1e6h/EuVIJWAFau1jKVS5Qd6KTjyf0sRys
31
+ 7nvF3JqKVIb6BlTimNUq1wYMJKX6mOb/MlHo8juzKMb+MYUA5ZHrO36u3nOgThiI
32
+ oOJavnwzLhk7AWp8urdy9yTj8P3b/3H3VtCfYMeAabE=
33
+ -----END CERTIFICATE-----
34
+
35
+ -----BEGIN CERTIFICATE-----
36
+ MIIEXjCCA0agAwIBAgITB3MSTyqVLj7Rili9uF0bwM5fJzANBgkqhkiG9w0BAQsF
37
+ ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6
38
+ b24gUm9vdCBDQSAxMB4XDTIyMDgyMzIyMjYzNVoXDTMwMDgyMzIyMjYzNVowPDEL
39
+ MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEcMBoGA1UEAxMTQW1hem9uIFJT
40
+ QSAyMDQ4IE0wNDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM3pVR6A
41
+ lQOp4xe776FdePXyejgA38mYx1ou9/jrpV6Sfn+/oqBKgwhY6ePsQHHQayWBJdBn
42
+ v4Wz363qRI4XUh9swBFJ11TnZ3LqOMvHmWq2+loA0QPtOfXdJ2fHBLrBrngtJ/GB
43
+ 0p5olAVYrSZgvQGP16Rf8ddtNyxEEhYm3HuhmNi+vSeAq1tLYJPAvRCXonTpWdSD
44
+ xY6hvdmxlqTYi82AtBXSfpGQ58HHM0hw0C6aQakghrwWi5fGslLOqzpimNMIsT7c
45
+ qa0GJx6JfKqJqmQQNplO2h8n9ZsFJgBowof01ppdoLAWg6caMOM0om/VILKaa30F
46
+ 9W/r8Qjah7ltGVkCAwEAAaOCAVowggFWMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYD
47
+ VR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAdBgNV
48
+ HQ4EFgQUH1KSYVaCVH+BZtgdPQqqMlyH3QgwHwYDVR0jBBgwFoAUhBjMhTTsvAyU
49
+ lC4IWZzHshBOCggwewYIKwYBBQUHAQEEbzBtMC8GCCsGAQUFBzABhiNodHRwOi8v
50
+ b2NzcC5yb290Y2ExLmFtYXpvbnRydXN0LmNvbTA6BggrBgEFBQcwAoYuaHR0cDov
51
+ L2NydC5yb290Y2ExLmFtYXpvbnRydXN0LmNvbS9yb290Y2ExLmNlcjA/BgNVHR8E
52
+ ODA2MDSgMqAwhi5odHRwOi8vY3JsLnJvb3RjYTEuYW1hem9udHJ1c3QuY29tL3Jv
53
+ b3RjYTEuY3JsMBMGA1UdIAQMMAowCAYGZ4EMAQIBMA0GCSqGSIb3DQEBCwUAA4IB
54
+ AQA+1O5UsAaNuW3lHzJtpNGwBnZd9QEYFtxpiAnIaV4qApnGS9OCw5ZPwie7YSlD
55
+ ZF5yyFPsFhUC2Q9uJHY/CRV1b5hIiGH0+6+w5PgKiY1MWuWT8VAaJjFxvuhM7a/e
56
+ fN2TIw1Wd6WCl6YRisunjQOrSP+unqC8A540JNyZ1JOE3jVqat3OZBGgMvihdj2w
57
+ Y23EpwesrKiQzkHzmvSH67PVW4ycbPy08HVZnBxZ5NrlGG9bwXR3fNTaz+c+Ej6c
58
+ 5AnwI3qkOFgSkg3Y75cdFz6pO/olK+e3AqygAcv0WjzmkDPuBjssuZjCHMC56oH3
59
+ GJkV29Di2j5prHJbwZjG1inU
60
+ -----END CERTIFICATE-----
61
+
62
+ -----BEGIN CERTIFICATE-----
63
+ MIIEkjCCA3qgAwIBAgITBn+USionzfP6wq4rAfkI7rnExjANBgkqhkiG9w0BAQsF
64
+ ADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNj
65
+ b3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4x
66
+ OzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1
67
+ dGhvcml0eSAtIEcyMB4XDTE1MDUyNTEyMDAwMFoXDTM3MTIzMTAxMDAwMFowOTEL
68
+ MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv
69
+ b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj
70
+ ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM
71
+ 9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw
72
+ IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6
73
+ VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L
74
+ 93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm
75
+ jgSubJrIqg0CAwEAAaOCATEwggEtMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/
76
+ BAQDAgGGMB0GA1UdDgQWBBSEGMyFNOy8DJSULghZnMeyEE4KCDAfBgNVHSMEGDAW
77
+ gBScXwDfqgHXMCs4iKK4bUqc8hGRgzB4BggrBgEFBQcBAQRsMGowLgYIKwYBBQUH
78
+ MAGGImh0dHA6Ly9vY3NwLnJvb3RnMi5hbWF6b250cnVzdC5jb20wOAYIKwYBBQUH
79
+ MAKGLGh0dHA6Ly9jcnQucm9vdGcyLmFtYXpvbnRydXN0LmNvbS9yb290ZzIuY2Vy
80
+ MD0GA1UdHwQ2MDQwMqAwoC6GLGh0dHA6Ly9jcmwucm9vdGcyLmFtYXpvbnRydXN0
81
+ LmNvbS9yb290ZzIuY3JsMBEGA1UdIAQKMAgwBgYEVR0gADANBgkqhkiG9w0BAQsF
82
+ AAOCAQEAYjdCXLwQtT6LLOkMm2xF4gcAevnFWAu5CIw+7bMlPLVvUOTNNWqnkzSW
83
+ MiGpSESrnO09tKpzbeR/FoCJbM8oAxiDR3mjEH4wW6w7sGDgd9QIpuEdfF7Au/ma
84
+ eyKdpwAJfqxGF4PcnCZXmTA5YpaP7dreqsXMGz7KQ2hsVxa81Q4gLv7/wmpdLqBK
85
+ bRRYh5TmOTFffHPLkIhqhBGWJ6bt2YFGpn6jcgAKUj6DiAdjd4lpFw85hdKrCEVN
86
+ 0FE6/V1dN2RMfjCyVSRCnTawXZwXgWHxyvkQAiSr6w10kY17RSlQOYiypok1JR4U
87
+ akcjMS9cmvqtmg5iUaQqqcT5NJ0hGA==
88
+ -----END CERTIFICATE-----