如何在Docker中使用OpenGPG而不使用口令

392 阅读3分钟

如果你不想在你的设备上安装GPG/PGP来使用其命令,你可以尝试下面的Docker设置。通过目前的设置,你可以对信息进行加密和解密。唯一可以添加的是,文件加密和解密应该很容易。

这块工作专门用于消息加密和解密,不需要用户的互动。密钥不受密码保护,因此它只用于内部或你的使用。例如,信息是用你的详细资料加密的,你被用作加密信息的接收者,在现实生活中通常是其他人。简而言之,你同时是发件人和收件人。这样做的原因是,我们想在CI中加密AWS IAM用户的密码,向你发送加密的输出,这样你就可以解密以获得实际的登录密码,该密码应该被立即更改。CI只需要知道如何加密一个信息,其他的都不需要

你的详细资料在.env.dist ,使用示例值。然而,对于真实的值,这个文件必须被复制为.env ,并包含真实的值。这个文件被排除在VCS提交以及/data/ 文件夹之外,在运行make 命令后,GPG密钥被放置在这个文件夹中。

结构

这是原始状态:

├── .dockerignore
├── .env.dist
├── .gitignore
├── Dockerfile
├── Makefile
├── Readme.md
├── data
│   └── msg-to-encrypt.txt
├── docker-compose.yaml
├── gpg.cfg
└── gpg.sh

这个输出是在运行下面的命令之后:

├── .dockerignore
├── .env.dist
├── .gitignore
├── Dockerfile
├── Makefile
├── Readme.md
├── data
│   ├── decrypted-msg.txt
│   ├── encrypted-msg.txt
│   ├── msg-to-encrypt.txt
│   ├── private.key
│   └── public.key
├── docker-compose.yaml
├── gpg.cfg
└── gpg.sh

文件

msg-to-encrypt.txt

Hello!

.dockerignore

*
!/gpg.sh
!/gpg.cfg

.env.dist

NAME_REAL=Continuous Integration and Delivery
NAME_COMMENT=CI\/CD use only
NAME_EMAIL=cicd@example.com

.gitignore

