Skip to content

Commit

Permalink
Add pfx HTTPS option (#1364)
Browse files Browse the repository at this point in the history
Co-authored-by: Sindre Sorhus <sindresorhus@gmail.com>
Co-authored-by: Giovanni Minotti <giovanni@minotti.net>
  • Loading branch information
3 people committed Sep 13, 2020
1 parent 0e0eefd commit c33df7f
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 5 deletions.
58 changes: 57 additions & 1 deletion readme.md
Expand Up @@ -1022,7 +1022,24 @@ Type: `string`

The passphrase to decrypt the `options.https.key` (if different keys have different passphrases refer to `options.https.key` documentation).

##### Examples for `https.key`, `https.certificate` and `https.passphrase`
##### https.pfx

Type: `string | Buffer | Array<string | Buffer | object>`

[PFX or PKCS12](https://en.wikipedia.org/wiki/PKCS_12) encoded private key and certificate chain. Using `options.https.pfx` is an alternative to providing `options.https.key` and `options.https.certificate` individually. A PFX is usually encrypted, and if it is, `options.https.passphrase` will be used to decrypt it.

Multiple PFX's can be be provided as an array of unencrypted buffers or an array of objects like:

```ts
{
buffer: string | Buffer,
passphrase?: string
}
```

This object form can only occur in an array. If the provided buffers are encrypted, `object.passphrase` can be used to decrypt them. If `object.passphrase` is not provided, `options.https.passphrase` will be used for decryption.

##### Examples for `https.key`, `https.certificate`, `https.passphrase`, and `https.pfx`

```js
// Single key with certificate
Expand Down Expand Up @@ -1069,6 +1086,45 @@ got('https://example.com', {
]
}
});

// Single encrypted PFX with passphrase
got('https://example.com', {
https: {
pfx: fs.readFileSync('./fake.pfx'),
passphrase: 'passphrase'
}
});

// Multiple encrypted PFX's with different passphrases
got('https://example.com', {
https: {
pfx: [
{
buffer: fs.readFileSync('./key1.pfx'),
passphrase: 'passphrase1'
},
{
buffer: fs.readFileSync('./key2.pfx'),
passphrase: 'passphrase2'
}
]
}
});

// Multiple encrypted PFX's with single passphrase
got('https://example.com', {
https: {
passphrase: 'passphrase',
pfx: [
{
buffer: fs.readFileSync('./key1.pfx')
},
{
buffer: fs.readFileSync('./key2.pfx')
}
]
}
});
```

##### https.rejectUnauthorized
Expand Down
14 changes: 14 additions & 0 deletions source/core/index.ts
Expand Up @@ -858,6 +858,7 @@ export interface HTTPSOptions {
The passphrase to decrypt the `options.https.key` (if different keys have different passphrases refer to `options.https.key` documentation).
*/
passphrase?: SecureContextOptions['passphrase'];
pfx?: SecureContextOptions['pfx'];
}

interface NormalizedPlainOptions extends PlainOptions {
Expand Down Expand Up @@ -1539,6 +1540,7 @@ export default class Request extends Duplex implements RequestEvents<Request> {
assert.any([is.string, is.object, is.array, is.undefined], options.https.key);
assert.any([is.string, is.object, is.array, is.undefined], options.https.certificate);
assert.any([is.string, is.undefined], options.https.passphrase);
assert.any([is.string, is.buffer, is.array, is.undefined], options.https.pfx);
}

assert.any([is.object, is.undefined], options.cacheOptions);
Expand Down Expand Up @@ -1833,6 +1835,10 @@ export default class Request extends Duplex implements RequestEvents<Request> {
deprecationWarning('"options.passphrase" was never documented, please use "options.https.passphrase"');
}

if ('pfx' in options) {
deprecationWarning('"options.pfx" was never documented, please use "options.https.pfx"');
}

// Other options
if ('followRedirects' in options) {
throw new TypeError('The `followRedirects` option does not exist. Use `followRedirect` instead.');
Expand Down Expand Up @@ -2390,6 +2396,10 @@ export default class Request extends Duplex implements RequestEvents<Request> {
if (options.https.passphrase) {
requestOptions.passphrase = options.https.passphrase;
}

if (options.https.pfx) {
requestOptions.pfx = options.https.pfx;
}
}

try {
Expand Down Expand Up @@ -2430,6 +2440,10 @@ export default class Request extends Duplex implements RequestEvents<Request> {
if (options.https.passphrase) {
delete requestOptions.passphrase;
}

if (options.https.pfx) {
delete requestOptions.pfx;
}
}

if (isClientRequest(requestOrResponse)) {
Expand Down
9 changes: 5 additions & 4 deletions test/https.ts
Expand Up @@ -454,11 +454,12 @@ test('client certificate PFX', withHttpsServer(), async (t, server, got) => {

const {pkcs12} = await createPkcs12(clientKey, clientCert, 'randomPassword');

// Change me on PR #1364
const response: any = await got({
pfx: pkcs12,
passphrase: 'randomPassword'
} as any).json();
https: {
pfx: pkcs12,
passphrase: 'randomPassword'
}
}).json();

t.true(response.authorized);
t.is(response.peerCertificate.subject.CN, 'client');
Expand Down

0 comments on commit c33df7f

Please sign in to comment.