DEV Community

Akhil Garg for Python Discipline @EPAM India

Posted on

How we set up GPG keys as Environment variables

This write up is in continuation of previous talk on Using GPG and Python to Secure files https://wearecommunity.io/events/using-python-and-gpg-to-secure-files.

If new to GPG keys then please go through above recording first.

Now when you have understood what GPG keys are, we can discuss its usage in projects.

In application deployments, we might have various environments like DEV, QA, STAG and PROD and there could be more.
And besides these there could be various types of files which will require multiple different GPG keys to enable encryption on them.

Now, the question is if we need GPG keys to be imported already on a specific environment before we deploy the application on it?
Well, this is one of the ways to import a key but only if we are sure keys will not frequently be changed.

Problems with this approach
A developer might have a permission to deploy an application on a specific env or this could also be done via CI/CD process. But developer might not have a full permission to import GPG keys.
He now needs another person having permission to import GPG keys. There comes a dependency now.
Every time a developer introduces a new GPG key or key gets changed then this another person having full permission on env will be required to test the newly developed changes.

How we removed this dependency
We need a solution where these keys can be configured like other configurable using environment variables.

Problem while configuring GPG keys as environment variable
Firstly let’s look at a sample GPG key:

-----BEGIN PGP PUBLIC KEY BLOCK-----

mDMEYr7UeBYJKwYBBAHaRw8BAQdAZceJqna9PlHH1t0QzO1pUk/M/p94UWt2w932
HxBZziq0IVNBUCBVc2VyIDEgPHNhcF91c2VyXzFAYXBwbGUuY29tPoiaBBMWCgBC
FiEElTDqcjvYE2kmvlx2xD2M6blccP4FAmK+1HgCGwMFCQPCZwAFCwkIBwIDIgIB
BhUKCQgLAgQWAgMBAh4HAheAAAoJEMQ9jOm5XHD+1vkBAIgwVNKc9EMAoJUMenUn
L9FdvuL3Yi/Sha+d97FoBp/IAP954uvnkM5UhSZs9/kMgKyiyHM0QrpGUn/Aqz7k
VcvuBLg4BGK+1HgSCisGAQQBl1UBBQEBB0AxD8Hev5OCrbsl1b28iomb76ylnnYg
5IsuuNrzYeRCfwMBCAeIfgQYFgoAJhYhBJUw6nI72BNpJr5cdsQ9jOm5XHD+BQJi
vtR4AhsMBQkDwmcAAAoJEMQ9jOm5XHD+C1kA/2i9r8ojLakCyy/x+n3l3uDPzxzq
ZLzaGSVv9bv9vom4AQC6QPJiNjI6xynWmjXQoxrUY3Oq4CSKmo4iuAgmekGHCA==
=t5iy
-----END PGP PUBLIC KEY BLOCK-----

As we can see the content of any GPG key is a multiline value and environment variable can have only single line value.

So we need this multiline to single line solution.

Multiline to Single line
Method 1:
We can place a separator like \n at the end of each line and can manually make this multiline value into single line.
After this, the Python code which will try to import the GPG keys will first prepare original key by removing \n with carriage return to make it multiline value again.
But we need a person to manually prepare this single line value and can be possibility that content might be changed, and then proper import will not happen.

Method 2:
We might take help of base64 utility.
A general command to export a key for sharing purpose is-
gpg --armor --export

The above command returns the multiline value.
So if we use above command as below

gpg --armor --export | base64

