Skip to content

[Bicep] Accessing https://downloads.bicep.azure.com/ from Mariner 2.0 fails with ssl.SSLCertVerificationError #26007

@jiasli

Description

@jiasli

Related command
az bicep

Symptom

Accessing https://downloads.bicep.azure.com/ from Mariner 2.0 fails with ssl.SSLCertVerificationError:

> docker run -it --rm mcr.microsoft.com/cbl-mariner/base/core:2.0

# tdnf install python3 -y

# python3 -c 'from urllib.request import urlopen; urlopen("https://downloads.bicep.azure.com/")'
Traceback (most recent call last):
  File "/usr/lib/python3.9/urllib/request.py", line 1346, in do_open
    h.request(req.get_method(), req.selector, req.data, headers,
  File "/usr/lib/python3.9/http/client.py", line 1285, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "/usr/lib/python3.9/http/client.py", line 1331, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "/usr/lib/python3.9/http/client.py", line 1280, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "/usr/lib/python3.9/http/client.py", line 1040, in _send_output
    self.send(msg)
  File "/usr/lib/python3.9/http/client.py", line 980, in send
    self.connect()
  File "/usr/lib/python3.9/http/client.py", line 1454, in connect
    self.sock = self._context.wrap_socket(self.sock,
  File "/usr/lib/python3.9/ssl.py", line 501, in wrap_socket
    return self.sslsocket_class._create(
  File "/usr/lib/python3.9/ssl.py", line 1041, in _create
    self.do_handshake()
  File "/usr/lib/python3.9/ssl.py", line 1310, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get issuer certificate (_ssl.c:1129)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/lib/python3.9/urllib/request.py", line 214, in urlopen
    return opener.open(url, data, timeout)
  File "/usr/lib/python3.9/urllib/request.py", line 517, in open
    response = self._open(req, data)
  File "/usr/lib/python3.9/urllib/request.py", line 534, in _open
    result = self._call_chain(self.handle_open, protocol, protocol +
  File "/usr/lib/python3.9/urllib/request.py", line 494, in _call_chain
    result = func(*args)
  File "/usr/lib/python3.9/urllib/request.py", line 1389, in https_open
    return self.do_open(http.client.HTTPSConnection, req,
  File "/usr/lib/python3.9/urllib/request.py", line 1349, in do_open
    raise URLError(err)
urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get issuer certificate (_ssl.c:1129)>

az bicep format --file test.bicep fails with the same error on Mariner 2.0.

test.bicep can be created with

echo "param demoString string
param demoInt int
param demoBool bool
param demoObject object
param demoArray array

param location string = resourceGroup().location" > test.bicep

Root cause

As commented in #21807 (comment), the current code sets CURL_CA_BUNDLE which only affects curl, but not urllib.request.urlopen at all:

os.environ.setdefault("CURL_CA_BUNDLE", certifi.where())
request = urlopen(_get_bicep_download_url(system, release_tag, target_platform=target_platform))

urllib.request.urlopen by default uses /etc/pki/tls/cert.pem as the CA bundle:

# python3 -c 'import ssl; print(ssl.get_default_verify_paths())'
DefaultVerifyPaths(cafile='/etc/pki/tls/cert.pem', capath='/etc/pki/tls/certs', openssl_cafile_env='SSL_CERT_FILE', openssl_cafile='/etc/pki/tls/cert.pem', openssl_capath_env='SSL_CERT_DIR', openssl_capath='/etc/pki/tls/certs')

However, Mariner's system CA bundle doesn't trust https://downloads.bicep.azure.com/. This may be caused by

Possible solutions

  1. ensure_bicep_installation can use requests to download the bicep package, which internally uses certifi.where() (https://requests.readthedocs.io/en/latest/user/advanced/#ca-certificates). This is what get_bicep_available_release_tags and get_bicep_latest_release_tag do:

    response = requests.get("https://aka.ms/BicepReleases", verify=_requests_verify)

    response = requests.get("https://aka.ms/BicepLatestRelease", verify=_requests_verify)

  2. ensure_bicep_installation can pass certifi.where() to ssl.create_default_context as cafile and use the created SSLContext with urllib.request.urlopen.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions