Skip to content

Commit e555a5e

Browse files
committed
feat: use as ClientCertificateas object property
1 parent 19a8eb8 commit e555a5e

File tree

10 files changed

+104
-40
lines changed

10 files changed

+104
-40
lines changed

packages/ui5-middleware-onelogin/README.md

+19-2
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,36 @@ npm install ui5-middleware-onelogin --save-dev
2727

2828
## Configuration options (in `$yourapp/ui5.yaml`)
2929

30-
Currently you can define the properties in the configuration (see below) or the following environment variables are used.
30+
You can define the properties either in the configuration (YAML file) or using environment variables. The order of precedence is:
31+
32+
1. YAML file configuration
33+
2. Environment variables
34+
3. Default configuration
35+
36+
**Important:** When configuring `ClientCertificate`, you must define all its properties either in the YAML file or in environment variables. Mixing definitions between YAML and environment variables for `ClientCertificate` is not supported.
37+
38+
Currently, you can define the following properties:
3139

3240
- path: `string` either the url or the hostname and port of the SAP system
3341
- subdirectory`(optional)`: `string` the subdirectory that is appended to the path, defaults to the fiori launchpad at /sap/bc/ui2/flp
3442
- username`(optional)`: `string` Username to be used to login to the launchpad
35-
- password`(optional)`: `string`Password used to login
43+
- password`(optional)`: `string` Password used to login
3644
- useCertificate`(optional)`: `boolean` use a certificate to login instead of username and password
3745
- debug`(optional)`: `boolean` true will open up the playwright browser so you can see what's going on
3846

3947
**NB1:** If you choose to use the certificate login then check the property AutoSelectCertificateForUrls in chrome://policy if it holds the url pattern for your system. [Playwright](https://github.com/microsoft/playwright/issues/1799) has an issue to handle the certificate prompt. Another workaround is to set debug and useCertificate to true in the configuration and press ok when the prompt opens
4048

4149
**NB2:** If your system does not host a fiori launchpad, you will have to adjust the subdirectory to point to a different login protected page. In the case of a MII java stack that hosts an OData service, try setting subdirectory to XMII/PropertyAccessServlet?Mode=List
4250

51+
- ClientCertificate`(optional)`: `object` Configuration for client certificate authentication
52+
- origin: `string` Exact origin that the certificate is valid for. Origin includes https protocol, a hostname and optionally a port.
53+
- certPath: `string` Path to the file with the certificate in PEM format.
54+
- keyPath: `string` Path to the file with the private key in PEM format.
55+
- pfxPath: `string` Path to the PFX or PKCS12 encoded private key and certificate chain.
56+
- passphrase: `string` Passphrase for the private key (PEM or PFX).
57+
58+
You can set the following environment variables in your .env file (remember to add it to your .gitignore):
59+
4360
You can either add the following properties to your .env file, remember to add that to your .gitignore
4461

4562
- UI5_MIDDLEWARE_ONELOGIN_LOGIN_URL or UI5_MIDDLEWARE_SIMPLE_PROXY_BASEURI

packages/ui5-middleware-onelogin/lib/cookieGetter.js

+18-11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/ui5-middleware-onelogin/lib/cookieGetter.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/ui5-middleware-onelogin/lib/index.js

+12-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/ui5-middleware-onelogin/lib/index.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
UI5_MIDDLEWARE_ONELOGIN_LOGIN_URL=https://example.com/login
2+
UI5_MIDDLEWARE_ONELOGIN_USE_CERTIFICATE=true
3+
UI5_MIDDLEWARE_ONELOGIN_CLIENT_CERTIFICATES=[{"origin": "https://accounts.sap.com","pfxPath": "sap.pfx","passphrase": "XXX"}]
4+
UI5_MIDDLEWARE_ONELOGIN_DEBUG=true

packages/ui5-middleware-onelogin/sample/certificate/ui5.yaml

