This documentation is for Version 1 of the Amazon CLI only. For documentation related to Version 2 of the Amazon CLI, see the Version 2 User Guide.
Enforcing a minimum version of TLS for the Amazon CLI
When using the Amazon Command Line Interface (Amazon CLI), the Transport Layer Security (TLS) protocol plays a crucial role in securing communication between the Amazon CLI and Amazon Web Services services. To add increased security when communicating with Amazon services, you should use TLS 1.2 or later.
The Amazon CLI and Amazon Web Services service can exchange data securely, with the TLS protocol providing encryption, authentication, and data integrity. By leveraging the TLS protocol, the Amazon CLI ensures that your interactions with Amazon Web Services services are protected from unauthorized access and data breaches, enhancing the overall security of your Amazon ecosystem.
The Amazon shared
responsibility model
To ensure the Amazon CLI version 1 uses no TLS version earlier than TLS 1.2, you might need to recompile OpenSSL to enforce this minimum and then recompile Python to use the newly built OpenSSL.
Determine your currently supported protocols
First, create a self-signed certificate to use for the test server and the Python SDK using OpenSSL.
$
openssl req -subj '/CN=localhost' -x509 -newkey rsa:4096 -nodes -keyout key.pem -out cert.pem -days 365
Then spin up a test server using OpenSSL.
$
openssl s_server -key key.pem -cert cert.pem -www
In a new terminal window, create a virtual environment and install the SDK for Python.
$
python3 -m venv test-env source test-env/bin/activate pip install botocore
Create a new Python script named check.py
that uses the SDK’s
underlying HTTP library.
$
import urllib3 URL = 'https://localhost:4433/' http = urllib3.PoolManager( ca_certs='cert.pem', cert_reqs='CERT_REQUIRED', ) r = http.request('GET', URL) print(r.data.decode('utf-8'))
Run your new script.
$
python check.py
This displays details about the connection made. Search for "Protocol : " in the output. If the output is "TLSv1.2" or later, the SDK defaults to TLS v1.2 or later. If it's an earlier version, you need to recompile OpenSSL and recompile Python.
However, even if your installation of Python defaults to TLS v1.2 or later, it's still possible for Python to renegotiate to a version earlier than TLS v1.2 if the server doesn't support TLS v1.2 or later. To check that Python doesn't automatically renegotiate to earlier versions, restart the test server with the following.
$
openssl s_server -key key.pem -cert cert.pem -no_tls1_3 -no_tls1_2 -www
If you're using an earlier version of OpenSSL, you might not have the
-no_tls_3
flag available. If this is the case, remove the flag
because the version of OpenSSL you're using doesn't support TLS v1.3. Then rerun the
Python script.
$
python check.py
If your installation of Python correctly doesn't renegotiate for versions earlier than TLS 1.2, you should receive an SSL error.
$
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='localhost', port=4433): Max retries exceeded with url: / (Caused by SSLError(SSLError(1, '[SSL: UNSUPPORTED_PROTOCOL] unsupported protocol (_ssl.c:1108)')))
If you're able to make a connection, you need to recompile OpenSSL and Python to disable negotiation of protocols earlier than TLS v1.2.
Compile OpenSSL and Python
To ensure the SDK or Amazon CLI doesn't negotiate for anything earlier than TLS 1.2, you need to recompile OpenSSL and Python. To do this, copy the following content to create a script and run it.
#!/usr/bin/env bash set -e OPENSSL_VERSION="1.1.1d" OPENSSL_PREFIX="/opt/openssl-with-min-tls1_2" PYTHON_VERSION="3.8.1" PYTHON_PREFIX="/opt/python-with-min-tls1_2" curl -O "https://www.openssl.org/source/openssl-$OPENSSL_VERSION.tar.gz" tar -xzf "openssl-$OPENSSL_VERSION.tar.gz" cd openssl-$OPENSSL_VERSION ./config --prefix=$OPENSSL_PREFIX no-ssl3 no-tls1 no-tls1_1 no-shared make > /dev/null sudo make install_sw > /dev/null cd /tmp curl -O "https://www.python.org/ftp/python/$PYTHON_VERSION/Python-$PYTHON_VERSION.tgz" tar -xzf "Python-$PYTHON_VERSION.tgz" cd Python-$PYTHON_VERSION ./configure --prefix=$PYTHON_PREFIX --with-openssl=$OPENSSL_PREFIX --disable-shared > /dev/null make > /dev/null sudo make install > /dev/null
This compiles a version of Python that has a statically linked OpenSSL that
doesn't automatically negotiate anything earlier than TLS 1.2. This also installs
OpenSSL in the /opt/openssl-with-min-tls1_2
directory and installs
Python in the /opt/python-with-min-tls1_2
directory. After you run this
script, confirm installation of the new version of Python.
$
/opt/python-with-min-tls1_2/bin/python3 --version
This should print out the following.
$
Python 3.8.1
To confirm this new version of Python doesn't negotiate a version earlier than TLS
1.2, rerun the steps from Determine your currently supported
protocols using the newly installed Python
version (that is,
/opt/python-with-min-tls1_2/bin/python3
).