data/*
!data/msg-to-encrypt.txt
.env

docker-compose.yaml

services:
  gpg:
    container_name: gpg
    build:
      context: "."
    env_file:
      - ".env"
    environment:
      - ACTION=${ACTION}
    volumes:
      - "./data:/data"

Dockerfile

FROM alpine:3.16.0
COPY . .
RUN apk update && apk fetch gnupg && apk add gnupg && chmod +x gpg.sh
ENTRYPOINT ["./gpg.sh"]

gpg.cfg

Key-Type: RSA
Key-Length: 2048
Subkey-Type: RSA
Subkey-Length: 2048
Name-Real: ${NAME_REAL}
Name-Comment: ${NAME_COMMENT}
Name-Email: ${NAME_EMAIL}
Expire-Date: 0
%no-protection

gig.sh

#!/bin/sh

set -eu

CYAN="\033[0;36m"
CLEAR="\033[0m"
GPG_DIR="/root/.gnupg"
DATA_DIR="/data"
PUBLIC_KEY_NAME="public.key"
PRIVATE_KEY_NAME="private.key"
DECRYPTED_MSG_NAME="decrypted-msg.txt"
ENCRYPTED_MSG_NAME="encrypted-msg.txt"
MESSAGE_TO_ENCRYPT_NAME="msg-to-encrypt.txt"

gen_key() {
    printf "${CYAN}> GENERATE KEYS (begin) --------------------------${CLEAR}\n"
    
    printf "${CYAN}Set local variables${CLEAR}\n"
    PUB_KEY="${DATA_DIR}/${PUBLIC_KEY_NAME}"
    PRV_KEY="${DATA_DIR}/${PRIVATE_KEY_NAME}"
    CFG_KEY="/gpg.cfg"
    echo "done"

    printf "${CYAN}Prepare configuration file${CLEAR}\n"
    sed -i \
        -e 's/${NAME_REAL}/'"${NAME_REAL}"'/g' \
        -e 's/${NAME_COMMENT}/'"${NAME_COMMENT}"'/g' \
        -e 's/${NAME_EMAIL}/'"${NAME_EMAIL}"'/g' \
        ${CFG_KEY}
    echo "done"

    printf "${CYAN}Create gpg directory and get into it${CLEAR}\n"
    gpg2 --list-keys
    cd ${GPG_DIR}

    printf "${CYAN}Generate keys${CLEAR}\n"
    gpg2 --verbose --batch --gen-key ${CFG_KEY}

    printf "${CYAN}Backup public and private keys${CLEAR}\n"
    gpg2 --yes --output ${PUB_KEY} --armor --export-options export-backup --export ${NAME_EMAIL}
    gpg2 --yes --output ${PRV_KEY} --armor --export-options export-backup --export-secret-keys ${NAME_EMAIL}
    echo "done"

    printf "${CYAN}Cleanup${CLEAR}\n"
    cleanup
    echo "done"

    printf "${CYAN}> GENERATE KEYS (end) ----------------------------${CLEAR}\n"
}

enc_msg() {
    printf "${CYAN}> ENCRYPT MESSAGE (begin) ------------------------${CLEAR}\n"

    printf "${CYAN}Set local variables${CLEAR}\n"
    PUB_KEY="${DATA_DIR}/${PUBLIC_KEY_NAME}"
    PRV_KEY="${DATA_DIR}/${PRIVATE_KEY_NAME}"
    ENCRYPTED_MSG="${DATA_DIR}/${ENCRYPTED_MSG_NAME}"
    MESSAGE_TO_ENCRYPT="${DATA_DIR}/${MESSAGE_TO_ENCRYPT_NAME}"
    echo "done"

    printf "${CYAN}Create gpg directory and get into it${CLEAR}\n"
    gpg2 --list-keys
    cd ${GPG_DIR}

    printf "${CYAN}Restore public key${CLEAR}\n"
    gpg2 --import-options import-restore --import ${PUB_KEY}
    
    printf "${CYAN}Restore private key${CLEAR}\n"
    gpg2 --import-options import-restore --import ${PRV_KEY}

    printf "${CYAN}Auto trust and verify keys${CLEAR}\n"
    echo -e "5\ny\n" | gpg2 --command-fd 0 --expert --edit-key ${NAME_EMAIL} trust

    printf "${CYAN}Encrypt message${CLEAR}\n"
    gpg2 --batch --yes --output ${ENCRYPTED_MSG} --encrypt --sign --armor -r ${NAME_EMAIL} ${MESSAGE_TO_ENCRYPT}
    echo "done"

    printf "${CYAN}Cleanup${CLEAR}\n"
    cleanup
    echo "done"
    
    printf "${CYAN}> ENCRYPT MESSAGE (end) --------------------------${CLEAR}\n"
}

dec_msg() {
    printf "${CYAN}> DECRYPT MESSAGE (begin) ------------------------${CLEAR}\n"
    
    printf "${CYAN}Set local variables${CLEAR}\n"
    PUB_KEY="${DATA_DIR}/${PUBLIC_KEY_NAME}"
    PRV_KEY="${DATA_DIR}/${PRIVATE_KEY_NAME}"
    ENCRYPTED_MSG="${DATA_DIR}/${ENCRYPTED_MSG_NAME}"
    DECRYPTED_MSG="${DATA_DIR}/${DECRYPTED_MSG_NAME}"
    echo "done"

    printf "${CYAN}Create gpg directory and get into it${CLEAR}\n"
    gpg2 --list-keys
    cd ${GPG_DIR}

    printf "${CYAN}Restore public key${CLEAR}\n"
    gpg2 --import-options import-restore --import ${PUB_KEY}
    
    printf "${CYAN}Restore private key${CLEAR}\n"
    gpg2 --import-options import-restore --import ${PRV_KEY}

    printf "${CYAN}Decrypt message${CLEAR}\n"
    gpg2 --decrypt ${ENCRYPTED_MSG} > ${DECRYPTED_MSG}

    printf "${CYAN}Cleanup${CLEAR}\n"
    cleanup
    echo "done"

    printf "${CYAN}> DECRYPT MESSAGE (end) --------------------------${CLEAR}\n"
}

cleanup() {
    cd /
    rm -rf ${GPG_DIR}
    rm gpg.sh gpg.cfg
}

if [ ${ACTION} == "gen-key" ]; then gen_key; fi
if [ ${ACTION} == "enc-msg" ]; then enc_msg; fi
if [ ${ACTION} == "dec-msg" ]; then dec_msg; fi

制作文件

.PHONY: help
help: ## Display available commands
	@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)

.PHONY: gen-key
gen-key: ## Generate keys
	make down
	ACTION=gen-key docker-compose run --rm gpg

.PHONY: enc-msg
enc-msg: ## Encrypt message
	make down
	ACTION=enc-msg docker-compose run --rm gpg

.PHONY: dec-msg
dec-msg: ## Decrypt message
	make down
	ACTION=dec-msg docker-compose run --rm gpg

.PHONY: config
config: ## Dump docker-compose configuration
	docker-compose config

.PHONY: down
down: ## Clean up docker artefacts
	docker-compose down
	@-docker rmi gpg_gpg
	docker system prune --volumes --force

命令

生成钥匙

它创建公钥和私钥,然后将它们备份到/data/ 文件夹中。创建的文件是private.keypublic.key

$ make gen-key

> GENERATE KEYS (begin) --------------------------
Set local variables
done
Prepare configuration file
done
Create gpg directory and get into it
gpg: directory /root/.gnupg created
gpg: keybox /root/.gnupg/pubring.kbx created
gpg: /root/.gnupg/trustdb.gpg: trustdb created
Generate keys
gpg: no running gpg-agent - starting /usr/bin/gpg-agent
gpg: waiting for the agent to come up ... (5s)
gpg: connection to agent established
gpg: writing self signature
gpg: RSA/SHA512 signature from: "FFB8195B9A6E634C [?]"
gpg: writing key binding signature
gpg: RSA/SHA512 signature from: "FFB8195B9A6E634C [?]"
gpg: RSA/SHA512 signature from: "EAB3A38FBCEDC2CB [?]"
gpg: writing public key to /root/.gnupg/pubring.kbx
gpg: using pgp trust model
gpg: directory /root/.gnupg/openpgp-revocs.d created
gpg: writing to /root/.gnupg/openpgp-revocs.d/4AF187A975C16AA53E8DE0FAFFB8195B9A6E634C.rev
gpg: RSA/SHA512 signature from: "FFB8195B9A6E634C Continuous Integration and Delivery (CI/CD use only) <cicd@example.com>"
gpg: revocation certificate stored as /root/.gnupg/openpgp-revocs.d/4AF187A975C16AA53E8DE0FAFFB8195B9A6E634C.rev
Backup public and private keys
done
Cleanup
done
> GENERATE KEYS (end) ----------------------------

加密密钥

它对/data/msg-to-encrypt.txt 文件内容进行加密并创建/data/encrypted-msg.txt 文件。如果你想,这是唯一被CI运行的命令。在这种情况下,你应该在enc_msg() 函数中用--output - 替换--output ${ENCRYPTED_MSG} 来输出加密的字符串。

$ make enc-msg

> ENCRYPT MESSAGE (begin) ------------------------
Set local variables
done
Create gpg directory and get into it
gpg: directory /root/.gnupg created
gpg: keybox /root/.gnupg/pubring.kbx created
gpg: /root/.gnupg/trustdb.gpg: trustdb created
Restore public key
gpg: key FFB8195B9A6E634C: public key "Continuous Integration and Delivery (CI/CD use only) <cicd@example.com>" imported
gpg: Total number processed: 1
gpg:               imported: 1
Restore private key
gpg: key FFB8195B9A6E634C: "Continuous Integration and Delivery (CI/CD use only) <cicd@example.com>" not changed
gpg: key FFB8195B9A6E634C: secret key imported
gpg: Total number processed: 1
gpg:              unchanged: 1
gpg:       secret keys read: 1
gpg:   secret keys imported: 1
Auto trust and verify keys
gpg (GnuPG) 2.2.35; Copyright (C) 2022 g10 Code GmbH
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Secret key is available.

sec  rsa2048/FFB8195B9A6E634C
     created: 2022-06-04  expires: never       usage: SCEA
     trust: unknown       validity: unknown
ssb  rsa2048/EAB3A38FBCEDC2CB
     created: 2022-06-04  expires: never       usage: SEA
[ unknown] (1). Continuous Integration and Delivery (CI/CD use only) <cicd@example.com>

sec  rsa2048/FFB8195B9A6E634C
     created: 2022-06-04  expires: never       usage: SCEA
     trust: unknown       validity: unknown
ssb  rsa2048/EAB3A38FBCEDC2CB
     created: 2022-06-04  expires: never       usage: SEA
[ unknown] (1). Continuous Integration and Delivery (CI/CD use only) <cicd@example.com>

Please decide how far you trust this user to correctly verify other users keys
(by looking at passports, checking fingerprints from different sources, etc.)

  1 = I dont know or wont say
  2 = I do NOT trust
  3 = I trust marginally
  4 = I trust fully
  5 = I trust ultimately
  m = back to the main menu


sec  rsa2048/FFB8195B9A6E634C
     created: 2022-06-04  expires: never       usage: SCEA
     trust: ultimate      validity: unknown
ssb  rsa2048/EAB3A38FBCEDC2CB
     created: 2022-06-04  expires: never       usage: SEA
[ unknown] (1). Continuous Integration and Delivery (CI/CD use only) <cicd@example.com>
Please note that the shown key validity is not necessarily correct
unless you restart the program.


sec  rsa2048/FFB8195B9A6E634C
     created: 2022-06-04  expires: never       usage: SCEA
     trust: ultimate      validity: unknown
ssb  rsa2048/EAB3A38FBCEDC2CB
     created: 2022-06-04  expires: never       usage: SEA
[ unknown] (1). Continuous Integration and Delivery (CI/CD use only) <cicd@example.com>

Encrypt message
gpg: checking the trustdb
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
done
Cleanup
done
> ENCRYPT MESSAGE (end) --------------------------

解密密钥

它解密/data/encrypted-msg.txt 文件内容并创建/data/decrypted-msg.txt 文件。

$ make dec-msg

> DECRYPT MESSAGE (begin) ------------------------
Set local variables
done
Create gpg directory and get into it
gpg: directory /root/.gnupg created
gpg: keybox /root/.gnupg/pubring.kbx created
gpg: /root/.gnupg/trustdb.gpg: trustdb created
Restore public key
gpg: key FFB8195B9A6E634C: public key "Continuous Integration and Delivery (CI/CD use only) <cicd@example.com>" imported
gpg: Total number processed: 1
gpg:               imported: 1
Restore private key
gpg: key FFB8195B9A6E634C: "Continuous Integration and Delivery (CI/CD use only) <cicd@example.com>" not changed
gpg: key FFB8195B9A6E634C: secret key imported
gpg: Total number processed: 1
gpg:              unchanged: 1
gpg:       secret keys read: 1
gpg:   secret keys imported: 1
Decrypt message
gpg: encrypted with 2048-bit RSA key, ID EAB3A38FBCEDC2CB, created 2022-06-04
      "Continuous Integration and Delivery (CI/CD use only) <cicd@example.com>"
gpg: Signature made Sat Jun  4 11:04:54 2022 UTC
gpg:                using RSA key 3535B47B7109B7CE4283DC47EAB3A38FBCEDC2CB
gpg: Good signature from "Continuous Integration and Delivery (CI/CD use only) <cicd@example.com>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
Primary key fingerprint: 4AF1 87A9 75C1 6AA5 3E8D  E0FA FFB8 195B 9A6E 634C
     Subkey fingerprint: 3535 B47B 7109 B7CE 4283  DC47 EAB3 A38F BCED C2CB
Cleanup
done
> DECRYPT MESSAGE (end) --------------------------