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

webdav: SSL verification error only available with -v #10076

Open
mdekstrand opened this issue Nov 8, 2023 · 3 comments
Open

webdav: SSL verification error only available with -v #10076

mdekstrand opened this issue Nov 8, 2023 · 3 comments
Labels
enhancement Enhances DVC fs: webdav Related to the Webdav filesystem

Comments

@mdekstrand
Copy link

Bug Report

Description

When using the 'webdavs' remote, if the connection fails due to an SSL verification error, the error cause is hidden and DVC fails with an internal error message.

Reproduce

  1. Add a webdavs:// remote that points to a server with a self-signed certificate
  2. Attempt to pull from the remote

Expected

DVC to fail with an error message stating that the SSL verification failed.

This information is currently only available when running with -v.

Environment information

DVC version: 3.28.0 (conda)
---------------------------
Platform: Python 3.10.13 on macOS-13.6.1-arm64-arm-64bit
Subprojects:
	dvc_data = 2.20.0
	dvc_objects = 1.1.0
	dvc_render = 0.6.0
	dvc_task = 0.3.0
	scmrepo = 1.4.1
Supports:
	http (aiohttp = 3.8.6, aiohttp-retry = 2.8.3),
	https (aiohttp = 3.8.6, aiohttp-retry = 2.8.3),
	ssh (sshfs = 2023.10.0),
	webdav (webdav4 = 0.9.8),
	webdavs (webdav4 = 0.9.8)
Config:
	Global: /Users/mde48/Library/Application Support/dvc
	System: /Library/Application Support/dvc
Cache types: <https://error.dvc.org/no-dvc-cache>
Caches: local
Remotes: webdavs
Workspace directory: apfs on /dev/disk3s1s1
Repo: dvc, git
Repo.site_cache_dir: /Library/Caches/dvc/repo/7db9a4553acc84ea09f78eaae3e0781d
@efiop
Copy link
Contributor

efiop commented Nov 8, 2023

@mdekstrand Could you post an example, please? Unfortunately, I doubt anyone is going to actively go and try reproducing it any time soon.

If you see a nice way to improve that, contributions are welcome.

@efiop efiop added fs: webhdfs Related to the WebHDFS filesystem fs: webdav Related to the Webdav filesystem enhancement Enhances DVC and removed fs: webhdfs Related to the WebHDFS filesystem labels Nov 8, 2023
@efiop efiop changed the title SSL verification error only available with -v webdav: SSL verification error only available with -v Nov 8, 2023
@efiop efiop added the awaiting response we are waiting for your reply, please respond! :) label Nov 8, 2023
@hqdncw
Copy link

hqdncw commented Nov 21, 2023

Hi @mdekstrand,

Thanks for sharing the steps to reproduce the issue. However, I couldn't replicate the problem using those steps because it seems that something needs to be pushed to the remote storage first. If nothing has been pushed yet, then there's no error. But if we try to push changes to the remote storage, the issue can be reproduced as well.

Here are the detailed steps I took:

  1. Run the following command to generate a certificate and private key for use with SFTPGo.
openssl req -x509 -out secrets/localhost.crt -keyout secrets/localhost.key \
  -newkey rsa:4096 -nodes -sha256 \
  -subj '/CN=localhost' -extensions EXT -config <( \
   printf "[dn]\nCN=localhost\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:localhost\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth")
  1. Set up an SFTPGo server that supports WebDAV. This server will listen on a specific port number (10443) on your local machine. Configure the server to use the SSL/TLS certificate and private key created in step 1 to enable secure connections over HTTPS.
#!/usr/bin/env bash

CONTAINER_NAME="webdav"
SECRETS_DIR="/usr/local/src/secrets"

graceful_shutdown() {
  docker stop $CONTAINER_NAME && docker rm $CONTAINER_NAME
  exit
}
trap graceful_shutdown INT TERM

