~/security/dockerfile-fips-enabled-python-with-openssl.md

Dockerfile for building Python 3.9.2 and Openssl for FIPS

3 min readMarch 03, 2021by Gorav Singal#openssl#fips#security
// TL;DR

A complete Dockerfile that builds FIPS-enabled OpenSSL and patches Python 3.9.2 to use it, combining both build steps into a single container image.

Dockerfile for building Python 3.9.2 and Openssl for FIPS

Introduction

In previous posts, we saw how to build FIPS enabled Openssl, and how to Patch and Build Python 3.9.2

In this post, we will put all those steps in a Dockerfile.

Python 3.9.2 Patch

Create a file with name: python_patch_3.9.2.patch

diff -aur Lib/ssl.py Lib/ssl.py
--- Lib/ssl.py	2020-10-05 15:07:58.000000000 +0000
+++ Lib/ssl.py	2021-03-02 04:23:32.026226000 +0000
@@ -111,6 +111,11 @@
     # LibreSSL does not provide RAND_egd
     pass
 
+try:
+    from _ssl import FIPS_mode, FIPS_mode_set
+except ImportError as e:
+    sys.stderr.write('error in importing\n')
+    sys.stderr.write(str(e))
 
 from _ssl import (
     HAS_SNI, HAS_ECDH, HAS_NPN, HAS_ALPN, HAS_SSLv2, HAS_SSLv3, HAS_TLSv1,
diff -aur Modules/Setup Modules/Setup
--- Modules/Setup	2020-10-05 15:07:58.000000000 +0000
+++ Modules/Setup	2021-03-02 04:24:28.071717000 +0000
@@ -207,14 +207,14 @@
 #_csv _csv.c
 
 # Socket module helper for socket(2)
-#_socket socketmodule.c
+_socket socketmodule.c
 
 # Socket module helper for SSL support; you must comment out the other
 # socket line above, and possibly edit the SSL variable:
-#SSL=/usr/local/ssl
-#_ssl _ssl.c \
-#	-DUSE_SSL -I$(SSL)/include -I$(SSL)/include/openssl \
-#	-L$(SSL)/lib -lssl -lcrypto
+SSL=/usr/local/ssl
+_ssl _ssl.c \
+	-DUSE_SSL -I$(SSL)/include -I$(SSL)/include/openssl \
+	-L$(SSL)/lib -lssl -lcrypto
 
 # The crypt module is now disabled by default because it breaks builds
 # on many systems (where -lcrypt is needed), e.g. Linux (I believe).
diff -aur Modules/_ssl.c Modules/_ssl.c
--- Modules/_ssl.c	2020-10-05 15:07:58.000000000 +0000
+++ Modules/_ssl.c	2021-03-02 04:25:30.930669000 +0000
@@ -5394,6 +5394,20 @@
     return PyLong_FromLong(RAND_status());
 }
 
+static PyObject *
+_ssl_FIPS_mode_impl(PyObject *module) {
+    return PyLong_FromLong(FIPS_mode());
+}
+
+static PyObject *
+_ssl_FIPS_mode_set_impl(PyObject *module, int n) {
+    if (FIPS_mode_set(n) == 0) {
+        _setSSLError(ERR_error_string(ERR_get_error(), NULL) , 0, __FILE__, __LINE__);
+        return NULL;
+    }
+    Py_RETURN_NONE;
+}
+
 #ifndef OPENSSL_NO_EGD
 /* LCOV_EXCL_START */
 /*[clinic input]
@@ -5875,6 +5889,8 @@
     _SSL_ENUM_CRLS_METHODDEF
     _SSL_TXT2OBJ_METHODDEF
     _SSL_NID2OBJ_METHODDEF
+    _SSL_FIPS_MODE_METHODDEF
+    _SSL_FIPS_MODE_SET_METHODDEF
     {NULL,                  NULL}            /* Sentinel */
 };
 
diff -aur Modules/clinic/_ssl.c.h Modules/clinic/_ssl.c.h
--- Modules/clinic/_ssl.c.h	2020-10-05 15:07:58.000000000 +0000
+++ Modules/clinic/_ssl.c.h	2021-03-02 04:27:06.120295000 +0000
@@ -1204,6 +1204,45 @@
     return _ssl_RAND_status_impl(module);
 }
 
