Skip to content

Commit

Permalink
NXDRIVE-1433: Handle custom SSL certificates
Browse files Browse the repository at this point in the history
Introduce the 'ca_bundle' option that must point
to a file or directory with certificates of
trusted CAs.
If set, the 'ssl-no-verify' option has no effect.
  • Loading branch information
Mickaël Schoentgen authored and BoboTiG committed Nov 22, 2018
1 parent 6d83fa8 commit abeeb11
Show file tree
Hide file tree
Showing 11 changed files with 68 additions and 26 deletions.
1 change: 1 addition & 0 deletions docs/changes/4.0.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
Release date: `2018-11-21`

Changes in command line arguments:

- Changed `consider-ssl-errors` with default as `True` to `ssl-no-verify` with default as `False`.

## Core
Expand Down
8 changes: 8 additions & 0 deletions docs/changes/4.0.2.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# 4.0.2

Release date: `2018-xx-xx`

Changes in command line arguments:

- Added `ca-bundle`.

## Core

- [NXDRIVE-1433](https://jira.nuxeo.com/browse/NXDRIVE-1433): Handle custom SSL certificates
49 changes: 33 additions & 16 deletions docs/configuration.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
# Configuration

Nuxeo Drive has different parameters that you can set up through:
- the REST API endpoint `/drive/configuration` served by the server (since [NXP-22946](https://jira.nuxeo.com/browse/NXP-22946) and Drive 3.0.0),
- a `$HOME/.nuxeo-drive/config.ini` file,
- a registry key inside `HKEY_CURRENT_USER\Software\Nuxeo\Drive` (since Drive 3.1.0, Windows only),
- the command line.

- The REST API endpoint `/drive/configuration` served by the server (since [NXP-22946](https://jira.nuxeo.com/browse/NXP-22946) and Drive 3.0.0).
- The command line.
- A registry key inside `HKEY_CURRENT_USER\Software\Nuxeo\Drive` (since Drive 3.1.0, Windows only).
- A `config.ini` file that can be located in different places:
- next to the Nuxeo Drive executable
- from the `$HOME/.nuxeo-drive` folder
- from the current working directory

Each of these ways overrides the previous one.

## Parameters

| Parameter | Default Value | Description
|---|---|---
| `beta-update-site-url` | https://community.nuxeo.com/static/drive-updates | Configure custom beta update website.
| `ssl-no-verify` | False | Define if SSL errors should be ignored.
| `beta-update-site-url` | `https://community.nuxeo.com/static/drive-updates` | Configure custom beta update website.
| `ca-bundle` | None | File or directory with certificates of trusted CAs. If set, `ssl-no-verify` has no effect. See the `requests` [documentation](http://docs.python-requests.org/en/master/user/advanced/#ssl-cert-verification) for more details.
| `debug` | False | Activate the debug window, and debug mode.
| `delay` | 30 | Define the delay before each remote check.
| `force-locale` | None | Force the reset to the language.
Expand All @@ -25,24 +30,36 @@ Each of these ways overrides the previous one.
| `ndrive-home` | `$HOME/.nuxeo-drive` | Define the personal folder.
| `nofscheck` | False | Disable the standard check for binding, to allow installation on network filesystem.
| `proxy-server` | None | Define the address of the proxy server (e.g. `http://proxy.example.com:3128`). This can also be set up by the user from the Settings window.
| `ssl-no-verify` | False | Define if SSL errors should be ignored. Highly unadvised to enable this option.
| `timeout` | 30 | Define the socket timeout.
| `update-check-delay` | 3600 | Define the auto-update check delay. 0 means disabled.
| `update-site-url` | https://community.nuxeo.com/static/drive-updates | Configure a custom update website. See Nuxeo Drive Update Site for more details.
| `update-site-url` | `https://community.nuxeo.com/static/drive-updates` | Configure a custom update website. See Nuxeo Drive Update Site for more details.

## Command Line Arguments

When used as a command line argument you need to prefix with the long argument modifier `--`, e.g.: `--log-level-file TRACE`.
When used as a command line argument you need to prefix with the long argument modifier `--`, e.g.: `--log-level-file=TRACE`.

## Configuration File

Instead of using command line arguments, you can create the `config.ini` file into the `$HOME/.nuxeo-drive` folder.
The file syntax is:
The format of the `config.ini` file is as following:

```ini
[DEFAULT]
env = custom

[DEFAULT]
env = custom
[no-updates]
; Unused section
update-check-delay = 0

[custom]
log-level-file = TRACE
debug = False
[custom]
ca_bundle = C:\certificates\terena-ssl.crt
debug = False
log-level-file = TRACE
ignored_suffixes =
.bak
.tmp
.XXX
```

You can add parameters inside the `[custom]` section.
The `env` option from the `[DEFAULT]` section defines in which section looking for options.
Here, options defined in the `[custom]` section will be taken into account.
9 changes: 6 additions & 3 deletions nxdrive/client/proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,11 +179,14 @@ def save_proxy(proxy: Proxy, dao: "EngineDAO", token: str = None) -> None:


def validate_proxy(proxy: Proxy, url: str) -> bool:
verify = Options.ca_bundle or not Options.ssl_no_verify
try:
with requests.get(
url, proxies=proxy.settings(url=url), verify=not Options.ssl_no_verify
):
with requests.get(url, proxies=proxy.settings(url=url), verify=verify):
return True
except OSError as exc:
# OSError: Could not find a suitable TLS CA certificate bundle, invalid path: ...
log.critical(f"{exc}. Ensure the 'ca_bundle' option is correct.")
return False
except:
log.exception("Invalid proxy.")
return False
Expand Down
2 changes: 1 addition & 1 deletion nxdrive/client/remote_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def __init__(
**kwargs: Any,
) -> None:
auth = TokenAuth(token) if token else (user_id, password)
kwargs["verify"] = not Options.ssl_no_verify
kwargs["verify"] = Options.ca_bundle or not Options.ssl_no_verify
self.kwargs = kwargs

super().__init__(
Expand Down
1 change: 1 addition & 0 deletions nxdrive/commandline.py
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,7 @@ def handle(self, argv: List[str]) -> int:
has_ssl_support = QSslSocket.supportsSsl()
log.info(f"SSL support: {has_ssl_support!r}")
if not has_ssl_support:
options.ca_bundle = None
options.ssl_no_verify = True

# Update default options
Expand Down
6 changes: 5 additions & 1 deletion nxdrive/gui/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -723,9 +723,13 @@ def _connect_startup_page(self, server_url: str) -> int:
headers=headers,
proxies=self._manager.proxy.settings(url=url),
timeout=timeout,
verify=not Options.ssl_no_verify,
verify=Options.ca_bundle or not Options.ssl_no_verify,
) as resp:
status = resp.status_code
except OSError as exc:
# OSError: Could not find a suitable TLS CA certificate bundle, invalid path: ...
log.critical(f"{exc}. Ensure the 'ca_bundle' option is correct.")
raise StartupPageConnectionError()
except:
log.exception(
f"Error while trying to connect to {APP_NAME}"
Expand Down
3 changes: 1 addition & 2 deletions nxdrive/gui/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -775,8 +775,7 @@ def show_release_notes(self, version: str) -> None:
version += " beta"

try:
# No need for the `verify=not Options.ssl_no_verify` here as GitHub will never use
# a bad certificate.
# No need for the `verify` kwarg here as GitHub will never use a bad certificate.
with requests.get(url) as resp:
data = resp.json()
except requests.HTTPError as exc:
Expand Down
1 change: 1 addition & 0 deletions nxdrive/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ def __get_home(*_) -> str:
"default",
),
"browser_startup_page": ("drive_browser_login.jsp", "default"),
"ca_bundle": (None, "default"),
"debug": (False, "default"),
"debug_pydev": (False, "default"),
"delay": (30, "default"),
Expand Down
4 changes: 2 additions & 2 deletions nxdrive/updater/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ def _download(self, version: str) -> str:
f"into {path!r}"
)
try:
# Note: I do not think we should pass the `verify=not Options.ssl_no_verify` kwarg here
# Note: I do not think we should pass the `verify` kwarg here
# because updates are critical and must be stored on a secured server.
req = requests.get(url, stream=True)
size = int(req.headers["content-length"])
Expand All @@ -184,7 +184,7 @@ def _fetch_versions(self) -> None:

url = f"{self.update_site}/versions.yml"
try:
# Note: I do not think we should pass the `verify=not Options.ssl_no_verify` kwarg here
# Note: I do not think we should pass the `verify` kwarg here
# because updates are critical and must be stored on a secured server.
with requests.get(url) as resp:
resp.raise_for_status()
Expand Down
10 changes: 9 additions & 1 deletion nxdrive/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,10 @@ def guess_server_url(
("http", domain, "", "", ""),
]

kwargs = {"timeout": timeout, "verify": not Options.ssl_no_verify}
kwargs = {
"timeout": timeout,
"verify": Options.ca_bundle or not Options.ssl_no_verify,
}
for new_url_parts in urls:
new_url = urlunsplit(new_url_parts).rstrip("/")
try:
Expand All @@ -597,6 +600,11 @@ def guess_server_url(
return new_url
except (ValueError, requests.RequestException):
pass
except OSError as exc:
# OSError: Could not find a suitable TLS CA certificate bundle, invalid path: ...
log.critical(f"{exc}. Ensure the 'ca_bundle' option is correct.")
except Exception:
log.exception("Unhandled error")

if not url.lower().startswith("http"):
return None
Expand Down

0 comments on commit abeeb11

Please sign in to comment.