+9-3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ server:
2222
path: https://emea.cockpit.btp.cloud.sap
2323
subdirectory: cockpit#/
2424
useCertificate: true
25-
clientCertificatesOrigin: "https://accounts.sap.com"
26-
clientCertificatesPfxPath: "sap.pfx"
27-
# clientCertificatesPfxPpassphrase: used from environment variable
25+
# clientCertificates:
26+
# - origin: "https://accounts.sap.com"
27+
# #certPath: "path/to/cert.pem"
28+
# # cert: Buffer value (not applicable in YAML)
29+
# #keyPath: "path/to/key.pem"
30+
# # key: Buffer value (not applicable in YAML)
31+
# pfxPath: "sap.pfx"
32+
# # pfx: Buffer value (not applicable in YAML)
33+
# #passphrase: "your_passphrase_here"

packages/ui5-middleware-onelogin/src/cookieGetter.ts

+17-13
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,7 @@ export default class CookieGetter {
8181
username: process.env.UI5_MIDDLEWARE_ONELOGIN_USERNAME,
8282
password: process.env.UI5_MIDDLEWARE_ONELOGIN_PASSWORD,
8383
useCertificate: process.env.UI5_MIDDLEWARE_ONELOGIN_USE_CERTIFICATE === "true",
84-
clientCertificatesOrigin: process.env.UI5_MIDDLEWARE_ONELOGIN_CLIENT_CERTIFICATES_ORIGIN,
85-
clientCertificatesPfxPath: process.env.UI5_MIDDLEWARE_ONELOGIN_CLIENT_CERTIFICATES_PFX_PATH,
86-
clientCertificatesPfxPpassphrase: process.env.UI5_MIDDLEWARE_ONELOGIN_CLIENT_CERTIFICATES_PFX_PASSPHRASE,
84+
clientCertificates: this.parseJSON(process.env.UI5_MIDDLEWARE_ONELOGIN_CLIENT_CERTIFICATES),
8785
debug: process.env.UI5_MIDDLEWARE_ONELOGIN_DEBUG === "true",
8886
query: this.parseJSON(process.env.UI5_MIDDLEWARE_ONELOGIN_QUERY),
8987
},
@@ -92,6 +90,12 @@ export default class CookieGetter {
9290
const effectiveOptions = Object.assign({}, options);
9391
effectiveOptions.configuration = Object.assign({}, defaultOptions.configuration, envOptions.configuration, options.configuration);
9492

93+
// Check if clientCertificates should be used: useCertificate is true and clientCertificates is defined or clientCertificates contains any certificate
94+
const useClientCertificates =
95+
effectiveOptions.configuration.useCertificate ||
96+
(effectiveOptions.configuration.clientCertificates &&
97+
effectiveOptions.configuration.clientCertificates.some((cert) => cert.certPath || cert.cert || cert.keyPath || cert.key || cert.pfxPath || cert.pfx));
98+
9599
if (effectiveOptions.configuration.debug) {
96100
log.info("Default options:");
97101
log.info(defaultOptions);
@@ -101,6 +105,7 @@ export default class CookieGetter {
101105
log.info(options);
102106
log.info("Effective options:");
103107
log.info(effectiveOptions);
108+
log.info(`Using client certificates: ${useClientCertificates}`);
104109
}
105110

106111
const attr: Attributes = {
@@ -109,7 +114,7 @@ export default class CookieGetter {
109114
password: effectiveOptions.configuration.password!,
110115
};
111116

112-
if ((!attr.username || !attr.password) && !effectiveOptions.configuration.useCertificate) {
117+
if ((!attr.username || !attr.password) && !useClientCertificates) {
113118
log.warn("No credentials provided. Please answer the following prompts");
114119
if (!attr.username) {
115120
attr.username = await prompt("Username: ");
@@ -141,20 +146,19 @@ export default class CookieGetter {
141146
const browser = await chromium.launch(playwrightOpt);
142147
const contextOptions: any = { ignoreHTTPSErrors: true };
143148

144-
if (effectiveOptions.configuration.useCertificate) {
145-
contextOptions.clientCertificates = [
146-
{
147-
origin: effectiveOptions.configuration.clientCertificatesOrigin,
148-
pfxPath: effectiveOptions.configuration.clientCertificatesPfxPath,
149-
passphrase: effectiveOptions.configuration.clientCertificatesPfxPpassphrase,
150-
},
151-
];
149+
if (useClientCertificates && effectiveOptions.configuration.clientCertificates) {
150+
contextOptions.clientCertificates = effectiveOptions.configuration.clientCertificates;
151+
}
152+
153+
if (effectiveOptions.configuration.debug) {
154+
log.info("Client certificates configuration:");
155+
log.info(contextOptions.clientCertificates);
152156
}
153157

154158
const context = await browser.newContext(contextOptions);
155159

156160
const page = await context.newPage();
157-
if (!effectiveOptions.configuration.useCertificate) {
161+
if (!useClientCertificates) {
158162
await page.goto(attr.url, { waitUntil: "domcontentloaded" });
159163

160164
const elem = await this.getUserInput(page);

packages/ui5-middleware-onelogin/src/index.ts

+13-3
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,25 @@ var firstTime: boolean = true;
1515
// key: string
1616
// }
1717

18+
/**
19+
* @typedef {Object} ClientCertificate
20+
* @property {string} origin - Exact origin that the certificate is valid for. Origin includes https protocol, a hostname and optionally a port.
21+
* @property {string} [certPath] - Path to the file with the certificate in PEM format.
22+
* @property {Buffer} [cert] - Direct value of the certificate in PEM format.
23+
* @property {string} [keyPath] - Path to the file with the private key in PEM format.
24+
* @property {Buffer} [key] - Direct value of the private key in PEM format.
25+
* @property {string} [pfxPath] - Path to the PFX or PKCS12 encoded private key and certificate chain.
26+
* @property {Buffer} [pfx] - Direct value of the PFX or PKCS12 encoded private key and certificate chain.
27+
* @property {string} [passphrase] - Passphrase for the private key (PEM or PFX).
28+
*/
29+
1830
/**
1931
* @typedef {Object} [configuration] configuration
2032
* @property {string} path - The path to use => env:UI5_MIDDLEWARE_ONELOGIN_LOGIN_URL
2133
* @property {string} [username] the username => env:UI5_MIDDLEWARE_ONELOGIN_USERNAME
2234
* @property {string|yo<password>} [password] the password => env:UI5_MIDDLEWARE_ONELOGIN_PASSWORD
2335
* @property {boolean|yo<confirm|false>} [useCertificate] use certificate login instead of username/password
24-
* @property {string} [clientCertificatesOrigin] the origin of the client certificates => env:UI5_MIDDLEWARE_ONELOGIN_CLIENT_CERTIFICATES_ORIGIN
25-
* @property {string} [clientCertificatesPfxPath] the path to the client certificates => env:UI5_MIDDLEWARE_ONELOGIN_CLIENT_CERTIFICATES_PFX_PATH
26-
* @property {string} [clientCertificatesPfxPpassphrase] the passphrase to the client certificates => env:UI5_MIDDLEWARE_ONELOGIN_CLIENT_CERTIFICATES_PFX_PASSPHRASE
36+
* @property {ClientCertificate[]} [clientCertificates] Array of client certificate configurations
2737
* @property {boolean|yo<confirm|false>} [debug] see output
2838
*/
2939
/**

packages/ui5-middleware-onelogin/src/types.ts

+10-3
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,15 @@ export interface Options {
77
useCertificate: boolean;
88
debug?: boolean;
99
query?: unknown;
10-
clientCertificatesOrigin?: string;
11-
clientCertificatesPfxPath?: string;
12-
clientCertificatesPfxPpassphrase?: string;
10+
clientCertificates?: Array<{
11+
origin: string;
12+
certPath?: string;
13+
cert?: Buffer;
14+
keyPath?: string;
15+
key?: Buffer;
16+
pfxPath?: string;
17+
pfx?: Buffer;
18+
passphrase?: string;
19+
}>;
1320
};
1421
}

0 commit comments

Comments
 (0)