CloudWatch エージェントでログファイルを収集する際にはパーミッションにご注意

CloudWatch エージェントでログファイルを収集する際にはパーミッションにご注意

Clock Icon2024.08.19

こんにちは。テクニカルサポートチームのShiinaです。

はじめに

Linux の EC2 インスタンスで CloudWatch エージェントを利用してログファイルの収集しようとしたところ、パーミッションの問題でログが収集できないことがありました。

困っていた事象

CloudWatch エージェントでログファイルを収集するようにセットアップしてみたものの、ログファイルに出力されたログメッセージが CloudWatchLogs ロググループにログが転送されていませんでした。

(例)エージェント設定ファイル
       (中略)
       "logs": {
                "logs_collected": {
                        "files": {
                                "collect_list": [
                                        {
                                                "file_path": "/opt/script/*",
                                                "log_group_class": "STANDARD",
                                                "log_group_name": "script",
                                                "log_stream_name": "{instance_id}",
                                                "retention_in_days": -1
                                        },
                                        {
                                                "file_path": "/var/log/messages",
                                                "log_group_class": "STANDARD",
                                                "log_group_name": "messages",
                                                "log_stream_name": "{instance_id}",
                                                "retention_in_days": -1
                                        }
                                ]
                        }
                }
        },
        (中略)

結論

CloudWatch エージェントでは run_as_user にて指定されたユーザが収集するログファイルの読み取り権限 (r) 許可と、ログファイルのパス内のすべてのディレクトリに対する実行権限 (x) 許可が必要です。

ユーザが cwagent となっている場合、ログファイルおよびディレクトリに対する権限が不足している可能性が高いです。

run_as_user はエージェント設定ファイルで指定することができます。

CloudWatch エージェントをインストールする際に、エージェント設定ファイルウィザード (amazon-cloudwatch-agent-config-wizard) を利用してセットアップした場合、run_as_user のユーザがデフォルト値は cwagent となっています。

Which user are you planning to run the agent?
1. cwagent
2. root
3. others
default choice: [1]:

トラブルシューティング

CloudWatch エージェントのログを確認することでトラブルシューティングに役立つことがあります。

