Shipping ssh login events through OpenTelemetry

by Sebastien Mirolo on Wed, 18 Sep 2024

Following the failed experiment to ship OpenTelemetry events to GitLab, we embarked on a smaller project of creating an HTTP POST request on a homegrown service every time an engineer ssh into the Cloud infrastructure.

Configuring journald receiver

Most Linux systems record security events (including user login) through auditd and manage logs locally on the machine through journald.

We will thus look through the journald receiver documentation, and modify the configuration file to look for specific user login events.

/etc/otelcol-contrib/config.yaml
receivers:
  journald:
    directory: /var/log/journal
    priority: "7"
    matches:
      - _TRANSPORT: audit

exporters:
  debug:
    verbosity: normal
    use_internal_logger: false

service:

  pipelines:

    logs:
      receivers: [journald]
      exporters: [debug]
      

Let's make sure the otelcol-contrib user has access to the journal. Then that the collector service is running properly.

Terminal
$ sudo su -s /bin/bash -c 'journalctl --lines 5' otelcol-contrib
Hint: You are currently not seeing messages from other users and the system.
      Users in groups 'systemd-journal' can see all messages.
      Pass -q to turn off this notice.
No journal files were opened due to insufficient permissions.

$ sudo usermod -aG systemd-journal otelcol-contrib
$ sudo su -s /bin/bash -c 'journalctl --lines 5' otelcol-contrib
Sep 13 18:21:26 hostname ...

$ sudo systemctl start otelcol-contrib.service

$ ps auxwww|grep otel
otelcol-contrib    /usr/bin/otelcol-contrib --config=/etc/otelcol-contrib/config.yaml
otelcol-contrib    journalctl --utc --output=json --follow --unit ssh --priority info --directory /run/log/journal
      

Let's make sure something is showing up in the collector.

Terminal
$ sudo journalctl -S "5 min ago" -l _SYSTEMD_UNIT=otelcol-contrib.service  --no-pager
      

Filtering for messages we are interested in

First, let's investigate which events we can reliably depend on. Since all ssh connections will go through a bastion/sally machine, we will attempt to ssh to a machine through the bastion (ProxyJump) or ssh into the bastion directly.

SSH through JumpProxySSH into bastion
CRYPTO_KEY_USER res=success
CRYPTO_SESSION res=success
CRYPTO_SESSION res=success
USER_AUTH res=success
CRYPTO_KEY_USER res=success
USER_ACCT res=success
CRYPTO_KEY_USER res=success
CRED_ACQ res=success
USER_ROLE_CHANGE res=success
USER_START res=success
CRYPTO_KEY_USER res=success
CRED_ACQ res=success
CRYPTO_KEY_USER res=success
CRYPTO_SESSION res=success
CRYPTO_SESSION res=success
USER_AUTH res=success
CRYPTO_KEY_USER res=success
USER_ACCT res=success
CRYPTO_KEY_USER res=success
CRED_ACQ res=success
USER_ROLE_CHANGE res=success
USER_START res=success
CRYPTO_KEY_USER res=success
CRED_ACQ p res=success
USER_LOGIN res=success
USER_START res=success
CRYPTO_KEY_USER res=success
SERVICE_START res=success
SERVICE_START res=success
SERVICE_STOP res=success
SSH through JumpProxy / into bastion (invalid ssh key)
CRYPTO_KEY_USER res=success
CRYPTO_SESSION res=success
CRYPTO_SESSION res=success
USER_AUTH res=failed
CRYPTO_KEY_USER res=success
CRYPTO_KEY_USER res=success
USER_ERR res=failed
CRYPTO_KEY_USER res=success
USER_LOGIN res=failed

We will settle on filtering USER_START, more specifically PAM:session_open, log events only.

The otelco-contrib filter processor only has syntax to drop out records. We are interested in keeping (filter-in) specific log statements. So we will have to do so in the receiver instead.

/etc/otelcol-contrib/config.yaml
receivers:
  journald:
    directory: /var/log/journal
    priority: "7"
    matches:
      - _TRANSPORT: audit
    grep: "USER_START.*op=PAM:session_open"
...   

Exporting OpenTelemetry events through HTTP requests

At this point, we use the experience gathered earlier to configure the otlphttp exporter.

/etc/otelcol-contrib/config.yaml
...
exporters:
  otlphttp:
    logs_endpoint: https://example.com/api/events
    headers:
      Authorization: Bearer *****
      Content-Type: application/json
    encoding: json
    compression: none
      

Conclusion

OpenTelemetry plays a similar role to syslog and journalctl aggregation features. The philosophy is to push every events through unless it is actively dropped.

More to read

You might also like to read failed experiment to ship OpenTelemetry events to GitLab, Fast-tracking server errors to a log aggregator on S3, or Logging Docker containers output through journald to syslog.

More technical posts are also available on the DjaoDjin blog, as well as business lessons we learned running a SaaS application hosting platform.

We also came across these insightful posts from across the Web while doing research:

by Sebastien Mirolo on Wed, 18 Sep 2024


Receive news about DjaoDjin in your inbox.

Bring fully-featured SaaS products to production faster.

Follow us on