Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Added functions to configure ca certificate to the global-agent #49

Open
wants to merge 54 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
5df9ceb
feat: added option to pass ca certificates while creating global-agen…
vipendra-mehra Aug 2, 2021
7f22bb4
Update README.md
vipendra-mehra Aug 2, 2021
07c3a6c
Update README.md
vipendra-mehra Aug 2, 2021
a3c70d2
Update Agent.ts
vipendra-mehra Aug 2, 2021
429f726
Fix: Updated ca type to be Array<string>
vipendra-mehra Aug 2, 2021
899a286
fix: updated ca type to string[]
vipendra-mehra Aug 2, 2021
c7a6d59
fix: updated default value of ca to be empty array
vipendra-mehra Aug 2, 2021
0b1714e
fix: replaced configuration with configurationInput
vipendra-mehra Aug 2, 2021
a69e748
fix: suppresed process.env eslint error
vipendra-mehra Aug 2, 2021
e7e1744
Update createGlobalProxyAgent.ts
vipendra-mehra Aug 2, 2021
75d3a3c
Update createGlobalProxyAgent.ts
vipendra-mehra Aug 2, 2021
44a445d
Update createGlobalProxyAgent.ts
vipendra-mehra Aug 2, 2021
2e86447
fix: Updated test cases and rearranged them
Aug 3, 2021
a74bce9
fix: Updated test
Aug 3, 2021
182747d
fix: suppressed type error
Aug 3, 2021
f2353ba
fix: updated test
Aug 3, 2021
6728712
fix: Updated test case
Aug 3, 2021
83df90e
fix: updated test
Aug 3, 2021
291e47d
fix: updated test
Aug 3, 2021
69bca77
fix: updated test
Aug 3, 2021
0661973
fix: fixed eslint error
Aug 3, 2021
e11dc9c
Merge branch 'master' into master
vipendra-mehra Aug 18, 2021
71f0759
Update Agent.ts
vipendra-mehra Aug 18, 2021
723905b
Update Agent.ts
vipendra-mehra Aug 18, 2021
de223b5
Update Agent.ts
vipendra-mehra Aug 18, 2021
9bf9bd0
Update Agent.ts
vipendra-mehra Aug 18, 2021
db42f5e
Update Agent.ts
vipendra-mehra Aug 18, 2021
c7e0462
Update Agent.ts
vipendra-mehra Aug 18, 2021
d646585
Update Agent.ts
vipendra-mehra Aug 18, 2021
38c948c
Update Agent.ts
vipendra-mehra Aug 19, 2021
57e4d65
Update types.ts
vipendra-mehra Sep 1, 2021
a53aad7
Update createGlobalProxyAgent.ts
vipendra-mehra Sep 1, 2021
7e8dfb2
Update HttpProxyAgent.ts
vipendra-mehra Sep 1, 2021
a8d31ec
Update HttpsProxyAgent.ts
vipendra-mehra Sep 1, 2021
b2fb9fd
Update Agent.ts
vipendra-mehra Sep 1, 2021
932aa76
Update types.ts
vipendra-mehra Sep 1, 2021
bd9e8b5
Update createGlobalProxyAgent.ts
vipendra-mehra Sep 1, 2021
cf01fe9
Update Agent.ts
vipendra-mehra Sep 1, 2021
eef536f
Update createGlobalProxyAgent.ts
vipendra-mehra Sep 1, 2021
d2ecb0a
Update Agent.ts
vipendra-mehra Sep 1, 2021
2af917f
Update createGlobalProxyAgent.ts
vipendra-mehra Sep 1, 2021
709b139
Update Agent.ts
vipendra-mehra Sep 1, 2021
57b3b54
Update Agent.ts
vipendra-mehra Sep 1, 2021
4817fe4
Update Agent.ts
vipendra-mehra Sep 1, 2021
2bf62f0
Update README.md
vipendra-mehra Sep 1, 2021
877b313
Update createGlobalProxyAgent.ts
vipendra-mehra Sep 1, 2021
d749871
Update types.ts
vipendra-mehra Sep 1, 2021
ab22851
Update HttpsProxyAgent.ts
vipendra-mehra Sep 1, 2021
29e06f7
Update HttpProxyAgent.ts
vipendra-mehra Sep 1, 2021
b7d3108
Update Agent.ts
vipendra-mehra Sep 1, 2021
59a7c43
Update README.md
vipendra-mehra Sep 1, 2021
693210c
Update Agent.ts
vipendra-mehra Sep 1, 2021
1c70873
Update createGlobalProxyAgent.ts
vipendra-mehra Sep 1, 2021
dcf2ec1
Update README.md
vipendra-mehra Sep 1, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,11 +166,13 @@ Use [`roarr-cli`](https://github.com/gajus/roarr-cli) program to pretty-print th
* @property environmentVariableNamespace Defines namespace of `HTTP_PROXY`, `HTTPS_PROXY` and `NO_PROXY` environment variables. (Default: `GLOBAL_AGENT_`)
* @property forceGlobalAgent Forces to use `global-agent` HTTP(S) agent even when request was explicitly constructed with another agent. (Default: `true`)
* @property socketConnectionTimeout Destroys socket if connection is not established within the timeout. (Default: `60000`)
* @property ca Single CA certificate or an array of CA certificates that is trusted for secure connections to the registry.
*/
type ProxyAgentConfigurationInputType = {|
+environmentVariableNamespace?: string,
+forceGlobalAgent?: boolean,
+socketConnectionTimeout?: number,
+ca?: string[] | string,
|};

(configurationInput: ProxyAgentConfigurationInputType) => ProxyAgentConfigurationType;
Expand Down Expand Up @@ -200,6 +202,65 @@ type ProxyAgentConfigurationInputType = {|
|`HTTPS_PROXY`|Yes|Sets a distinct proxy to use for HTTPS requests.|
|`NO_PROXY`|Yes|Specifies a pattern of URLs that should be excluded from proxying. See [Exclude URLs](#exclude-urls).|

## Certificate Authority (CA)

### `addCACertificates`
This method can be accessed using https to add CA certificates to the global-agent.

Uses:
```js
if (typeof https.globalAgent.addCACertificates === 'function') {
//certificate - an array of ca certificates to be added to the global-agent
https.globalAgent.addCACertificates(certificate);
}
```

Method Definition:
```js
/**
* This method can be used to append new ca certificates to existing ca certificates
* @param {string[] | string} ca a ca certificate or an array of ca certificates
*/
public addCACertificates (ca: string[] | string) {
if (!ca) {
log.error('Invalid input ca certificate');
} else if (this.ca) {
if (typeof ca === typeof this.ca) {
// concat valid ca certificates with the existing certificates,
if (typeof this.ca === 'string') {
this.ca = this.ca.concat(ca as string);
} else {
this.ca = this.ca.concat(ca as string[]);
}
} else {
log.error('Input ca certificate type mismatched with existing ca certificate type');
}
} else {
this.ca = ca;
}
}
```

### `clearCACertificates`
This method can be accessed using https to clear existing CA certificates from global-agent.

Uses:
```js
if (typeof https.globalAgent.clearCACertificates === 'function') {
https.globalAgent.clearCACertificates();
}
```
Method Definition:
```js
/**
* This method clears existing CA Certificates.
* It sets ca to undefined
*/
public clearCACertificates () {
this.ca = undefined;
}
```

## Supported libraries

`global-agent` works with all libraries that internally use [`http.request`](https://nodejs.org/api/http.html#http_http_request_options_callback).
Expand Down
68 changes: 55 additions & 13 deletions src/classes/Agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,71 @@ abstract class Agent {

public socketConnectionTimeout: number;

public ca: string[] | string | undefined;

public constructor (
isProxyConfigured: IsProxyConfiguredMethodType,
mustUrlUseProxy: MustUrlUseProxyMethodType,
getUrlProxy: GetUrlProxyMethodType,
fallbackAgent: AgentType,
socketConnectionTimeout: number,
ca: string[] | string | undefined,
) {
this.fallbackAgent = fallbackAgent;
this.isProxyConfigured = isProxyConfigured;
this.mustUrlUseProxy = mustUrlUseProxy;
this.getUrlProxy = getUrlProxy;
this.socketConnectionTimeout = socketConnectionTimeout;
this.ca = ca;
}

/**
* This method can be used to append new ca certificates to existing ca certificates
* @param {string[] | string} ca a ca certificate or an array of ca certificates
*/
public addCACertificates (ca: string[] | string) {
if (!ca) {
log.error('Invalid input ca certificate');
} else if (this.ca) {
if (typeof ca === typeof this.ca) {
// concat valid ca certificates with the existing certificates,
if (typeof this.ca === 'string') {
this.ca = this.ca.concat(ca as string);
} else {
this.ca = this.ca.concat(ca as string[]);
}
} else {
log.error('Input ca certificate type mismatched with existing ca certificate type');
}
} else {
this.ca = ca;
}
}

/**
* This method clears existing CA Certificates.
* It sets ca to undefined
*/
public clearCACertificates () {
this.ca = undefined;
}

/**
* Evaluate value for tls reject unauthorized variable
*/
public getRejectUnauthorized () {
// eslint-disable-next-line node/no-process-env
const rejectUnauthorized = process.env.NODE_TLS_REJECT_UNAUTHORIZED;
let returnValue = true;
if (typeof rejectUnauthorized === 'boolean') {
returnValue = rejectUnauthorized;
} else if (typeof rejectUnauthorized === 'number') {
returnValue = rejectUnauthorized === 1;
} else if (typeof rejectUnauthorized === 'string') {
returnValue = ['true', 't', 'yes', 'y', 'on', '1'].includes(rejectUnauthorized.trim().toLowerCase());
}

return returnValue;
}

public abstract createConnection (configuration: ConnectionConfigurationType, callback: ConnectionCallbackType): void;
Expand Down Expand Up @@ -152,7 +205,7 @@ abstract class Agent {
// > key, passphrase, pfx, rejectUnauthorized, secureOptions, secureProtocol, servername, sessionIdContext.
if (configuration.secureEndpoint) {
connectionConfiguration.tls = {
ca: configuration.ca,
ca: configuration.ca ?? this.ca,
cert: configuration.cert,
ciphers: configuration.ciphers,
clientCertEngine: configuration.clientCertEngine,
Expand All @@ -163,23 +216,12 @@ abstract class Agent {
key: configuration.key,
passphrase: configuration.passphrase,
pfx: configuration.pfx,
rejectUnauthorized: configuration.rejectUnauthorized ?? true,
rejectUnauthorized: configuration.rejectUnauthorized ?? this.getRejectUnauthorized(),
secureOptions: configuration.secureOptions,
secureProtocol: configuration.secureProtocol,
servername: configuration.servername ?? connectionConfiguration.host,
sessionIdContext: configuration.sessionIdContext,
};

// This is not ideal because there is no way to override this setting using `tls` configuration if `NODE_TLS_REJECT_UNAUTHORIZED=0`.
// However, popular HTTP clients (such as https://github.com/sindresorhus/got) come with pre-configured value for `rejectUnauthorized`,
// which makes it impossible to override that value globally and respect `rejectUnauthorized` for specific requests only.
if (
// eslint-disable-next-line node/no-process-env
process.env.NODE_TLS_REJECT_UNAUTHORIZED === '0'
) {
// @ts-expect-error seems like we are using wrong guard for this change that does not align with secureEndpoint
connectionConfiguration.tls.rejectUnauthorized = false;
}
}

this.createConnection(connectionConfiguration, (error, socket) => {
Expand Down
2 changes: 2 additions & 0 deletions src/classes/HttpProxyAgent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@ class HttpProxyAgent extends Agent {
getUrlProxy: GetUrlProxyMethodType,
fallbackAgent: AgentType,
socketConnectionTimeout: number,
ca: string[] | string | undefined,
) {
super(
isProxyConfigured,
mustUrlUseProxy,
getUrlProxy,
fallbackAgent,
socketConnectionTimeout,
ca,
);

this.protocol = 'http:';
Expand Down
2 changes: 2 additions & 0 deletions src/classes/HttpsProxyAgent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@ class HttpsProxyAgent extends Agent {
getUrlProxy: GetUrlProxyMethodType,
fallbackAgent: AgentType,
socketConnectionTimeout: number,
ca: string[] | string | undefined,
) {
super(
isProxyConfigured,
mustUrlUseProxy,
getUrlProxy,
fallbackAgent,
socketConnectionTimeout,
ca,
);

this.protocol = 'https:';
Expand Down
2 changes: 2 additions & 0 deletions src/factories/createGlobalProxyAgent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ export default (configurationInput: ProxyAgentConfigurationInputType = defaultCo
getUrlProxy(getHttpProxy),
http.globalAgent,
configuration.socketConnectionTimeout,
configuration.ca,
);
}
};
Expand All @@ -136,6 +137,7 @@ export default (configurationInput: ProxyAgentConfigurationInputType = defaultCo
getUrlProxy(getHttpsProxy),
https.globalAgent,
configuration.socketConnectionTimeout,
configuration.ca,
);
}
};
Expand Down
4 changes: 3 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export type ProxyConfigurationType = {
};

export type TlsConfigurationType = {
ca?: string,
ca?: string[] | string,
cert?: string,
ciphers?: string,
clientCertEngine?: string,
Expand Down Expand Up @@ -55,10 +55,12 @@ export type ProxyAgentConfigurationInputType = {
environmentVariableNamespace?: string,
forceGlobalAgent?: boolean,
socketConnectionTimeout?: number,
ca?: string[] | string,
};

export type ProxyAgentConfigurationType = {
environmentVariableNamespace: string,
forceGlobalAgent: boolean,
socketConnectionTimeout: number,
ca?: string[] | string,
};
Loading