docker create --name $CONTAINER_NAME \
  -a STDOUT \
  -p 8080:8080 \
  -p 2022:2022 \
  -p 10443:10443 \
  -e SFTPGO_WEBDAVD__BINDINGS__0__PORT=10443 \
  -e SFTPGO_WEBDAVD__BINDINGS__0__ENABLE_HTTPS=true \
  -e SFTPGO_WEBDAVD__BINDINGS__0__CERTIFICATE_FILE=$SECRETS_DIR/localhost.crt \
  -e SFTPGO_WEBDAVD__BINDINGS__0__CERTIFICATE_KEY_FILE=$SECRETS_DIR/localhost.key \
  -t "drakkan/sftpgo:v2.5.5" || exit

docker cp -q ./secrets/ $CONTAINER_NAME:$SECRETS_DIR || exit
docker start --attach $CONTAINER_NAME || exit
  1. Make sure the server is using the certificate you provided
openssl s_client -showcerts -connect localhost:10443 </dev/null
  1. Initialize DVC.
dvc init --no-scm
  1. Track some changes.
touch example.xml && dvc add example.xml
  1. Add the remote.
dvc remote add test webdavs://localhost:10443
  1. Try to push changes to the remote.
dvc push --remote test
Actual result
$ dvc push --verbose --remote test
2023-11-18 18:11:26,480 DEBUG: v3.28.0, CPython 3.11.2 on <REDACTED>
2023-11-18 18:11:26,480 DEBUG: command: push --verbose
2023-11-18 18:11:26,701 DEBUG: Preparing to transfer data from '/home/sid/workspace/test2/.dvc/cache/files/md5' to 'https://localhost:10443/files/md5'
2023-11-18 18:11:26,702 DEBUG: Preparing to collect status from 'files/md5'
2023-11-18 18:11:26,702 DEBUG: Collecting status from 'files/md5'
2023-11-18 18:11:26,703 DEBUG: Querying 1 oids via object_exists
2023-11-18 18:11:26,820 DEBUG: Preparing to collect status from '/home/sid/workspace/test2/.dvc/cache/files/md5'
2023-11-18 18:11:26,820 DEBUG: Collecting status from '/home/sid/workspace/test2/.dvc/cache/files/md5'
2023-11-18 18:11:26,869 ERROR: unexpected error - [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certificate (_ssl.c:992): [SSL: CERTIFICATE_VERI
FY_FAILED] certificate verify failed: self-signed certificate (_ssl.c:992): [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certificate (_ssl.c:99
2)
Traceback (most recent call last):
  File "/home/sid/workspace/dvc/.venv/lib/python3.11/site-packages/httpcore/_exceptions.py", line 10, in map_exceptions
    yield
  File "/home/sid/workspace/dvc/.venv/lib/python3.11/site-packages/httpcore/_backends/sync.py", line 168, in start_tls
    raise exc
  File "/home/sid/workspace/dvc/.venv/lib/python3.11/site-packages/httpcore/_backends/sync.py", line 163, in start_tls
    sock = ssl_context.wrap_socket(
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/ssl.py", line 517, in wrap_socket
    return self.sslsocket_class._create(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/ssl.py", line 1075, in _create
    self.do_handshake()
  File "/usr/lib/python3.11/ssl.py", line 1346, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certificate (_ssl.c:992)

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/sid/workspace/dvc/.venv/lib/python3.11/site-packages/httpx/_transports/default.py", line 66, in map_httpcore_exceptions
    yield
  File "/home/sid/workspace/dvc/.venv/lib/python3.11/site-packages/httpx/_transports/default.py", line 228, in handle_request
    resp = self._pool.handle_request(req)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/sid/workspace/dvc/.venv/lib/python3.11/site-packages/httpcore/_sync/connection_pool.py", line 268, in handle_request
    raise exc
  File "/home/sid/workspace/dvc/.venv/lib/python3.11/site-packages/httpcore/_sync/connection_pool.py", line 251, in handle_request
    response = connection.handle_request(request)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/sid/workspace/dvc/.venv/lib/python3.11/site-packages/httpcore/_sync/connection.py", line 99, in handle_request
    raise exc
  File "/home/sid/workspace/dvc/.venv/lib/python3.11/site-packages/httpcore/_sync/connection.py", line 76, in handle_request
    stream = self._connect(request)
             ^^^^^^^^^^^^^^^^^^^^^^
  File "/home/sid/workspace/dvc/.venv/lib/python3.11/site-packages/httpcore/_sync/connection.py", line 156, in _connect
    stream = stream.start_tls(**kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/sid/workspace/dvc/.venv/lib/python3.11/site-packages/httpcore/_backends/sync.py", line 152, in start_tls
    with map_exceptions(exc_map):
  File "/usr/lib/python3.11/contextlib.py", line 155, in __exit__
    self.gen.throw(typ, value, traceback)
  File "/home/sid/workspace/dvc/.venv/lib/python3.11/site-packages/httpcore/_exceptions.py", line 14, in map_exceptions
    raise to_exc(exc) from exc
httpcore.ConnectError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certificate (_ssl.c:992)

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/sid/workspace/dvc/dvc/cli/__init__.py", line 209, in main
    ret = cmd.do_run()
          ^^^^^^^^^^^^
  File "/home/sid/workspace/dvc/dvc/cli/command.py", line 26, in do_run
    return self.run()
           ^^^^^^^^^^
  File "/home/sid/workspace/dvc/dvc/commands/data_sync.py", line 64, in run
    processed_files_count = self.repo.push(
                            ^^^^^^^^^^^^^^^
  File "/home/sid/workspace/dvc/dvc/repo/__init__.py", line 61, in wrapper
    return f(repo, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/sid/workspace/dvc/dvc/repo/push.py", line 115, in push
    push_transferred, push_failed = ipush(
                                    ^^^^^^
  File "/home/sid/workspace/dvc/.venv/lib/python3.11/site-packages/dvc_data/index/push.py", line 42, in push
    result = transfer(
             ^^^^^^^^^
  File "/home/sid/workspace/dvc/.venv/lib/python3.11/site-packages/dvc_data/hashfile/transfer.py", line 225, in transfer
    failed = _do_transfer(
             ^^^^^^^^^^^^^
  File "/home/sid/workspace/dvc/.venv/lib/python3.11/site-packages/dvc_data/hashfile/transfer.py", line 123, in _do_transfer
    failed_ids.update(_add(src, dest, all_file_ids, **kwargs))
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/sid/workspace/dvc/.venv/lib/python3.11/site-packages/dvc_data/hashfile/transfer.py", line 166, in _add
    dest.add(
  File "/home/sid/workspace/dvc/.venv/lib/python3.11/site-packages/dvc_data/hashfile/db/__init__.py", line 110, in add
    transferred = super().add(
                  ^^^^^^^^^^^^
  File "/home/sid/workspace/dvc/.venv/lib/python3.11/site-packages/dvc_objects/db.py", line 162, in add
    self._init(parts)
  File "/home/sid/workspace/dvc/.venv/lib/python3.11/site-packages/dvc_objects/db.py", line 67, in _init
    for path in self.fs.ls(self.path, detail=False)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/sid/workspace/dvc/.venv/lib/python3.11/site-packages/dvc_objects/fs/base.py", line 425, in ls
    return self.fs.ls(path, detail=detail, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/contextlib.py", line 81, in inner
    return func(*args, **kwds)
           ^^^^^^^^^^^^^^^^^^^
  File "/home/sid/workspace/dvc/.venv/lib/python3.11/site-packages/webdav4/fsspec.py", line 117, in ls
    data = self.client.ls(
           ^^^^^^^^^^^^^^^
  File "/home/sid/workspace/dvc/.venv/lib/python3.11/site-packages/webdav4/client.py", line 510, in ls
    result = self.propfind(
             ^^^^^^^^^^^^^^
  File "/home/sid/workspace/dvc/.venv/lib/python3.11/site-packages/webdav4/client.py", line 318, in propfind
    http_resp = self.with_retry(call)
                ^^^^^^^^^^^^^^^^^^^^^
  File "/home/sid/workspace/dvc/.venv/lib/python3.11/site-packages/webdav4/func_utils.py", line 44, in wrapped_function
    return func()
           ^^^^^^
  File "/home/sid/workspace/dvc/.venv/lib/python3.11/site-packages/webdav4/func_utils.py", line 68, in wrapped
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/home/sid/workspace/dvc/.venv/lib/python3.11/site-packages/webdav4/client.py", line 362, in _request
    http_resp = self.http.request(method, url, **kwargs)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/sid/workspace/dvc/.venv/lib/python3.11/site-packages/httpx/_client.py", line 814, in request
    return self.send(request, auth=auth, follow_redirects=follow_redirects)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/sid/workspace/dvc/.venv/lib/python3.11/site-packages/httpx/_client.py", line 901, in send
    response = self._send_handling_auth(
               ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/sid/workspace/dvc/.venv/lib/python3.11/site-packages/httpx/_client.py", line 929, in _send_handling_auth
    response = self._send_handling_redirects(
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/sid/workspace/dvc/.venv/lib/python3.11/site-packages/httpx/_client.py", line 966, in _send_handling_redirects
    response = self._send_single_request(request)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/sid/workspace/dvc/.venv/lib/python3.11/site-packages/httpx/_client.py", line 1002, in _send_single_request
    response = transport.handle_request(request)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/sid/workspace/dvc/.venv/lib/python3.11/site-packages/httpx/_transports/default.py", line 227, in handle_request
    with map_httpcore_exceptions():
  File "/usr/lib/python3.11/contextlib.py", line 155, in __exit__
    self.gen.throw(typ, value, traceback)
  File "/home/sid/workspace/dvc/.venv/lib/python3.11/site-packages/httpx/_transports/default.py", line 83, in map_httpcore_exceptions
    raise mapped_exc(message) from exc
httpx.ConnectError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certificate (_ssl.c:992)

2023-11-18 18:11:26,916 DEBUG: link type reflink is not available ([Errno 95] no more link types left to try out)
2023-11-18 18:11:26,916 DEBUG: Removing '/home/sid/workspace/.HMJK2Xt7dTDwuiabtdYWRh.tmp'
2023-11-18 18:11:26,916 DEBUG: Removing '/home/sid/workspace/.HMJK2Xt7dTDwuiabtdYWRh.tmp'
2023-11-18 18:11:26,916 DEBUG: Removing '/home/sid/workspace/.HMJK2Xt7dTDwuiabtdYWRh.tmp'
2023-11-18 18:11:26,916 DEBUG: Removing '/home/sid/workspace/test2/.dvc/cache/files/md5/.NfyncAmxhrw2j8BWgewtgV.tmp'
2023-11-18 18:11:26,918 DEBUG: Version info for developers:
DVC version: 3.28.0
-------------------
Platform: Python 3.11.2 on <REDACTED>
Subprojects:
        dvc_data = 2.20.0
        dvc_objects = 1.1.0
        dvc_render = 0.6.0
        dvc_task = 0.3.0
        scmrepo = 1.4.1
Supports:
        azure (adlfs = 2023.10.0, knack = 0.11.0, azure-identity = 1.15.0),
        gdrive (pydrive2 = 1.17.0),
        gs (gcsfs = 2023.9.2),
        hdfs (fsspec = 2023.9.2, pyarrow = 14.0.1),
        http (aiohttp = 3.8.6, aiohttp-retry = 2.8.3),
        https (aiohttp = 3.8.6, aiohttp-retry = 2.8.3),
        oss (ossfs = 2021.8.0),
        s3 (s3fs = 2023.9.2, boto3 = 1.28.17),
        ssh (sshfs = 2023.10.0),
        webdav (webdav4 = 0.9.8),
        webdavs (webdav4 = 0.9.8),
        webhdfs (fsspec = 2023.9.2)
Config:
        Global: /home/sid/.config/dvc
        System: /etc/xdg/dvc
Cache types: hardlink, symlink
Cache directory: ext4 on /dev/sda9
Caches: local
Remotes: webdavs
Workspace directory: ext4 on /dev/sda9
Repo: dvc (no_scm)
Repo.site_cache_dir: /var/tmp/dvc/repo/565945b4dca6a1d7be16ba663c6af60c

Having any troubles? Hit us up at https://dvc.org/support, we are always happy to help!
2023-11-18 18:11:26,919 DEBUG: Analytics is disabled.

@mdekstrand
Copy link
Author

Thanks @hqdncw! That's exactly the error situation I was seeing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Enhances DVC fs: webdav Related to the Webdav filesystem
Projects
None yet
Development

No branches or pull requests

3 participants