Skip to main content

'Protecting' python code with Cython and Docker

· 3 min read
Shaw Innes
Builder of things

Security Through Obscurity

I was looking for a method to distribute some proprietary code to 3rd parties with some level of IP protection. Knowing that this is a losing battle, and that I suspected that it was more about limiting curiosity rather than deliberate reverse engineering, I decided to investigate the use of cython to compile python via C into a binary.

This repo demonstrates the process of building a Flask app into a Docker container with a compiled binary of the application using Cython. It also uses a multi-stage docker build to ensure that the original source files are never copied into the target image.

For a more thorough obfuscation, I would suggesting looking into using a more robust solution such as this.

How it works

There is simply a compilation step defined in setup.py that refers to the src/api.pyx file. This file uses cython to do the build, and outputs a binary library file which can later be referenced via gunicorn, or in other python files as a normal module reference.

setup.py
from distutils.core import setup
from Cython.Distutils import build_ext
from Cython.Build import cythonize

setup(
name='Hello Flask',
cmdclass={'build_ext': build_ext},
ext_modules=cythonize("src/api.pyx",
compiler_directives={'language_level': "3"},
build_dir="build"
)
)

Local Build

pip install -r requirements.txt
python setup.py build_ext --inplace

Confirming the binary is built

As you can see, the binary is compiled as a shared object fil, the following screenshot shows a hex dump of this file. Although it would be possible to reverse engineer this file, the effort required to do so would be considerable.

XXD hexdump of the compiled library

Running the local binary with gunicorn

gunicorn api:app

Building the image for docker

Build single-arch image, load to local docker

docker buildx build --platform linux/arm64 --load --tag helloflask .

docker buildx build --platform linux/amd64 --load --tag helloflask .

Build multi-arch image

docker buildx build --platform linux/arm64,linux/amd64 --tag helloflask .

Running the image

docker run -p 80:80 -it helloflask

Running the built docker image

Confirming the binary is in the image

Screenshot showing that there are no source files in the docker image

Conclusion

Although this is literally the definition of security through obscurity, for many use cases this might be enough.

I haven't gone beyond a hello world example of this approach, so there are likely deficiencies in the approach, I'm not sure for example what would happen with more complex dependencies. The fact that Flask worked more or less straight up is encouraging though.

I've stored this in a public repo, so if you have any suggestions or improvements, please feel free to raise an issue or PR.

DDD Melbourne

· 2 min read
Shaw Innes
Builder of things

Shaw at DDD Melbourne

Overview

I had the pleasure of presenting my thoughts about documentation as code, this time at DDD Melbourne.

The main point of this talk is to focus your documentation on filling the gaps between the obvious, how can you make your codebases easily discoverable and enable new team members to join your project and quickly get up to speed and provide valuable contributions in the shortest possible time.

Below is a quick visual outline of my presentation.

Visual overview of Documentation for Developers

  • Overview - README.MD Markdown files to help developers understand what they're looking at.
  • Get Started - README.MD Markdown file with more information to help developers get started, install dependencies, etc.
  • Old Decisions - Architecture Decision Records to understand what decisions have been made in the past, and why.
  • New Decisions - Architecture Principles to help guide future decisions.
  • Architecture - Diagrams to help developers understand the architecture of the system.
  • Sharing - Use mkdocs to to share documentation with the team.
  • Scaling - Ways to share and scale documentation as the team grows beyond a few repositories.

Securing Content in Azure Static Web Apps

· 6 min read
Shaw Innes
Builder of things

Recently, I’ve been working on a few internal projects that required creating and hosting documentation for our team.

However, one challenge consistently got in the way of me being able to quickly share the information: finding an uncomplicated yet secure way to host this valuable content.

Using a static content generator like mkdocs was my preferred approach, but I really wanted to avoid having to run it in a docker container or behind a web server in order to add authentication to the mix.

As it turns out, Azure Static Web Apps paired with MkDocs and Azure AD is a relatively simple solution to this problem. The documentation alludes to the fact you can do all of this, but it took a few hours of stuffing around to get it "just right". Hopefully this can save you the hassle.

Documentation for Developers

· 4 min read
Shaw Innes
Builder of things

Onboarding new team members can be a costly aspect of building and maintaining software, and this gets harder the bigger your organisation gets.

It's well known how much we cringe at the thought of having to write documentation, but thinking about it differently, and adopting a documentation-as-code approach we can remove the friction of this process.

In my talk, "Documentation for Developers", I share some stories and practices you can use to help make your software easier to understand for new developers joining the team. I also share some tools and techniques for capturing the architecture and design of your software.

Whether you're a one-person team hoping to scale up, or an enterprise with hundreds of repos, this talk will have some useful tips.

Azure AD B2C and MSAL

· 3 min read
Shaw Innes
Builder of things

I recently tried to create a simple demonstration of using Azure B2C in a React App using the MSAL-browser and MSAL-react libraries following the official documentation. I found it very confusing to understand which endpoints I should be using to use B2C authentication rather than AAD, and to subsequently obtain an access token.

If you don't care about my struggles and just want to copy and paste a solution: Give me the code!

Server-Side Geospatial Clustering

· 7 min read

I was recently asked by a colleague to help brainstorm a solution to displaying a large number of data points onto a leafletjs map on a client project. The problem was that although client-side clustering was working in most instances, it was suffering from performance problems due to having to send the entire dataset to the client before performing the clustering.

One proposed solution which we implemented was to round the latitude and longitude of the resulting data with lower precision which would effectively group nearby points onto a single location which could be grouped. While this worked, it didn't seem clean to me so I decided to do some further research into established solutions for this.

TL;DR - I've created a working sample project for this here

Adding an Authority Key Identifier in .NET Core

· One min read

When creating a certificate request to create an intermediate CA, you generally want to add an Authority Key Identifier to the request so that there is clarity as to which issuing key was used to sign the intermediate CA cert. .NET Core currently lacks a native extension for this, so I hacked something together, allowing a similar experience to when adding a Subject Key Identifier to the request.

Quickly Serving Local Content

· 2 min read

Sometimes you need to serve some local static content over HTTP/HTTPS for testing SPAs or other things.

I recently stumbled across the dotnet-serve tool which is a dotnet cli global tool. It provides similar basic functionality to the Python module, however it also allows you to do a couple of extra things like returning headers, enabling HTTPS, and enabling content compression.

DevExtreme and Angular with Internationalisation

· 2 min read

As an Australian developer, I'm always fighting with applications that default to US date formats. I was recently working on an Angular 8 application which was using the DevExpress DevExtreme components. The problem was that the date controls kept formatting my dates as MM/DD/YYYY which isn't helpful

I had a look at the DevExpress documentation and struggled to configure it to use my Australian date formats. It took longer than I expected to figure out the trick, so I thought I'd document it here for anyone else who gets stuck.

Say No to No

· 3 min read

When you're at work meetings, have you ever noticed how many people will just find all the reasons why something won't work?

Have you ever worked with someone who, rather than doing this, moves towards the outcome whilst working around the challenges. "yes, we can do this, and we need to manage these risks"

Employees of large companies waste millions of dollars every year having circular arguments about why particular activities won't work.  These activities are time-consuming, frustrating, and largely ineffective.

A while ago I was introduced to the term "Institutional Yes" vs "Institutional No".  The way I see this idea is that any given organisation will have a predisposition or culture towards having a positive or negative attitude towards the possibility of taking action.