Compare commits
No commits in common. "master" and "feature/cleandoc" have entirely different histories.
master
...
feature/cl
13 changed files with 11 additions and 202 deletions
18
.drone.yml
18
.drone.yml
|
@ -25,9 +25,9 @@ steps:
|
|||
commands:
|
||||
- cargo build --release
|
||||
- mkdir coffer-${DRONE_TAG}-x86_64-musl
|
||||
- mv target/x86_64-unknown-linux-musl/release/coffer-server
|
||||
target/x86_64-unknown-linux-musl/release/coffer-client
|
||||
target/x86_64-unknown-linux-musl/release/coffer-companion
|
||||
- mv target/x86_64-unknown-linux-musl/release/coffer-server \
|
||||
target/x86_64-unknown-linux-musl/release/coffer-client \
|
||||
target/x86_64-unknown-linux-musl/release/coffer-companion \
|
||||
coffer-${DRONE_TAG}-x86_64-musl
|
||||
- strip coffer-${DRONE_TAG}-x86_64-musl/coffer-server
|
||||
- strip coffer-${DRONE_TAG}-x86_64-musl/coffer-client
|
||||
|
@ -36,13 +36,13 @@ steps:
|
|||
- name: package
|
||||
image: alpine
|
||||
commands:
|
||||
- tar cjf coffer-${DRONE_TAG}-x86_64-musl.tar.bz2
|
||||
coffer-${DRONE_TAG}-x86_64-musl/coffer-server
|
||||
coffer-${DRONE_TAG}-x86_64-musl/coffer-client
|
||||
- tar cjf coffer-${DRONE_TAG}-x86_64-musl.tar.bz2 \
|
||||
coffer-${DRONE_TAG}-x86_64-musl/coffer-server \
|
||||
coffer-${DRONE_TAG}-x86_64-musl/coffer-client \
|
||||
coffer-${DRONE_TAG}-x86_64-musl/coffer-companion
|
||||
- tar czf coffer-${DRONE_TAG}-x86_64-musl.tar.gz
|
||||
coffer-${DRONE_TAG}-x86_64-musl/coffer-server
|
||||
coffer-${DRONE_TAG}-x86_64-musl/coffer-client
|
||||
- tar czf coffer-${DRONE_TAG}-x86_64-musl.tar.gz \
|
||||
coffer-${DRONE_TAG}-x86_64-musl/coffer-server \
|
||||
coffer-${DRONE_TAG}-x86_64-musl/coffer-client \
|
||||
coffer-${DRONE_TAG}-x86_64-musl/coffer-companion
|
||||
|
||||
- name: publish
|
||||
|
|
2
.gitattributes
vendored
2
.gitattributes
vendored
|
@ -2,5 +2,3 @@
|
|||
*.cert filter=lfs diff=lfs merge=lfs -text
|
||||
overview.png filter=lfs diff=lfs merge=lfs -text
|
||||
overview.svg filter=lfs diff=lfs merge=lfs -text
|
||||
coffer-client filter=lfs diff=lfs merge=lfs -text
|
||||
coffer-server filter=lfs diff=lfs merge=lfs -text
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Coffer
|
||||
[![Build Status](https://drone.friedl.net/api/badges/incubator/coffer/status.svg?ref=refs/heads/develop)](https://drone.friedl.net/incubator/coffer)
|
||||
[![Build Status](https://drone.friedl.net/api/badges/incubator/coffer/status.svg)](https://drone.friedl.net/incubator/coffer)
|
||||
|
||||
Coffer is a collection of tools for the simple but secure management of
|
||||
application configuration.
|
||||
|
@ -68,7 +68,7 @@ certificates are distributed and kept secret according to your threat model. An
|
|||
attacker in control of a certificate can steal secret configuration!
|
||||
|
||||
Coffer does not assume a trust anchor for you. Instead, you are free to choose
|
||||
your own trust anchor. In a simple personal server setup this might
|
||||
your own trust anchor according. In a simple personal server setup this might
|
||||
mean just distributing certificates by hand. In a more complex, corporate
|
||||
environment you may want to set up a secure, central authority.
|
||||
|
||||
|
|
|
@ -1,124 +0,0 @@
|
|||
Here you can find a simple example on how to run coffer.
|
||||
|
||||
# Run the example
|
||||
|
||||
To run the example, simply execute:
|
||||
|
||||
```shell
|
||||
docker-compose up
|
||||
```
|
||||
|
||||
This should print out:
|
||||
|
||||
```shell
|
||||
@@@@@@@ @@@@@@ @@@@@@@@ @@@@@@@@ @@@@@@@@ @@@@@@@
|
||||
@@@@@@@@ @@@@@@@@ @@@@@@@@ @@@@@@@@ @@@@@@@@ @@@@@@@@
|
||||
!@@ @@! @@@ @@! @@! @@! @@! @@@
|
||||
!@! !@! @!@ !@! !@! !@! !@! @!@
|
||||
!@! @!@ !@! @!!!:! @!!!:! @!!!:! @!@!!@!
|
||||
!!! !@! !!! !!!!!: !!!!!: !!!!!: !!@!@!
|
||||
:!! !!: !!! !!: !!: !!: !!: :!!
|
||||
:!: :!: !:! :!: :!: :!: :!: !:!
|
||||
::: ::: ::::: :: :: :: :: :::: :: :::
|
||||
:: :: : : : : : : : :: :: : : :
|
||||
|
||||
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||
TERM=xterm
|
||||
container=podman
|
||||
HOSTNAME=f7a1614d8752
|
||||
HOME=/root
|
||||
CLIENT_SECRET=SECRETKEY
|
||||
client
|
||||
0
|
||||
```
|
||||
|
||||
Where `CLIENT_SECRET` is the secret set into the environment of `printenv` in
|
||||
the client. `printenv` is the coffer'ed process.
|
||||
|
||||
Note that if you connect to a shell in the client container you are not able to
|
||||
retrieve the secret. The secret _only_ exists in the environment of the
|
||||
coffer'ed process. It does not even exist in some parent process of the
|
||||
coffer'ed process, as coffer reaps itself while starting the sub-process. This
|
||||
is quite different from other alternatives that either set the secrets into the
|
||||
environment of the container, or into a volume on the container. Both of which
|
||||
are accessible (with more or less effort) from anyone that has access to the
|
||||
container.
|
||||
|
||||
Also note how the whole server container, despite being able to service hundreds
|
||||
of clients in parallel, uses less than 3 MB in total.
|
||||
|
||||
# Setup and Configuration
|
||||
In this example we create a [coffer server](server/Dockerfile) with some [client secrets](config.toml)
|
||||
and a simple [client container](client/Dockerfile). The container are built, run and connected a shared
|
||||
network via [docker-compose](docker-compose.yml).
|
||||
|
||||
Both, the client and the server, need a certificate. The client for
|
||||
authenticating with the server, and the server for decrypting the client
|
||||
secrets.
|
||||
|
||||
Certificates can be generated with:
|
||||
```shell
|
||||
coffer-companion certificate certificate.cert
|
||||
```
|
||||
|
||||
Furthermore, the secrets need to be authorized. Even though a coffer server can
|
||||
handle secrets for multiple clients, a client can only request its own secrets.
|
||||
Secrets retrieval is authorized by the public key of the client. You can get the
|
||||
public key by
|
||||
```shell
|
||||
coffer-companion info certificate.cert
|
||||
```
|
||||
|
||||
The public key must be put into the `id` section of a secret. For
|
||||
example, our [secrets](config.toml) contain a section like this:
|
||||
```toml
|
||||
[client]
|
||||
id = "452B0788D966059B21DB04FF37BC6161072B15EA2CDF88A5040FEEAB89D1143A"
|
||||
CLIENT_SECRET = "SECRETKEY"
|
||||
```
|
||||
|
||||
Finally, the promise of coffer is that certificates are the fundamental trust
|
||||
anchor. This also means they are the _only_ thing you have to care about for
|
||||
security of your secrets. Consequently, [secrets themselves are encrypted](server/config.enc)
|
||||
with the server certificate:
|
||||
```shell
|
||||
coffer-companion encrypt --certificate certificate.cert --out config.enc --yaml config.toml
|
||||
```
|
||||
|
||||
# Encoffering the client
|
||||
You may have noticed that the actual client program (`printenv`) is not run
|
||||
directly. Instead the [Dockerfile](client/Dockerfile) contains an entrypoint like this:
|
||||
```Dockerfile
|
||||
ENTRYPOINT ["coffer-client"]
|
||||
|
||||
CMD ["--certificate", "client.cert", \
|
||||
"--server-address", "server:9187", \
|
||||
"--", \
|
||||
"printenv"]
|
||||
```
|
||||
|
||||
The coffer client will connect to the server and retrieve its secrets.
|
||||
Afterwards it sets the secrets into the process environment and replaces its own
|
||||
process image with the coffer'ed command.
|
||||
|
||||
The major drawback of this approach is that you have to build your own images.
|
||||
If you want to coffer your own software this is probably only a minor
|
||||
inconvenience. For pre-build images like e.g. the official
|
||||
[postgres](https://hub.docker.com/_/postgres) image this means you have to
|
||||
derive your own image for and coffer the entrypoint. For postgres this might
|
||||
look like:
|
||||
```Dockerfile
|
||||
FROM postgres:12-alpine
|
||||
|
||||
COPY ./coffer-client /usr/local/bin
|
||||
COPY ./postgres.cert .
|
||||
|
||||
ENTRYPOINT ["coffer-client", \
|
||||
"--certificate", "postgres.cert",
|
||||
"--server-address", "server:9187",
|
||||
"--",
|
||||
"docker-entrypoint.sh"]
|
||||
|
||||
CMD ["postgres"]
|
||||
|
||||
```
|
|
@ -1,13 +0,0 @@
|
|||
FROM busybox
|
||||
|
||||
RUN mkdir -p /usr/local/bin
|
||||
|
||||
COPY ./coffer-client /usr/local/bin
|
||||
COPY ./client.cert .
|
||||
|
||||
ENTRYPOINT ["coffer-client"]
|
||||
|
||||
CMD ["--certificate", "client.cert", \
|
||||
"--server-address", "server:9187", \
|
||||
"--", \
|
||||
"printenv"]
|
BIN
example/client/client.cert
(Stored with Git LFS)
BIN
example/client/client.cert
(Stored with Git LFS)
Binary file not shown.
BIN
example/client/coffer-client
(Stored with Git LFS)
BIN
example/client/coffer-client
(Stored with Git LFS)
Binary file not shown.
|
@ -1,3 +0,0 @@
|
|||
[client]
|
||||
id = "452B0788D966059B21DB04FF37BC6161072B15EA2CDF88A5040FEEAB89D1143A"
|
||||
CLIENT_SECRET = "SECRETKEY"
|
|
@ -1,21 +0,0 @@
|
|||
version: "3"
|
||||
|
||||
services:
|
||||
server:
|
||||
container_name: server
|
||||
build:
|
||||
context: ./server/
|
||||
networks:
|
||||
- coffer
|
||||
|
||||
client:
|
||||
container_name: client
|
||||
build:
|
||||
context: ./client/
|
||||
networks:
|
||||
- coffer
|
||||
depends_on:
|
||||
- server
|
||||
|
||||
networks:
|
||||
coffer:
|
|
@ -1,13 +0,0 @@
|
|||
FROM gcr.io/distroless/static
|
||||
|
||||
COPY ./coffer-server .
|
||||
COPY ./server.cert .
|
||||
COPY ./config.enc .
|
||||
|
||||
|
||||
EXPOSE 9187
|
||||
ENTRYPOINT ["./coffer-server"]
|
||||
|
||||
CMD ["--certificate", "server.cert", \
|
||||
"--secrets", "config.enc", \
|
||||
"--address", "0.0.0.0:9187"]
|
BIN
example/server/coffer-server
(Stored with Git LFS)
BIN
example/server/coffer-server
(Stored with Git LFS)
Binary file not shown.
BIN
example/server/config.enc
(Stored with Git LFS)
BIN
example/server/config.enc
(Stored with Git LFS)
Binary file not shown.
BIN
example/server/server.cert
(Stored with Git LFS)
BIN
example/server/server.cert
(Stored with Git LFS)
Binary file not shown.
Loading…
Reference in a new issue