|
1 | 1 | import { readFile } from 'fs/promises'; |
2 | 2 | import http from 'http'; |
3 | 3 | import https from 'https'; |
| 4 | +import * as jks from 'jks-js'; |
4 | 5 | import { createLogger, last } from '@sap-cloud-sdk/util'; |
5 | 6 | /* Careful the proxy imports cause circular dependencies if imported from scp directly */ |
6 | 7 | // eslint-disable-next-line import/no-internal-modules |
@@ -132,6 +133,37 @@ function getKeyStoreOptions(destination: Destination): |
132 | 133 |
|
133 | 134 | const certBuffer = Buffer.from(certificate.content, 'base64'); |
134 | 135 |
|
| 136 | + if ( |
| 137 | + getFormat(certificate) === 'jks' || |
| 138 | + getFormat(certificate) === 'keystore' |
| 139 | + ) { |
| 140 | + const pemKeystore = jks.toPem( |
| 141 | + certBuffer, |
| 142 | + destination.keyStorePassword || '' |
| 143 | + ); |
| 144 | + const aliases = Object.keys(pemKeystore); |
| 145 | + if (aliases.length === 0) { |
| 146 | + throw Error('No entries found in JKS keystore'); |
| 147 | + } |
| 148 | + const alias = aliases[0]; |
| 149 | + |
| 150 | + if (aliases.length > 1) { |
| 151 | + logger.debug( |
| 152 | + `JKS keystore contains ${aliases.length} aliases. ` + |
| 153 | + 'Using the first one. ' + |
| 154 | + 'If this is not the correct certificate, please use a JKS file with only one entry.' |
| 155 | + ); |
| 156 | + } |
| 157 | + |
| 158 | + const entry = pemKeystore[alias]; |
| 159 | + if (!entry.cert || !entry.key) { |
| 160 | + throw Error('Invalid JKS entry: missing cert or key'); |
| 161 | + } |
| 162 | + return { |
| 163 | + cert: Buffer.from(entry.cert, 'utf8'), |
| 164 | + key: Buffer.from(entry.key, 'utf8') |
| 165 | + }; |
| 166 | + } |
135 | 167 | // if the format is pem, the key and certificate needs to be passed separately |
136 | 168 | // it could be required to separate the string into two parts, but this seems to work as well |
137 | 169 | if (getFormat(certificate) === 'pem') { |
@@ -207,7 +239,7 @@ function mtlsIsEnabled(destination: Destination) { |
207 | 239 | /* |
208 | 240 | The node client supports only these store formats https://nodejs.org/api/tls.html#tlscreatesecurecontextoptions. |
209 | 241 | */ |
210 | | -const supportedCertificateFormats = ['p12', 'pfx', 'pem']; |
| 242 | +const supportedCertificateFormats = ['p12', 'pfx', 'pem', 'jks', 'keystore']; |
211 | 243 |
|
212 | 244 | function isSupportedFormat(format: string | undefined): boolean { |
213 | 245 | return !!format && supportedCertificateFormats.includes(format); |
@@ -235,15 +267,7 @@ function validateFormat(certificate: DestinationCertificate) { |
235 | 267 | const format = getFormat(certificate); |
236 | 268 | if (!isSupportedFormat(format)) { |
237 | 269 | throw Error( |
238 | | - `The format of the provided certificate '${ |
239 | | - certificate.name |
240 | | - }' is not supported. Supported formats are: ${supportedCertificateFormats.join( |
241 | | - ', ' |
242 | | - )}. ${ |
243 | | - format && ['jks', 'keystore'].includes(format) |
244 | | - ? "You can convert Java Keystores (.jks, .keystore) into PKCS#12 keystores using the JVM's keytool CLI: keytool -importkeystore -srckeystore your-keystore.jks -destkeystore your-keystore.p12 -deststoretype pkcs12" |
245 | | - : '' |
246 | | - }` |
| 270 | + `The format of the provided certificate '${certificate.name}' is not supported. Supported formats are: ${supportedCertificateFormats.join(', ')}.` |
247 | 271 | ); |
248 | 272 | } |
249 | 273 | } |
|
0 commit comments