Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
37 changes: 30 additions & 7 deletions libmamba/src/download/downloader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "mamba/core/invoke.hpp"
#include "mamba/core/thread_utils.hpp"
#include "mamba/core/util.hpp"
#include "mamba/core/util_os.hpp"
#include "mamba/core/util_scope.hpp"
#include "mamba/download/downloader.hpp"
#include "mamba/util/build.hpp"
Expand Down Expand Up @@ -84,19 +85,41 @@ namespace mamba::download
// from `conda-forge::ca-certificates` and the system CA certificates.
else if (remote_fetch_params.ssl_verify == "<system>")
{
// Use the CA certificates from `conda-forge::ca-certificates` installed in the
// root prefix or the system CA certificates if the certificate is not present.
fs::u8path root_prefix = detail::get_root_prefix();
fs::u8path env_prefix_conda_cert = root_prefix / "ssl" / "cacert.pem";

LOG_INFO << "Checking for CA certificates at the root prefix: "
const fs::u8path executable_path = get_self_exe_path();
// Find the supposed environment prefix.
// `mamba` or `micromamba` is installed at:
// - `${PREFIX}/bin/{mamba,micromamba}` on Unix
// - `${PREFIX}/Library/bin/{mamba,micromamba}.exe` on Windows
const fs::u8path env_prefix
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This whole block is extracted from get_root_prefix right?

// Find the supposed environment prefix of libmamba.
// `libmamba` is installed at:
// - `${PREFIX}/lib/libmamba${SHLIB_EXT}` on Unix
// - `${PREFIX}/Library/bin/libmamba$.dll` on Windows
const fs::u8path libmamba_env_prefix = fs::weakly_canonical(
util::on_win ? libmamba_path.parent_path().parent_path().parent_path()
: libmamba_path.parent_path().parent_path()
);

I would prefer if you factorize that in a function called here and in get_root_prefix.

Also, I think this is a bit fragile: is that supposed to work with micromamba which can be installed in any place (my micromamba never has ../bin as an example) and doesnt have a libmamba install?

Isnt there an env variable already for the env prefix? Or we really want the one from the executable here?

I see we later check the existence of this path so maybe it's not important and it's Ok with micromamba, just asking to be sure. :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I think this is a bit fragile: is that supposed to work with micromamba which can be installed in any place (my micromamba never has ../bin as an example) and doesnt have a libmamba install?

This is only meant to support a new use-case (see conda-forge/mamba-feedstock#362 (comment)).

Isnt there an env variable already for the env prefix? Or we really want the one from the executable here?

I do not think we can expect that an environment variable is set for the use-case given above.

= (util::on_win ? executable_path.parent_path().parent_path().parent_path()
: executable_path.parent_path().parent_path());

const fs::u8path env_prefix_conda_cert = env_prefix / "ssl" / "cacert.pem";

LOG_INFO << "Checking for CA certificates in the same environment as the executable installation: "
<< env_prefix_conda_cert;

if (fs::exists(env_prefix_conda_cert))
{
LOG_INFO << "Using CA certificates from `conda-forge::ca-certificates` installed in the root prefix "
LOG_INFO << "Using CA certificates from the same prefix as the executable installation "
<< "(i.e " << env_prefix_conda_cert << ")";
remote_fetch_params.ssl_verify = env_prefix_conda_cert;
return;
}

// Try to use the CA certificates from `conda-forge::ca-certificates` installed
// in the root prefix.
const fs::u8path root_prefix = detail::get_root_prefix();
const fs::u8path root_prefix_conda_cert = root_prefix / "ssl" / "cacert.pem";

LOG_INFO << "Checking for CA certificates at the root prefix: "
<< root_prefix_conda_cert;

if (fs::exists(root_prefix_conda_cert))
{
LOG_INFO << "Using CA certificates from `conda-forge::ca-certificates` installed in the root prefix "
<< "(i.e " << root_prefix_conda_cert << ")";
remote_fetch_params.ssl_verify = root_prefix_conda_cert;
remote_fetch_params.curl_initialized = true;
return;
}
Expand Down
28 changes: 28 additions & 0 deletions micromamba/tests/test_env.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import os
import re
import shutil
import subprocess

from packaging.version import Version
from pathlib import Path
Expand Down Expand Up @@ -525,3 +526,30 @@ def test_env_export_with_pip(tmp_path, json_flag):
# Check that `requests` and `urllib3` (pulled dependency) are exported
assert "requests==2.32.3" in pip_section_vals
assert any(pkg.startswith("urllib3==") for pkg in pip_section_vals)


def test_env_export_with_ca_certificates(tmp_path):
# CA certificates in the same environment as `mamba` or `micromamba`
# executable installation are used by default.
tmp_env_prefix = tmp_path / "env-export-with-ca-certificates"

helpers.create("-p", tmp_env_prefix, "ca-certificates", no_dry_run=True)

# Copy the `micromamba` executable in this prefix `bin` subdirectory
(tmp_env_prefix / "bin").mkdir(parents=True, exist_ok=True)
tmp_env_micromamba = tmp_env_prefix / "bin" / "micromamba"
shutil.copy(helpers.get_umamba(), tmp_env_micromamba)

# Run a command using mamba in verbose mode and check that the ca-certificates file
# from the same environment as the executable is used by default.
p = subprocess.run(
[tmp_env_micromamba, "search", "xtensor", "-v"],
capture_output=True,
check=False,
)
stderr = p.stderr.decode()
assert (
"Checking for CA certificates in the same environment as the executable installation"
in stderr
)
assert "Using CA certificates from the same prefix as the executable installation" in stderr
Loading