+PyDoc_STRVAR(_ssl_FIPS_mode__doc__,
+"FIPS Mode");
+
+#define _SSL_FIPS_MODE_METHODDEF    \
+    {"FIPS_mode", (PyCFunction)_ssl_FIPS_mode, METH_NOARGS, _ssl_FIPS_mode__doc__},
+
+static PyObject *
+_ssl_FIPS_mode_impl(PyObject *module);
+
+static PyObject *
+_ssl_FIPS_mode(PyObject *module, PyObject *Py_UNUSED(ignored))
+{
+    return _ssl_FIPS_mode_impl(module);
+}
+
+PyDoc_STRVAR(_ssl_FIPS_mode_set_doc__,
+"FIPS Mode Set");
+
+#define _SSL_FIPS_MODE_SET_METHODDEF    \
+    {"FIPS_mode_set", (PyCFunction)_ssl_FIPS_mode_set, METH_O, _ssl_FIPS_mode_set_doc__},
+
+static PyObject *
+_ssl_FIPS_mode_set_impl(PyObject *module, int n);
+
+static PyObject *
+_ssl_FIPS_mode_set(PyObject *module, PyObject *arg)
+{
+    PyObject *return_value = NULL;
+    int n;
+
+    if (!PyArg_Parse(arg, "i:FIPS_mode_set", &n)) {
+        goto exit;
+    }
+    return_value = _ssl_FIPS_mode_set_impl(module, n);
+
+exit:
+    return return_value;
+}
+
 #if !defined(OPENSSL_NO_EGD)
 
 PyDoc_STRVAR(_ssl_RAND_egd__doc__,

Dockerfile

FROM centos:7

RUN yum update -y 
RUN yum -y install git \
    libffi-devel libffi libssh2-devel autoconf automake libtool \
    libxml2-devel libxslt-devel libjpeg-devel zlib-devel \
    make cmake gcc python-devel python-setuptools wget bzip2-devel 

# OpenSSL build steps
ENV OPENSSL_FIPS=1
RUN mkdir -p /usr/local/src/ /python_installation \
  && cd /usr/local/src/ \
  && curl -O https://www.openssl.org/source/openssl-fips-2.0.16.tar.gz \
  && curl -O https://www.openssl.org/source/openssl-1.0.2t.tar.gz \
  && tar -xvf openssl-fips-2.0.16.tar.gz \
  && cd openssl-fips-2.0.16 \
  && ./config \
  && make install \
  && cd ../ \
  && tar -xvf openssl-1.0.2t.tar.gz \
  && cd openssl-1.0.2t \
  && ./config shared fips no-ssl2 no-ssl3 \
  && make depend \
  && make install \
  && cd ../ && rm -rf openssl-fips-2.0.16.tar.gz ./openssl-fips-2.0.16 \
  && echo "/usr/local/ssl/lib" > /etc/ld.so.conf.d/openssl-1.0.2t.conf \
  && ldconfig -v \
  && ln -s /usr/local/ssl/bin/openssl /usr/bin/openssl \
  && openssl version

ADD python_patch_3.9.2.patch /python_installation/
ARG PYENV_VERSION=3.9.2
ENV PYENV_INSTALLER_URL=https://raw.githubusercontent.com/pyenv/pyenv-installer/master/bin/pyenv-installer
ENV PYTHON_CONFIGURE_OPTS="--enable-shared"
RUN umask 022 \
 && curl -s -S -L "$PYENV_INSTALLER_URL" -o /usr/bin/pyenv-installer \
 && chmod 0755 /usr/bin/pyenv-installer \
 && /usr/bin/pyenv-installer \
 && eval "$(pyenv init -)" \
 && pyenv install --patch $PYENV_VERSION < /python_installation/python_patch_3.9.2.patch \
 && pyenv global $PYENV_VERSION \
 && pip install --upgrade pip \
 && pip install wheel \
 && CRYPTOGRAPHY_DONT_BUILD_RUST=1 CFLAGS="-I/usr/local/ssl/include" LDFLAGS="-L/usr/local/ssl/lib" pip wheel --no-binary :all: cryptography==3.0 \
  && CRYPTOGRAPHY_DONT_BUILD_RUST=1 CFLAGS="-I/usr/local/ssl/include" LDFLAGS="-L/usr/local/ssl/lib" pip install cryptography-3.0-cp39-cp39-linux_x86_64.whl 

Related Post

$ subscribe --weekly

One deep dive a week, in your inbox

System design, AI engineering, trading systems and interview prep. Tested code, real numbers. Free, and you can unsubscribe any time.

or read it on gyanbyte.substack.com

Share

Related Posts

How to Patch and Build Python 3.9.x for FIPS enabled Openssl

How to Patch and Build Python 3.9.x for FIPS enabled Openssl

Introduction In this post, we will see Python 3.9.x patch for FIPS enabled…

How to Patch and Build Python 3.7.9 for FIPS enabled Openssl

How to Patch and Build Python 3.7.9 for FIPS enabled Openssl

Introduction In this post, we will see Python 3.7.9 patch for FIPS enabled…

How to build FIPS enabled Openssl in docker

How to build FIPS enabled Openssl in docker

Introduction In this post, we will see how we can build FIPS enabled openssl in…

Python - How to apply patch to Python and Install Python via Pyenv

Python - How to apply patch to Python and Install Python via Pyenv

Introduction In this post, we will see how we can apply a patch to Python and…

How to Install Python from command line and Docker on Windows

How to Install Python from command line and Docker on Windows

Introduction We will see how we can install Python 3.7 on Windows without UI. i…

How to Install Python from command line and Docker on Linux

How to Install Python from command line and Docker on Linux

Introduction We will see how we can install Python from command line using pyenv…

Latest Posts

How to Stay Valuable as a Software Engineer in the AI Era: A Practical Playbook

How to Stay Valuable as a Software Engineer in the AI Era: A Practical Playbook

In the previous article I argued that AI is not killing software engineering…

How to Review AI-Generated Code: A Checklist for Catching What the Model Missed

How to Review AI-Generated Code: A Checklist for Catching What the Model Missed

A few months back I approved a PR that was almost entirely AI-generated. It…

How to Debug AI-Generated Code: Understand First, Fix Last

How to Debug AI-Generated Code: Understand First, Fix Last

In the last article I wrote about reviewing AI code before it goes in. This one…

The Future of Software Engineering: What AI Changes, What Stays, and Where the Jobs Go

The Future of Software Engineering: What AI Changes, What Stays, and Where the Jobs Go

Every few weeks somebody sends me a scary headline — “AI will replace all…

The Transactional Outbox Pattern: Never Lose an Event Again

The Transactional Outbox Pattern: Never Lose an Event Again

This is one of those patterns that looks like nothing until you get burnt once…

Event Sourcing, Explained: Store What Happened, Not Just the Final State

Event Sourcing, Explained: Store What Happened, Not Just the Final State

Here is a question I like to ask in interviews: your bank account shows a…