Tommy Skaug
a4adbc2b1c
All checks were successful
Export / Explore-GitHub-Actions (push) Successful in 34s
195 lines
No EOL
5.9 KiB
Markdown
195 lines
No EOL
5.9 KiB
Markdown
## Key Takeaways
|
|
|
|
* Organisations should focus on defendable infrastructure
|
|
to enable efficient security monitoring. This requires
|
|
using reverse proxies, software-defined networking, a
|
|
well-defined and flexible architecture.
|
|
|
|
* We can add the LimaCharlie Adapter in file-mode
|
|
to stream JSON logs to limacharlie.io for
|
|
centralized and actionable logging (free to test).
|
|
|
|
* Infrastructure as Config/Code enables templating so
|
|
that the setup can be re-used across applications and
|
|
saves a lot of engineering time.
|
|
|
|
|
|
## Background
|
|
|
|
Yesterday I published a post about how I'm moving from
|
|
OpenBSD to Docker for my Matrix Dendrite setup. At the same
|
|
time I reshaped the infrastructure delivering Dendrite
|
|
to take advantage of the reverse proxying capabilities
|
|
in Traefik.
|
|
|
|
One of the major advantages of moving to Docker is that
|
|
it facilitates security monitoring in a better way than
|
|
OpenBSD. This mostly has to do with vendor support and
|
|
the fact that OpenBSD does things differently.
|
|
|
|
Within security monitoring, centralized logging with
|
|
[LimaCharlie Adapters](https://doc.limacharlie.io/docs/documentation/73a613e8e43ed-lima-charlie-adapter)
|
|
is a good option, which is what I wanted to share a
|
|
simple example of here.
|
|
|
|
Please note that this is simplistic in design, since the
|
|
rig I'm building for doesn't have much activity. If
|
|
I were building the monitoring setup for e.g. Kubernetes
|
|
I would need to take into consideration that there will
|
|
be multiple containers moving around, distributed file
|
|
storage etc.
|
|
|
|
I'm separating containers by duty. It will probably bring
|
|
a little extra overhead over using centralized storage or
|
|
an embedded adapter with stdout-streaming per container.
|
|
|
|
Let's keep the rest of this article short and sweet.
|
|
|
|
## The Configuration
|
|
|
|
First we need to add the following [`accessLog` labels to traefik](https://doc.traefik.io/traefik/observability/access-logs/)
|
|
in our Docker Compose:
|
|
|
|
```
|
|
[...]
|
|
reverse-proxy:
|
|
[...]
|
|
command:
|
|
[...]
|
|
- --accessLog.filePath=/var/log/traefik/access.log
|
|
- --accessLog.format=json
|
|
volumes:
|
|
[...]
|
|
- ./data/traefik:/var/log/traefik
|
|
[...]
|
|
[...]
|
|
```
|
|
|
|
This will write logs to `./data/traefik` outside Docker. We'll
|
|
share the same directory with the LimaCharlie Adapter. For this
|
|
purpose we'll configure the adapter to run in `file-mode`. In a
|
|
more demanding configuration I would consider using `stdin-mode`.
|
|
|
|
There's an example in the LimaCharlie docs of how to use the
|
|
[adapter in Docker with syslog](https://doc.limacharlie.io/docs/documentation/73a613e8e43ed-lima-charlie-adapter#syslog). We can also run the
|
|
following to get the file configuration options:
|
|
|
|
```sh
|
|
$ docker run --rm -it -p 4444:4444 refractionpoint/lc-adapter:latest
|
|
|
|
For file
|
|
----------------------------------
|
|
client_options.identity.oid
|
|
client_options.identity.installation_key
|
|
client_options.hostname
|
|
client_options.platform
|
|
client_options.architecture
|
|
client_options.mapping.parsing_re
|
|
client_options.mapping.sensor_key_path
|
|
client_options.mapping.sensor_hostname_path
|
|
client_options.mapping.event_type_path
|
|
client_options.mapping.event_time_path
|
|
client_options.mapping.rename_only
|
|
client_options.mapping.mappings
|
|
client_options.mappings
|
|
client_options.indexing
|
|
client_options.is_compressed
|
|
client_options.sensor_seed_key
|
|
client_options.dest_url
|
|
write_timeout_sec
|
|
file_path
|
|
no_follow
|
|
```
|
|
|
|
Having a look at `data/traefik/access.log`, we find that Traefik
|
|
has the following pattern:
|
|
|
|
```json
|
|
{
|
|
"ClientAddr": "[IP]:[PORT]",
|
|
"ClientHost": "[IP]",
|
|
"ClientPort": "[PORT]",
|
|
"ClientUsername": "-",
|
|
"DownstreamContentSize": 105,
|
|
"DownstreamStatus": 200,
|
|
"Duration": 30012385827,
|
|
"OriginContentSize": 105,
|
|
"OriginDuration": 30012309833,
|
|
"OriginStatus": 200,
|
|
"Overhead": 75994,
|
|
"RequestAddr": "matrix.{{tailnet-id}}.ts.net",
|
|
"RequestContentSize": 0,
|
|
"RequestCount": 5,
|
|
"RequestHost": "matrix.{{tailnet-id}}.ts.net",
|
|
"RequestMethod": "GET",
|
|
"RequestPath": "/_matrix/client/r0/sync?[...]",
|
|
"RequestPort": "-",
|
|
"RequestProtocol": "HTTP/2.0",
|
|
"RequestScheme": "https",
|
|
"RetryAttempts": 0,
|
|
"RouterName": "web@docker",
|
|
"ServiceAddr": "[IP]:[PORT]",
|
|
"ServiceName": "dendrite-docker-matrix@docker",
|
|
"ServiceURL": "http://[IP]:[PORT]",
|
|
"StartLocal": "2023-04-25T08:06:12.121010341Z",
|
|
"StartUTC": "2023-04-25T08:06:12.121010341Z",
|
|
"TLSCipher": "TLS_AES_128_GCM_SHA256",
|
|
"TLSVersion": "1.3",
|
|
"entryPointName": "client",
|
|
"level": "info",
|
|
"msg": "",
|
|
"time": "2023-04-25T08:06:42Z"
|
|
}```
|
|
|
|
This won't matter for getting basic logging up and running as
|
|
we can use the adapter in JSON mode as follows:
|
|
|
|
```sh
|
|
docker run --rm \
|
|
-v ./data/traefik/access.log:/logs/traefik/access.log \
|
|
refractionpoint/lc-adapter:latest file \
|
|
file_path=/logs/traefik/access.log \
|
|
client_options.identity.installation_key={{ADAPTER INSTALL. KEY}} \
|
|
client_options.identity.oid={{limacharlie.io ORG ID}} \
|
|
client_options.hostname=traefik-ts-dendrite \
|
|
client_options.sensor_seed_key=traefik-ts-dendrite \
|
|
client_options.platform=json
|
|
```
|
|
|
|
And voilà, our adapter is streaming to our organisation
|
|
(synonym to "tenant") at limacharlie.io.
|
|
|
|
To make it permanent, we convert the `docker` command to
|
|
`docker-compose` and end up with:
|
|
|
|
```docker-compose
|
|
version: '3.3'
|
|
services:
|
|
traefik-lc-adapter:
|
|
image: refractionpoint/lc-adapter:latest
|
|
command:
|
|
- file
|
|
- file_path=/logs/traefik/access.log
|
|
- client_options.identity.installation_key=$LC_INSTALLATION_KEY
|
|
- client_options.identity.oid=$LC_ORG_ID
|
|
- client_options.hostname=$LC_HOSTNAME
|
|
- client_options.sensor_seed_key=$LC_HOSTNAME
|
|
- client_options.platform=json
|
|
restart: unless-stopped
|
|
environment:
|
|
TZ: UTC
|
|
env_file:
|
|
- ./config/limacharlie/.limacharlie_env
|
|
volumes:
|
|
- './data/traefik/access.log:/logs/traefik/access.log'
|
|
```
|
|
|
|
Add keys to environment file in `.env`:
|
|
|
|
```sh
|
|
LC_INSTALLATION_KEY={{ADAPTER INSTALLATION KEY}}
|
|
LC_ORG_ID={{limacharlie.io ORG ID}}
|
|
LC_HOSTNAME=traefik-ts-dendrite
|
|
```
|
|
|
|
Easy as that. |