Single line key would look like as below:
LS0tLS1CRUdJTiBQR1AgUFVCTElDIEtFWSBCTE9DSy0tLS0tCgptUUVOQkdRejNYb0JDQURDZURnbXhZZGdXSVJzUFhCVGdxMzM3NEthSWFBZ2tLTzlYZ3dpOWxEQmFaRjNUcDdNCi9rWmxTSHRiODYyWnpnL0pGMjYwN1puK0NEMmI4dDEwLzhQZVFZbmpqOEZMcjFJcndWVjRpY3hGWW5uMXFQU0wKZGpzaDRDeXNxZThVaitmYlFWR25BeDNoSE5wNEwvSlV3NzI5QTFiTlhSVlovNzFQWWx0VWdMNzZETDg5TXY5bgpUMFBJbzE4TDJzZ2JMR1hvUWhFeExPME41cjZQaUMxTDVMeEtQUFl6ajJ6Sm1QeDg0Y2kydENFMjczVmZtWk8vCjd6aE5tWUNvRHZ4MUU4S1oxd203Q3pHZE9MNkwzN1NZd3VmWkZTSm5neHdFK0lkS1BpSXBIRDRYVGxXL3pGV1UKam9LTW5kVHhZQmtsSERTc2gxR3gzb015QWEzdGU2KzNjNUNMQUJFQkFBRzBLR052WVNCMFpYTjBJQ2gwWlhOMApJR3RsZVNrZ1BHTnZZVjkwWlhOMFFHRndjR3hsTG1OdmJUNkpBVkVFRXdFSUFEc1dJUVJrZlVyRXVoWHEvOGoyCmtsTE84d2dWZWhTZ1p3VUNaRFBkZWdJYkF3VUxDUWdIQWdJaUFnWVZDZ2tJQ3dJRUZnSURBUUllQndJWGdBQUsKQ1JETzh3Z1ZlaFNnWjBzWEIvOVc5KzhMWFBSdGtIRjlNQlpYemJHVWVwT3BtOFVzV29lY2p1TDRwNXIreC94dwpjUmVqK05NN3RWNmJMM2dSR0pTbVp1dDJGTnVSMEVGWmdTbnZYbEczbzVUMnJHUlZEMCthWjFMMys4MGNpbTVsCmozZ2E5eEdmUk9TUDE1M2wrdlVXYXo0dUZ4TlBnL25oNEY5YVJLeDExQ0Jlc0hvTGFySzJzYzZUelpHVHpQUlUKR0dGcGNkdkE4NXFJUUdwY2tYZ2hzSmg4U1lFa0ZKRTU4NXBIUVhoRFJuUUlBUXExVlhOOXFHQ1JCQWRCMkptZwpKNHM2VWhaQ0ZNdys2QVBTeUlNT0JHRzdjTlVMQ1NUK29QVXlwOUpsdWNRYXE4K29lTVN3UDVKZURwTmU0ZkQvCi9nVmI3T1FveVNyd1cvL0hFcGRrUUIxY3YrT3JPY2pyZ1FyU0hIUEl1UUVOQkdRejNYb0JDQURjenJCcTBmeUcKeWJ0VlZKZ0dnOHR3WlBUZnRuT05JSE5DWlJYOWdmbldiZG1UbVZDaXN4Sk5VeW9wOGhJNzhPUVZoNE0zYlRlbApGWENTWWZOeHorb1BhMi9ZOVp3Wis4MjNpelJRSnZSZFF6K0Yyd0M1VDJKRjBGSWw4QU9TcmVXZm1mTS9SVTJ5CnZiUks1a3VyL0RaZmkxQytCZEMxR3plNjBJZVRsM1NQSW5WZW1WVXVvWERLTytNQlZkZTFGdEZKaHVDNlFvYjgKYU9rWjhvdTVrL0tCR1p5TkdBeFI0ODN2a3ZxZGswdmpsMmVPWEo0RDQwLzhJK3RYblhKckduWFZ0dnNCc1diawptT3NiVWltS1psUVBjajlLQjNuNzkxUkQ1THA0Wk9uQ0RZbmVqbzNsNlRCcVhjZzVTK2JzdmpHS3oyNjRpNzV3CkNxMlQzUlAyK0lKVEFCRUJBQUdKQVRZRUdBRUlBQ0FXSVFSa2ZVckV1aFhxLzhqMmtsTE84d2dWZWhTZ1p3VUMKWkRQZGVnSWJEQUFLQ1JETzh3Z1ZlaFNnWnp6NENBQzhvR1FwZFBDY1FiU2NjT2FCVEdDcmVpK09RR1RTbjNSVQpGUHJUWlE2RlowMlNUbGlSOVY3Q2hEQlc0djNva0trT3MyTHNkdE1PR0hiazBlZm4wUjIrZytuOWJsaUdFREZjCm00QkhBcDlmaTQ0TTF1QjU2alNSUnBDTkdtNkJ4YzdUdEI3Z1hBWVdBVlM0MzQ5N3NjaDhoTFF5bGxJUHhUZ2wKSXh5Z1pJdG04NGlvZlI0bXZUWVZ4YUhtYXZQa3JCM1BKcTd4Q0pLdStNa1JMbTh4Qjc1RloxN3hoQTNIK1hIbQpIQkZXdzBGN1MvZWdiYWkzTnZIQnRRMG00V2tPVW51M1JZUkZJdDR1WWZweDdjR2x6Q0NXU1pienpzUklST2trCmlJbDNVYlFCWHRES09LOW1oNU5oMDJJS3IxK2hGdkJRVkJzWlk4R3NEcWVBbmtyQmxTb0UKPTN1WkkKLS0tLS1FTkQgUEdQIFBVQkxJQyBLRVkgQkxPQ0stLS0tLQo=

We will get a single line base64 encoded GPG key.
Then in Python code, we may retrieve the original GPG key before we import as below:

original_multiline_gpg_key = base64.b64decode(gpg_key_base64_encoded)

This way, we removed the dependency from a person who we were requiring just to import any new GPG key.

Disclaimer:
This is a personal blog. The views and opinions expressed here are only those of the author and do not represent those of any organization or any individual with whom the author may be associated, professionally or personally.

Top comments (0)