Skip to content

Commit

Permalink
build: add encrypter docker image utils to contrib
Browse files Browse the repository at this point in the history
  • Loading branch information
spwoodcock committed Feb 28, 2024
1 parent 2857f6c commit e4b6312
Show file tree
Hide file tree
Showing 4 changed files with 183 additions and 0 deletions.
60 changes: 60 additions & 0 deletions contrib/encrypter/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Copyright (c) 2022, 2023 Humanitarian OpenStreetMap Team
# This file is part of FMTM.
#
# FMTM is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# FMTM is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with FMTM. If not, see <https:#www.gnu.org/licenses/>.
#
ARG PYTHON_IMG_TAG=3.10


# Includes all labels and timezone info to extend from
FROM docker.io/python:${PYTHON_IMG_TAG}-slim-bookworm as base
RUN set -ex \
&& apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get install \
-y --no-install-recommends "locales" "ca-certificates" \
&& DEBIAN_FRONTEND=noninteractive apt-get upgrade -y \
&& rm -rf /var/lib/apt/lists/* \
&& update-ca-certificates
# Set locale
RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && locale-gen
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
ENV LC_ALL en_US.UTF-8


# Build stage will all dependencies required to build Python wheels
FROM base as build
RUN set -ex \
&& apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get install \
-y --no-install-recommends \
"build-essential" \
"gcc" \
&& rm -rf /var/lib/apt/lists/*
RUN pip install --user --no-warn-script-location \
--no-cache-dir cryptography==42.0.5


# Run stage will minimal dependencies required to run Python libraries
FROM base as runtime
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
PYTHONFAULTHANDLER=1
# Copy Python deps from build to runtime
COPY --from=build \
/root/.local \
/root/.local
WORKDIR /code
COPY encrypter.py .
ENTRYPOINT ["python", "encrypter.py"]
42 changes: 42 additions & 0 deletions contrib/encrypter/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Encrypter Util

FMTM encrypts the ODK access token & ODK passwords in the database.

Sometimes these must be manually encrypted / decrypted for the database.

This util makes that process easier.

```bash
usage: encrypter.py [-h] [--encrypt] [--decrypt] key value

Encrypt or decrypt string values.

positional arguments:
key Encryption key.
value Value to encrypt or decrypt.

options:
-h, --help show this help message and exit
--encrypt Encrypt the value.
--decrypt Decrypt the value.
```

> Note the values may need to be quoted, as they often contain special chars.
## Encrypt a value

```bash
docker run -i --rm ghcr.io/hotosm/fmtm/encrypter:latest \
--encrypt \
your_encryption_token \
some_value_to_encrypt
```

## Decrypt a value

```bash
docker run -i --rm ghcr.io/hotosm/fmtm/encrypter:latest \
--decrypt \
your_encryption_token \
some_value_to_encrypt
```
5 changes: 5 additions & 0 deletions contrib/encrypter/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/bin/bash

docker build . -t ghcr.io/hotosm/fmtm/encrypter:latest

docker push ghcr.io/hotosm/fmtm/encrypter:latest
76 changes: 76 additions & 0 deletions contrib/encrypter/encrypter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
"""Convert between JSON and QRCode formats."""

import sys
import argparse
import base64
from cryptography.fernet import Fernet



def get_cipher_suite(key):
"""Cache cypher suite."""
return Fernet(key)


def encrypt_value(key: str, value: str) -> str:
"""Encrypt value before going to the DB."""
cipher_suite = get_cipher_suite(key)
encrypted_password = cipher_suite.encrypt(value.encode("utf-8"))
return base64.b64encode(encrypted_password).decode("utf-8")


def decrypt_value(key: str, value: str) -> str:
"""Decrypt the database value."""
cipher_suite = get_cipher_suite(key)
encrypted_password = base64.b64decode(value.encode("utf-8"))
decrypted_password = cipher_suite.decrypt(encrypted_password)
return decrypted_password.decode("utf-8")


def display_value(value: str) -> None:
"""Pretty print the final value."""
print("")
print("Value:")
print("")
print(value)
print("")


if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Encrypt or decrypt string values."
)
parser.add_argument(
"key",
help="Encryption key.",
)
parser.add_argument(
"value",
help="Value to encrypt or decrypt.",
)
parser.add_argument(
"--encrypt",
action="store_true",
help="Encrypt the value.",
)
parser.add_argument(
"--decrypt",
action="store_true",
help="Decrypt the value.",
)

args = parser.parse_args()

if args.encrypt and args.decrypt:
print("Cannot both encrypt and decrypt at the same time.")
print("Pass one of either: --encrypt or --decrypt")
sys.exit(1)

if args.encrypt:
result = encrypt_value(args.key, args.value)
display_value(result)
elif args.decrypt:
result = decrypt_value(args.key, args.value)
display_value(result)
else:
print("Please provide either --encrypt or --decrypt flag.")

0 comments on commit e4b6312

Please sign in to comment.