Carpe Diem

備忘録

HashiCorp VaultのAudit Devicesでオペレーションをロギング

概要

HashiCorp Vaultの売りは

  • Secure secret management
  • Dynamic secrets
  • Encryption as a Service
  • Leasing and Renewal

など多々ありますが、その中でもAudit(監査)ログ(Vaultの操作ログ)の管理はとても重要です。
今回はその設定を紹介します。

Audit Devices

公式では以下の3つの形式をサポートしています。

Audit Devices - Vault by HashiCorp

  • Syslog
  • File
  • Socket

ただこの中でも

  • SyslogはUDPのサイズ上限があるのでログが欠損する可能性がある
  • Socketはコネクションが切れた時にログが欠損する可能性がある

という問題がドキュメントにも書いてあるので、お薦めはFileです。

Vaultの設定

出力先

まずログの出力先を用意します。これの権限が無くて出力されない〜というエラーがよくあるので。

$ sudo mkdir -p /var/log/vault/
$ sudo chown vault: /var/log/vault 

Auditの有効化

file auditを有効化します。

$ vault audit enable -path="audit" file \
  file_path=/var/log/vault/vault_audit.log \
  hmac_accessor=false \
  mode=0644

hmac_accessor=falseにすることでtoken accessor(tokenのid)を生の値にし、漏洩が起きた時に検索しやすくしておきます。

どんなログが出るのか?

例えばvault list auth/aws/rolesを実行すると

{
  "time": "2018-07-31T04:50:03.466310969Z",
  "type": "request",
  "auth": {
    "client_token": "hmac-sha256:3a882f05f841e5b579695cbd23a5ba1312b4baa7defe6a400d49cd6c292df238",
    "accessor": "UfWW6oJYgqgr3beaWNSy9ynM",
    "display_name": "aws-tsuji_jumpei",
    "policies": [
      "admin",
      "default"
    ],
    "token_policies": [
      "admin",
      "default"
    ],
    "metadata": {
      "account_id": "664653893268",
      "auth_type": "iam",
      "canonical_arn": "arn:aws:iam::xxxx:user/tsuji_jumpei",
      "client_arn": "arn:aws:iam::xxxx:user/tsuji_jumpei",
      "client_user_id": "yyyyyyyyyyyyyyyyyyyy",
      "inferred_aws_region": "",
      "inferred_entity_id": "",
      "inferred_entity_type": ""
    },
    "entity_id": "d55cda33-4ded-2cd1-8712-a59d7ca1e55f"
  },
  "request": {
    "id": "6deccc9d-b6f9-0d02-84f9-ebff698f154e",
    "operation": "list",
    "client_token": "hmac-sha256:3a882f05f841e5b579695cbd23a5ba1312b4baa7defe6a400d49cd6c292df238",
    "client_token_accessor": "UfWW6oJYgqgr3beaWNSy9ynM",
    "path": "auth/aws/roles/",
    "data": null,
    "policy_override": false,
    "remote_address": "10.1.0.242",
    "wrap_ttl": 0,
    "headers": {}
  },
  "error": ""
}

といった感じでどのユーザがどういった操作をしたのかが分かります。

ポイント

  • ログはリクエストで1オブジェクト、レスポンスで1オブジェクト
  • authで認証した人(=操作した人)が分かる
  • request.operationでどんな操作をしたかが分かる
  • request.pathでどのデータにアクセスしたかが分かる
  • tokenのような重要な情報はデフォルトだとsha256でハッシュ化される
    • log_raw=trueにするとハッシュ化されなくなる

ログローテーション

fileログの問題点はログの肥大化に依るディスク容量の圧迫です。
これについては

christina04.hatenablog.com

で紹介したlogrotateを利用します。

設定ファイル

/etc/logrotate.d/vault

/var/log/vault/*.log {
        daily
        missingok
        rotate 52
        compress
        delaycompress
        notifempty
        create 644 vault vault
        sharedscripts
        postrotate
                [ -f /var/run/vault/vault.pid ] && kill -HUP `cat /var/run/vault/vault.pid`
        endscript
}

というファイルを用意します。

解説

SIGHUP

        postrotate
                [ -f /var/run/vault/vault.pid ] && kill -HUP `cat /var/run/vault/vault.pid`

vaultはSIGHUPシグナルを投げれば開き直してくれるので、ローテート後にシグナルを投げて新しいファイルを向くようにしています。

Sending a SIGHUP to the Vault process will cause file audit devices to close and re-open their underlying file, which can assist with log rotation needs.

ref: File - Audit Devices - Vault by HashiCorp

PID

上記では/var/run/vault/vault.pidを指定しています。
これはsystemdの設定と、vaultの設定でこのような形にしています。

systemdの設定

Vault High Availability with Consul | Vault - HashiCorp Learn を参考に以下のようなファイルを用意します。

### BEGIN INIT INFO
# Provides:          vault
# Required-Start:    $local_fs $remote_fs
# Required-Stop:     $local_fs $remote_fs
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Vault server
# Description:       Vault secret management tool
### END INIT INFO

[Unit]
Description=Vault secret management tool
Requires=network-online.target
After=network-online.target

[Service]
User=vault
Group=vault
PIDFile=/var/run/vault/vault.pid
PermissionsStartOnly=true
ExecStartPre=-/bin/mkdir -p /var/run/vault
ExecStartPre=/bin/chown -R vault:vault /var/run/vault
ExecStart=/usr/local/bin/vault server \
    -config=/usr/local/etc/vault/vault_server.hcl \
    -log-level=debug
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
KillSignal=SIGTERM
Restart=on-failure
RestartSec=42s
LimitMEMLOCK=infinity

[Install]
WantedBy=multi-user.target
vaultの設定

pid_fileというフィールドがあるのでそこを指定します。

storage "consul" {
  address = "127.0.0.1:8500"
  path    = "vault/"
}

listener "tcp" {
 address         = "0.0.0.0:8200"
 cluster_address = "10.1.42.202:8201"
}

disable_mlock = 1
pid_file = "/var/run/vault/vault.pid"

api_addr = "http://10.1.42.202:8200"
cluster_addr = "https://10.1.42.202:8201"

検証

$ logrotate -fv /etc/logrotate.d/vault

reading config file /etc/logrotate.d/vault

Handling 1 logs

rotating pattern: /var/log/vault/*.log  forced from command line (52 rotations)
empty log files are not rotated, old logs are removed

...

log /var/log/vault/vault_audit.log.53.gz doesn't exist -- won't try to dispose of it
renaming /var/log/vault/vault_audit.log to /var/log/vault/vault_audit.log.1
creating new /var/log/vault/vault_audit.log mode = 0644 uid = 1002 gid = 1002
running postrotate script

ちゃんと成功します。
ディレクトリを確認すると

$ ls /var/log/vault/
vault_audit.log  vault_audit.log.1

ローテートされてることが確認できました。

まとめ

Vaultの操作ログを出力するようにしました。
加えてfluentdなどでS3などに保管することでインスタンスが消えてもロストせずに済むように対応する必要があると思います。