/opt/aws/amazon-cloudwatch-agent/logs/amazon-cloudwatch-agent.log
2024-08-19T00:24:52Z I! creating new logs agent
2024-08-19T00:24:52Z I! [logagent] starting
2024-08-19T00:24:52Z I! [logagent] found plugin cloudwatchlogs is a log backend
2024-08-19T00:24:52Z I! [logagent] found plugin logfile is a log collection
2024-08-19T00:24:52Z I! [logagent] start logs plugin file paths [/opt/script/* /var/log/messages]
2024-08-19T00:24:52Z I! [inputs.logfile] turned on logs plugin
2024-08-19T00:24:53Z E! [inputs.logfile] Failed to tail file /var/log/messages with error: open /var/log/messages: permission denied

/var/log/messages に対しては permission denied というエラーメッセージが出力がありました。

しかしながら、/opt/script/* に対するエラーメッセージは特にないようでした。

読み取り権限不足

例に挙げた /var/log/messages のログは一般的に所有ユーザ、所有グループが root root となっていて、他ユーザーに対しては読み取り/実行は許可されていません。

ls -l /var/log/messages

-rw-------. 1 root root 2127064 Aug 15 23:46 /var/log/messages

上記のようなファイルに対しては読み取り権限を与える必要があります。

ファイルに読み取り権限を与えてみます。

sudo chmod o+r /var/log/messages

ログが転送されるようになりました。
image

ログローテーションされているファイル場合はローテション後も権限を維持させるために logrotate の設定変更も必要です。

604のパーミッションを追加してみます。

/etc/logrotate.d/rsyslog
var/log/cron
/var/log/maillog
/var/log/messages
/var/log/secure
/var/log/spooler
{
    missingok
    sharedscripts
    create 0604 root root
    postrotate
        /usr/bin/systemctl kill -s HUP rsyslog.service >/dev/null 2>&1 || true
    endscript
}

一度、デバックモードで確認します。

sudo logrotate -d /etc/logrotate.d/rsyslog

WARNING: logrotate in debug mode does nothing except printing debug messages!  Consider using verbose mode (-v) instead if this is not what you want.

reading config file /etc/logrotate.d/rsyslog
Reading state from file: /var/lib/logrotate/logrotate.status
Allocating hash table for state file, size 64 entries
Creating new state
Creating new state
Creating new state
Creating new state
Creating new state
Creating new state
Creating new state
Creating new state
Creating new state
Creating new state
Creating new state
Creating new state
Creating new state

Handling 1 logs

rotating pattern: /var/log/cron
/var/log/maillog
/var/log/messages
/var/log/secure
/var/log/spooler
 1048576 bytes (no old logs will be kept)
empty log files are rotated, old logs are removed
considering log /var/log/cron
  log /var/log/cron does not exist -- skipping
considering log /var/log/maillog
  Now: 2024-08-19 04:17
  Last rotated at 2024-08-14 02:00
  log does not need rotating (log size is below the 'size' threshold)
considering log /var/log/messages
  Now: 2024-08-19 04:17
  Last rotated at 2024-08-14 02:00
  log needs rotating
considering log /var/log/secure
  Now: 2024-08-19 04:17
  Last rotated at 2024-08-14 02:00
  log does not need rotating (log size is below the 'size' threshold)
considering log /var/log/spooler
  Now: 2024-08-19 04:17
  Last rotated at 2024-08-14 02:00
  log does not need rotating (log size is below the 'size' threshold)
rotating log /var/log/messages, log->rotateCount is 0
dateext suffix '-20240819'
glob pattern '-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'
set default create context to system_u:object_r:var_log_t:s0
renaming /var/log/messages.1 to /var/log/messages.2 (rotatecount 1, logstart 1, i 1),
renaming /var/log/messages.0 to /var/log/messages.1 (rotatecount 1, logstart 1, i 0),
log /var/log/messages.2 doesn't exist -- won't try to dispose of it
set default create context to system_u:object_r:var_log_t:s0
renaming /var/log/messages to /var/log/messages.1
disposeName will be /var/log/messages.1
creating new /var/log/messages mode = 0604 uid = 0 gid = 0
running postrotate script
running script with args /var/log/cron
/var/log/maillog
/var/log/messages
/var/log/secure
/var/log/spooler
 : "
        /usr/bin/systemctl kill -s HUP rsyslog.service >/dev/null 2>&1 || true
"
removing old log /var/log/messages.1

強制的にログローテションしてみます。


sudo logrotate -f /etc/logrotate.d/rsyslog

再度 /var/log/messages の権限を確認します。

ls -l messages

-rw----r--. 1 root root 3894 Aug 19 04:20 messages

ログローテーション後も権限が外れないことを確認できました。

ディレクトリ実行権限不足

例に挙げた /opt/script/* は /opt/scirpt ディレクトリに対しては他のユーザに対して実行権限が許可されていませんでした。

namei コマンドを利用すると、権限情報を確認することができます。

namei -m /opt/script/20240819.log

f: /opt/script/20240819.log
 dr-xr-xr-x /
 drwxr-xr-x opt
 drwxr-xr-- script
 -rw-r--r-- 20240819.log

上記のようなディレクトリに対しては実行権限を与える必要があります。
実行権限は見落としやすいのでお気をつけください!

ディレクトリに実行権限を与えてみます。

sudo chmod o+rx /opt/script/

image (1)

ログが転送されるようになりました。

CloudWatch エージェントユーザ変更

特権の最小化の観点からすると、ログファイルに適切なパーミッションを与える方が好ましいとは思いますが、 CloudWatch エージェントユーザを root へ変更する方法でも対処可能です。

run_as_user を cwagent から root ユーザーへ変更してみます。

1)エージェント設定ファイルの確認します。

CloudWatch エージェントのセットアップ方法によってエージェント設定ファイルのパスが異なります。

  • ウィザード利用してエージェント設定ファイルを作成した場合
/opt/aws/amazon-cloudwatch-agent/bin/config.json
  • 手動でエージェント設定ファイルを作成した場合
/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json

2)エージェント設定ファイルを次のように編集して保存します。

"run_as_user": "cwagent" を "run_as_user": "root" に変更します。

/opt/aws/amazon-cloudwatch-agent/bin/config.json
(中略)

"agent": {

"metrics_collection_interval": 60,

"run_as_user": "root"

},

(中略)

3)エージェント設定ファイルのフェッチと CloudWatch エージェント再起動を行います。

  • ウィザード利用してエージェント設定ファイルを作成した場合
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -s -c file:/opt/aws/amazon-cloudwatch-agent/bin/config.json
  • 手動でエージェント設定ファイルを作成した場合
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -s -c file:/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -s -c file:/opt/aws/amazon-cloudwatch-agent/bin/config.json

****** processing amazon-cloudwatch-agent ******
I! Trying to detect region from ec2 D! [EC2] Found active network interface I! imds retry client will retry 1 timesSuccessfully fetched the config and saved in /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.d/file_config.json.tmp
Start configuration validation...
2024/08/14 08:52:42 Reading json config file path: /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.d/file_config.json.tmp ...
2024/08/14 08:52:42 I! Valid Json input schema.
2024/08/14 08:52:42 D! ec2tagger processor required because append_dimensions is set
2024/08/14 08:52:42 Configuration validation first phase succeeded
I! Detecting run_as_user...
I! Trying to detect region from ec2
D! [EC2] Found active network interface
I! imds retry client will retry 1 times
/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent -schematest -config /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.toml
Configuration validation second phase succeeded
Configuration validation succeeded

再起動すると、ユーザが反映されてログが転送されるようになります。

まとめ

CloudWatch でログファイルを収集する場合はログファイルの読み取り権限 (r) 許可と、ログファイルのパス内のすべてのディレクトリに対する実行権限 (x) 許可が必要です。

最後までご覧いただきありがとうございました。

本記事が誰かのお役に立てれば幸いです。

参考

https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/CloudWatch-Agent-Configuration-File-Details.html#CloudWatch-Agent-Configuration-File-Agentsection

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.