Skip to content

Commit

Permalink
Work in progress
Browse files Browse the repository at this point in the history
  • Loading branch information
amousset committed Dec 13, 2020
1 parent e65824b commit a58f5fa
Show file tree
Hide file tree
Showing 27 changed files with 12,365 additions and 0 deletions.
3 changes: 3 additions & 0 deletions docker/.vscode/settings.json
@@ -0,0 +1,3 @@
{
"python.pythonPath": "/usr/bin/python3"
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
38 changes: 38 additions & 0 deletions docker/rudder-relay/Dockerfile
@@ -0,0 +1,38 @@
FROM centos:8

COPY \
# https://github.com/gdraheim/docker-systemctl-replacement/blob/1bb5768abbf68245b7b6a8bd9d6ac4df4d78044f/files/docker/systemctl3.py
systemctl3.py /usr/bin/systemctl

RUN \
yum -y install curl && \
curl --silent --output rudder-setup https://repository.rudder.io/tools/rudder-setup && \
sh rudder-setup add-repository 6.2 && \
yum -y install rudder-server-relay

RUN \
# In case something goes wrong
sed -i '1 a set -x' /opt/rudder/share/commands/agent-check

RUN \
# Symbolic links to persisted files
mkdir /rudder && \
ln -sf /rudder/uuid.hive /opt/rudder/etc/uuid.hive && \
ln -sf /rudder/agent.cert /opt/rudder/etc/ssl/agent.cert && \
ln -sf /rudder/localhost.priv /var/rudder/cfengine-community/ppkeys/localhost.priv && \
ln -sf /rudder/localhost.pub /var/rudder/cfengine-community/ppkeys/localhost.pub && \
ln -sf /rudder/policy_server_hash /var/rudder/cfengine-community/ppkeys/policy_server_hash && \
ln -sf /rudder/policy_server.dat /var/rudder/cfengine-community/policy_server.dat

COPY \
rudder-relay.sh .

RUN \
yum clean all && \
rm -rf /var/rudder/cfengine-community/state/*
# TODO reset bootstrap policies

CMD ["./rudder-relay.sh"]


EXPOSE 443 5309
88 changes: 88 additions & 0 deletions docker/rudder-relay/README.adoc
@@ -0,0 +1,88 @@
= relay

== Summary

These containers provide a full Rudder relay running in unprivileged
read-only containers.

Each service runs in its own container.

The relay is almost stateless and the only data that needs to be persisted are:

* Agent id and key pair
* HTTP server key pair

Everything else can be rebuilt dynamically.

The containers are:

* `cf-execd`: runs the agent every 5 minutes. In this context, it is actually only used as a data bus
in the form of an rsync for data files, shared with other containers. Applying other policies is not supported.
* `cf-serverd`: its mains role is to serve policy files (and other data files) to managed Unix nodes.
It can also be used to trigger an agent run through remote-run (in this case it runs an agent
to sync the data files).
* `httpd`: acts as HTTPS endpoint, reverse proxy and network security layer
* `relayd`: runs the core logic of the relay

== Images

Images are currently based on CentOS 8 and install Rudder 6.1 using rudder-setup.

We use the standard packages (after disabling service management to allow
packaging scripts calls to systemctl to succeed), even for httpd as we rely on
changes made by our packaging scripts.

We need several tricks to workaround docker and Rudder limitations:

* To allow Rudder's packaging script to run correctly, we replace all service commands by `/bin/true` (in particular systemctl)
* We can't share a single file between containers, so when we need to share and persist some files
in a directory but not the others, we use a dedicated directory (namely `/agent_certs /node_id /httpd_conf /relayd_conf`)
* We can't use agent initialization because of that (as we need to use symlinks in place of generated files), so
the agent init (id ans key generation) is done by `cf-execd.sh`.
* We need dynamic configuration reload. It is usually done by the agent through systemctl, but to
replace it while limiting interactions between containers, we use inotify-based reload mechanism.
* As we need to use server-generated config that hardcodes 127.0.0.1 for local calls on the server
we dynamically edit the config at reload to use the container's name instead.

We need to minimize upgrade scripts, which requires only storing necessary data
in persistent volumes.

The volumes that should be persisted:

* agent_certs
* node_id
* httpd_certs

== Run a relay

We provide a docker-compose configuration example.

You need to modify the `policy_server.dat` file to set the right policy server.
You can also modify the relay's hostname (it is the `cf-execd`'s hostname),
to set the hostname you want to see on the Rudder server.

Then run:

----
docker-compose up
----

Accept the inventory, run `rudder server node-to-relay`. Everything
should be automatically applied from now. Remote run on the relay works too.

== TODO

* [ ] See where to configure policy server (inside or outside of the containers?)
* [ ] Upgrade procedure
* [ ] Logs management
* [ ] Random cf-execd/serverd start error?

In the long term:

* [ ] Replace current server role system by something simpler and configurable
to allow customizing lightening and destination host and port for each service
* [ ] Replace agent-based data sync with something HTTP based
* [ ] Replace (or re-implement in relayd) cf-serverd's file copy protocol
* [ ] Avoid the need for an agent totally and allow making a working relayd with
relayd and (maybe) httpd.

32 changes: 32 additions & 0 deletions docker/rudder-relay/docker-compose.yml
@@ -0,0 +1,32 @@
services:
toto:
volumes:
- "agent_state:/var/rudder/cfengine-community/"
- "policies_lib:/var/rudder/ncf"
- "policies_src_lib:/usr/share/ncf/tree"
- "policies_loc_lib:/var/rudder/configuration-repository/ncf"
- "policies:/var/rudder/share"
- "shared_folder:/var/rudder/configuration-repository/shared-files/"
- "httpd_certs:/opt/rudder/etc/ssl/"
- "httpd_conf:/httpd_conf"
- "relayd_conf:/relayd_conf/"
- "relayd_nodelist:/var/rudder/lib/relay/"
- "relayd_certs:/var/rudder/lib/ssl/"
- "shared_files:/var/rudder/shared-files/"
- "inventories:/var/rudder/inventories"
- "reports:/var/rudder/reports"
tmpfs:
- /var/rudder/tmp
- /var/rudder/modified-files
- /var/backup/rudder
- /opt/rudder/var/fusioninventory
- /var/rudder/inventories
- /var/rudder/reports
- /tmp
- /etc/cron.d
- /etc/logrotate.d
- /var/log
- /var/log/httpd
- /var/log/rudder/apache2
- /run/httpd
# /tmp/davlock.db
52 changes: 52 additions & 0 deletions docker/rudder-relay/rudder-relay.nomad
@@ -0,0 +1,52 @@
# Minimal example configuration

job "rudder" {
datacenters = ["dc1"]
type = "service"
group "cache" {
network {
port "https" {
to = 443
}
port "cfengine" {
to = 5309
}
}

service {
name = "rudder-relay"
tags = ["rudder"]
port = "https"

check {
name = "alive"
type = "tcp"
interval = "10s"
timeout = "2s"
}
}

task "rudder-relay" {
driver = "docker"

config {
# latest version
image = "amousset/rudder-relay:test1"
ports = ["https", "cfengine"]

hostname = "rudder-relay-01"

#readonly_rootfs = "true"

volumes = [
"rudder-relay-data:/rudder/"
]
}

resources {
cpu = 500 # 500 MHz
memory = 256 # 256MB
}
}
}
}
98 changes: 98 additions & 0 deletions docker/rudder-relay/rudder-relay.sh
@@ -0,0 +1,98 @@
#!/bin/bash

set -e
set -x

# Configurable with env variables:
#
# * RUDDER_RELAY_ID: agent id
# * RUDDER_RELAY_KEY: agent private key
# * RUDDER_RELAY_CERTIFICATE: agent certificate
# * RUDDER_RELAY_SERVER: hostname/IP of the server, default is "rudder"
# * RUDDER_RELAY_SERVER_HASH: hash of the relay's upstream key
#
# The id, keys and certificate can be persisted by making /rudder/ persistent
#
# The env variables have priority over persisted values.

# Allow using our binaries
export PATH="/opt/rudder/bin/:$PATH"

################
# Policy server
################

if [ -n "$RUDDER_RELAY_SERVER_HASH" ]; then
echo "$RUDDER_RELAY_SERVER_HASH" > /rudder/policy_server_hash
fi

if [ -n "$RUDDER_RELAY_SERVER" ]; then
echo "$RUDDER_RELAY_SERVER" > /rudder/policy_server.dat
elif [ ! -f /rudder/uuid.hive ]; then
echo "rudder" > /rudder/policy_server.dat
fi

################
# Relay node id
################

if [ -n "$RUDDER_RELAY_ID" ]; then
echo "$RUDDER_RELAY_ID" > /rudder/uuid.hive
elif [ ! -f /rudder/uuid.hive ]; then
rudder-uuidgen > /rudder/uuid.hive
fi

uuid=$(cat /rudder/uuid.hive)

################
# Private key
################

if [ -n "$RUDDER_RELAY_KEY" ]; then
(
echo "-----BEGIN RSA PRIVATE KEY-----"
echo "$RUDDER_RELAY_KEY" | fold -w 64
echo "-----END RSA PRIVATE KEY-----"
) > /agent_certs/localhost.priv
chmod 600 /agent_certs/localhost.priv
elif [ ! -f /agent_certs/localhost.priv ]; then
cf-key --key-type 4096 --output-file /rudder/localhost
fi

# Generate public key based on private key to be sure it's correct
openssl rsa -in /rudder/localhost.priv -RSAPublicKey_out > /rudder/localhost.pub

################
# Certificate
################

if [ -n "$RUDDER_RELAY_CERTIFICATE" ]; then
(
echo "-----BEGIN CERTIFICATE-----"
echo "$RUDDER_RELAY_CERTIFICATE" | fold -w 64
echo "-----END CERTIFICATE-----"
) > /rudder/agent.cert
elif [ ! -f /rudder/agent.cert ]; then
openssl req -new -sha256 -key /rudder/localhost.priv -out /rudder/agent.cert -passin "pass:Cfengine passphrase" -x509 -days 3650 -extensions agent_cert -config /opt/rudder/etc/ssl/openssl-agent.cnf -subj "/UID=${uuid}"
fi

# We verify that the certificate belongs to the private key (Modulus is identical)
modulus_cert=$(openssl x509 -noout -modulus -in /rudder/agent.cert)
modulus_key=$(openssl rsa -noout -modulus -passin "pass:Cfengine passphrase" -in /rudder/localhost.priv)
if [ "${modulus_cert}" != "${modulus_key}" ]; then
echo "Certificate does not match agent key" >&2
exit 1
fi

#############################

rudder agent check -f

# download policies first ?

systemctl start rudder-cf-execd rudder-cf-serverd httpd rudder-relayd

#/opt/rudder/bin/cf-execd --no-fork --inform &
#/opt/rudder/bin/cf-serverd --no-fork --inform &
#/usr/sbin/httpd -DFOREGROUND &
#/opt/rudder/bin/rudder-relayd

0 comments on commit a58f5fa

Please sign in to comment.