Skip to content

Commit

Permalink
Easier certificate settings (#638)
Browse files Browse the repository at this point in the history
* Prepare for 0.4.0 release

* Fix link

* PR issues

* Easier certificate settings

* asdf
  • Loading branch information
StephenWeatherford authored Nov 20, 2018
1 parent f2eb4e3 commit e19f88a
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 34 deletions.
22 changes: 17 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,23 @@ This build includes preview support for connecting to private registries (such a

## Self-signed and corporate certificates

If you are using a self-signed or corporate CA certificate (e.g. for a private Docker registry) and have the certificate authority's certificate registered in the Windows or Mac certificate store, you will need to set the `docker.useCertificateStore` setting to true in order for that certificate to be trusted by the extension. If you're on Linux, you will need to specify your certificate folder(s) and/or file(s) using the `docker.certificatePaths` setting. The exact folder to use will depend on the Linux distribution, but we suggest trying `["/etc/ssl/certs/ca-certificates", "/etc/openssl/certs", "/etc/pki/tls/certs", "/usr/local/share/certs"]` first.

Note that currently if you specify either of these settings, Node.js's internal certificate list will be ignored.

We will likely set default values for these in the future.
If you are using a self-signed or corporate CA certificate (e.g. for a private Docker registry) and have the certificate authority's certificate registered in the Windows or Mac certificate store, you will want to use the following setting:
```json
"docker.importCertificates": true
```
This causes the extension automatically pick up system-wide certificates. Leaving it at the default `false` means the default Node.js list of trusted certificates will be used. You can fine-tune the values this way:
```json
"docker.importCertificates":{
"useCertificateStore": true,
"certificatePaths": [
"/etc/ssl/certs/ca-certificates",
"/etc/openssl/certs",
"/etc/pki/tls/certs",
"/usr/local/share/certs"
]
}
```
The exact folder to use for certificatePaths on Linux will depend on the distribution.

## Debugging .NET Core (Preview)

Expand Down
2 changes: 1 addition & 1 deletion dockerExtension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ async function setRequestDefaults(): Promise<void> {
let error = <{ cause?: { code?: string } }>err;

if (error && error.cause && error.cause.code === 'UNABLE_TO_VERIFY_LEAF_SIGNATURE') {
err = wrapError(err, `There was a problem verifying a certificate. This could be caused by a self-signed or corporate certificate. You may need to set the 'docker.useCertificateStore' or 'docker.certificatePaths' setting.`)
err = wrapError(err, `There was a problem verifying a certificate. This could be caused by a self-signed or corporate certificate. You may need to set the 'docker.importCertificates' setting to true.`)
}

throw err;
Expand Down
44 changes: 30 additions & 14 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -471,21 +471,37 @@
"default": "",
"description": "Host to connect to (same as setting the DOCKER_HOST environment variable)"
},
"docker.certificatePaths": {
"type": [
"array",
"null"
"docker.importCertificates": {
"oneOf": [
{
"type": "boolean"
},
{
"type": "object",
"properties": {
"useCertificateStore": {
"type": "boolean",
"default": true,
"description": "On Mac and Windows, indicates whether to automatically import certificates from the system certificate store. Ignored on Linux."
},
"certificatePaths": {
"type": "array",
"items": {
"type": "string"
},
"default": [
"/etc/ssl/certs/ca-certificates",
"/etc/openssl/certs",
"/etc/pki/tls/certs",
"/usr/local/share/certs"
],
"description": "Paths to files or folders containing certificates to import. For Linux, the correct path to pick up system-wide certificates will depend on the distribution."
}
}
}
],
"items": {
"type": "string"
},
"description": "Paths to files or folders containing certificates to import. For Linux, the correct path to pick up system-wide certificates will depend on the distribution. The list [\"/etc/ssl/certs/ca-certificates\", \"/etc/openssl/certs\", \"/etc/pki/tls/certs\", \"/usr/local/share/certs\"] may suffice for many.",
"default": null
},
"docker.useCertificateStore": {
"type": "boolean",
"description": "On Mac and Windows, indicates whether to automatically import certificates from the system certificate store. Ignored on Linux.",
"default": false
"default": false,
"description": "True causes the extension to attempt to find system-wide certificates, false indicates that the default Node.js trusted certificates list will be used. Use an object to get more fine-grained control."
},
"docker.languageserver.diagnostics.deprecatedMaintainer": {
"scope": "resource",
Expand Down
48 changes: 34 additions & 14 deletions utils/getTrustedCertificates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,29 +14,49 @@ import { isLinux, isMac, isWindows } from '../helpers/osVersion';

let _systemCertificates: (string | Buffer)[] | undefined;

type ImportCertificatesSetting = boolean | {
useCertificateStore: boolean,
certificatePaths: string[]
};

const defaultCertificatePaths: string[] = [
"/etc/ssl/certs/ca-certificates",
"/etc/openssl/certs",
"/etc/pki/tls/certs",
"/usr/local/share/certs"
];

export async function getTrustedCertificates(): Promise<(string | Buffer)[]> {
// tslint:disable-next-line:no-function-expression
return callWithTelemetryAndErrorHandling('docker.certificates', async function (this: IActionContext): Promise<(string | Buffer)[] | undefined> {
this.suppressTelemetry = true;

let useCertificateStore: boolean = !!vscode.workspace.getConfiguration('docker').get<boolean>('useCertificateStore');
this.properties.useCertStore = String(useCertificateStore);
let systemCerts: (string | Buffer)[] | undefined = useCertificateStore ? getCertificatesFromSystem() : undefined;

let certificatePaths: string[] = vscode.workspace.getConfiguration('docker').get<string[] | null>('certificatePaths');
let filesCerts: Buffer[] | undefined;
if (Array.isArray(certificatePaths)) {
this.properties.certPathsCount = String(certificatePaths.length);
filesCerts = await getCertificatesFromPaths(certificatePaths);
let importSetting = vscode.workspace.getConfiguration('docker').get<ImportCertificatesSetting>('importCertificates');
if (importSetting === false) {
// Use default Node.js behavior
this.properties.importCertificates = 'false';
return undefined;
}

if (systemCerts === undefined && filesCerts === undefined) {
// If neither setting is set, be sure to return undefined to get Node.js's default list of trusted certificates
return undefined;
let useCertificateStore: boolean;
let certificatePaths: string[];

if (importSetting === true) {
this.properties.importCertificates = 'true';
useCertificateStore = true;
certificatePaths = defaultCertificatePaths;
} else {
this.properties.importCertificates = 'custom';
useCertificateStore = !!importSetting.useCertificateStore;
certificatePaths = importSetting.certificatePaths || [];
}

systemCerts = systemCerts || [];
filesCerts = filesCerts || [];
this.properties.useCertStore = String(useCertificateStore);
let systemCerts: (string | Buffer)[] = useCertificateStore ? getCertificatesFromSystem() : [];

let filesCerts: Buffer[];
this.properties.certPathsCount = String(certificatePaths.length);
filesCerts = await getCertificatesFromPaths(certificatePaths);

this.properties.systemCertsCount = String(systemCerts.length);
this.properties.fileCertsCount = String(filesCerts.length);
Expand Down

0 comments on commit e19f88a

Please sign in to comment.