AWS IAM Roles Anywhereと証明書認証で実現するアクセスキー不要のIoTログ転送

水色の背景に六角形が2つあるイラスト 水色の背景に六角形が2つあるイラスト
アイキャッチ
目次

【アクセスキー不要】IoT・オンプレミス環境におけるAWS連携のセキュリティ課題

近年、IoT機器やエッジデバイスから収集したログをクラウドに転送し、分析や監視に活用するケースが増えています。しかし、デバイス上にAWSのアクセスキー(長期クレデンシャル)を直接保存することは、漏洩時のリスクが高くセキュリティ上の大きな課題となります。

本記事では、IoT機器やエッジデバイスのアクセスキー漏洩リスクを排除する、AWS IAM Roles Anywhereと国産のクラウド型認証・ID管理サービスSoliton OneGate(以下、OneGate)を活用したセキュアなログ転送の手順を解説します。

OneGateは、デジタル証明書を用いた強固なデバイス認証を簡単に実現できるクラウドサービスです。OneGateを利用することで、Wi-FiやVPNなどの社内ネットワーク認証だけでなく、今回のようなクラウド連携時のデバイス認証基盤としてもシームレスに証明書を統合でき、管理者の運用負荷を大きく軽減できます。

本記事では、一時クレデンシャルの自動失効からAWS LambdaによるCRL(証明書失効)運用の自動化まで、実運用に役立つ具体的な手順をご紹介します。

本来であれば専用のIoT機器で行いたいところですが、今回は手軽に検証できるよう、SyslogサーバーおよびSNMPマネージャーに見立てた仮想マシン(Ubuntu OS)を用意しました。この環境を用いて、デバイスに長期クレデンシャルを持たせずに、Amazon CloudWatch Logsへログを安全に転送する仕組みを試します。

なぜAWS IoT CoreではなくIAM Roles Anywhere?証明書認証と運用負荷で比較

IoT機器をターゲットとする場合、「AWS IoT Coreを使う方が良いのでは」と感じる方も多いと思います。確かにアーキテクチャとしてはIoT Coreが自然です。しかし、「証明書失効」の運用に目を向けると、それぞれ異なる特徴が見えてきます。

サービス証明書の失効方法特徴・懸念事項
AWS IoT Coreデバイスレジストリ上で対象証明書のステータスをINACTIVEやREVOKEDに変更する。CRL(証明書失効リスト)ファイルをアップロードする形式ではなく、「このシリアルは失効している」と個別に記載(API実行等)する必要があります。一括管理には作り込みが必要です。
IAM Roles AnywhereCRLファイルをインポート(アップロード)する。OneGateなどの認証局から出力したCRLをそのまま適用できるため、既存のPKIインフラと親和性が高いです。ただしCRLの定期更新の仕組みが必要となります。

今回は、OneGateとの連携のしやすさや、エンタープライズPKIでの一般的な失効運用(CRL)に適合しやすい点から、IAM Roles Anywhereを採用しました。

アクセスキーを持たせないセキュアなログ転送の構成とシステム要件

本記事の検証構成・要件は次の通りです。


  • デバイス: 仮想マシン (Ubuntu OS) をネットワーク内のSyslogサーバー / SNMPマネージャーとして稼働させます。
  • 認証方式: IAM Roles Anywhere + OneGate発行のクライアント証明書を使用します。
  • データ保存先: Amazon CloudWatch Logsへ転送します。
  • ログの扱い: 本番運用でのSDカードの寿命(書き込み回数上限)を考慮し、ログはtmpfs(RAMディスク)上に一時保存します。CloudWatch Agentを用いて、tmpfs上のログをほぼリアルタイムにCloudWatch Logsへストリーミング送信します。
  • 証明書の失効(CRL)運用: AWS LambdaAmazon EventBridgeを組み合わせ、OneGateのCRL配布ポイントから最新のCRLを1日1回取得し、IAM Roles Anywhereへ自動的にアップロード(更新)する仕組みを構築します。

💡 なぜCloudWatch Agentを採用したのか?
RAMディスク(tmpfs)は電源断でデータが消失するリスクがありますが、CloudWatch Agentによる「ニアリアルタイムなストリーミング送信」を組み合わせることで、突然の電源喪失時でもログのロストを数秒〜数十秒の最小限に抑えつつ、SDカードの寿命を保護することが可能になります。

フェーズ1:仮想マシンへの証明書認証導入とログ転送環境の構築

1. OneGateからの証明書発行と準備

まずは認証局であるOneGateから仮想マシン用のクライアント証明書を発行します。

1-1. OneGateから証明書をダウンロード

  1. 管理画面より仮想マシン用のクライアント証明書(.p12形式)を発行し、ダウンロードします。

1-2. Windowsから仮想マシンへファイルを転送する

  1. Windowsの「コマンドプロンプト」または「PowerShell」を開いて、scp(セキュアコピー)コマンドを使います。
    ubuntu_user の部分は仮想マシン(Ubuntu OS)のログインユーザー名、192.168.x.x の部分は仮想マシンのIPアドレスに置き換えてください。
    scp AgentCert_SyslogServer01.p12 ubuntu_user@192.168.x.x:~/

1-3. 仮想マシン上で証明書と秘密鍵を抽出する

  1. 仮想マシンにSSHログインし、以下のコマンドでクライアント証明書を抽出します。
    (※実行時に「1-1. OneGateから証明書をダウンロード」で設定したクライアント証明書のパスフレーズを求められます)
    # クライアント証明書(client.crt)の抽出
    openssl pkcs12 -in AgentCert_SyslogServer01.p12 -clcerts -nokeys -out client.crt -legacy
  2. Enter Import Password と聞かれるので設定したクライアント証明書のパスフレーズを入力してEnterを押します。エラーが出なければ、client.crt というファイルが作成されます。
  3. 続いて、以下のコマンドで秘密鍵を抽出します。
    # 秘密鍵(private.key)の抽出(パスフレーズなし)
    openssl pkcs12 -in AgentCert_SyslogServer01.p12 -nocerts -nodes -out private.key -legacy
  4. 先ほどと同様にパスフレーズを入力します。これで private.key というファイルが作成されます。

1-4. セキュアなディレクトリへの配置と権限設定

  1. 抽出した証明書をセキュアなディレクトリに移動し、厳格なアクセス権(パーミッション)を設定します。
    # 配置用ディレクトリの作成
    sudo mkdir -p /etc/ssl/private
    
    # 転送した証明書と秘密鍵を移動
    sudo mv ~/client.crt /etc/ssl/private/
    sudo mv ~/private.key /etc/ssl/private/
    
    # 所有者を root に変更し、パーミッションを 600 (所有者のみ読み書き可能)に設定
    sudo chown root:root /etc/ssl/private/client.crt /etc/ssl/private/private.key
    sudo chmod 600 /etc/ssl/private/client.crt /etc/ssl/private/private.key
  2. これで、AWS CLIやCloudWatch Agentから安全に読み込める形でクライアント証明書の準備が完了しました。

💡 セキュリティを高めるためのベストプラクティス
本記事では検証の手軽さを優先し、証明書の配置やエージェントの実行を root 権限で行う手順としていますが、本番環境で運用する際は「CloudWatch Agent用の専用ユーザー」を使用して実行することを推奨します。

2. ログ一時保存領域(tmpfs)の作成

本番運用を想定しSDカードの摩耗を防ぐため、SyslogやSNMPの受信ログをメモリ上のRAMディスク(tmpfs)に書き込むよう設定します。

2-1. ログ保存用ディレクトリの作成とマウント設定

  1. まずは、ログを保存するディレクトリ(マウントポイント)を作成します。
    # マウントポイントの作成
    sudo mkdir -p /var/log/iot_ramdisk
  2. 次に、仮想マシンを再起動しても自動でRAMディスクが作成(マウント)されるように、/etc/fstabに設定を追記します。(RAMディスクのサイズは、環境に合わせて適宜変更してください。)
    # fstabにtmpfsの設定を追記
    echo "tmpfs /var/log/iot_ramdisk tmpfs defaults,size=50m,noatime,mode=0755,uid=syslog,gid=adm 0 0" | sudo tee -a /etc/fstab
    
    # 設定を反映(今すぐマウントを実行)
    sudo mount -a
    
    # 正しくマウントされたか確認
    df -h | grep iot_ramdisk
  3. コマンド実行後、画面に tmpfs 50M 0 50M 0% /var/log/iot_ramdisk のように表示されれば成功です。以降、Syslogなどの各種ログデーモンの出力先をこのディレクトリに変更しておきます。

3. IAM Roles Anywhere のセットアップ

AWS側のマネジメントコンソールで「Roles Anywhere」と検索し、IAMの機能として表示された「Roles Anywhere」の画面から設定を行います。

💡 重要:ARNをメモしておきましょう
作成した「信頼アンカー」「IAMロール」「プロファイル」それぞれの ARN をメモ帳などにコピーしておいてください。後の手順で使用します。

3-1. 信頼アンカー(Trust Anchor)の作成

  1. セットアップ手順の「ステップ1:信頼性の確立」に表示される 「信頼アンカーを作成する」 をクリックします。

  2. OneGateのCA証明書は、OneGate管理画面から 証明書管理 > CA情報 に進み「PEM形式」をクリックしてダウンロードしてください。ダウンロードされたCA証明書をメモ帳などで開いておきます。

  3. AWSの画面に戻り、任意の名前(例:OneGate-TrustAnchor)を入力し、認証機関(CA)ソースとして「外部証明書バンドル」を選択します。「外部証明書バンドル」のテキストボックスに、先ほど開いたOneGateの「CA証明書(PEM形式)」の中身を貼り付け、「信頼アンカーを作成する」 をクリックします。

  4. 作成した信頼アンカーが表示されていることを確認します。

3-2. IAMロールの作成(CloudWatchへの書き込み権限付与)

  1. セットアップ手順の「ステップ2:ロールの設定」に表示される 「新しいロールを作成」 をクリックします。

  2. 信頼されたエンティティタイプとして「カスタム信頼ポリシー」を選択します。

  3. カスタム信頼ポリシーの欄に以下のJSONを貼り付け、Roles Anywhereに対してロールの引き受けを許可します。「次へ」をクリックします。(CNの「SyslogServer01」の部分は、「1-1. OneGateから証明書をダウンロード」でダウンロードした証明書のCNの値に変更してください。)
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Principal": {
                    "Service": "rolesanywhere.amazonaws.com"
                },
                "Action": [
                    "sts:AssumeRole",
                    "sts:TagSession",
                    "sts:SetSourceIdentity"
                ],
                "Condition": {
                    "StringEquals": {
                        "aws:PrincipalTag/x509Subject/CN": "SyslogServer01"
                    }
                }
            }
        ]
    }



  4. 許可ポリシーの画面で CloudWatchAgentServerPolicy と検索して表示されるポリシーにチェックを入れ、「次へ」をクリックします。

  5. 任意のロール名(例:IoT-CloudWatch-Role)を入力し、設定を確認して 「ロールを作成」 をクリックします。


  6. 作成したロールが表示されていることを確認します。

3-3. プロファイル(Profile)の作成

  1. セットアップ手順の「ステップ2:ロールの設定」に表示される 「プロファイルを設定」 をクリックします。

  2. 任意の名前(例:OneGate-IoT-Profile)を入力し、ロールの欄で「別のロールの追加」をクリックしてから「3-2. IAMロールの作成(CloudWatchへの書き込み権限付与)」で作成したIAMロール(例:IoT-CloudWatch-Role)を選択して 「プロファイルを作成」 をクリックします。

  3. 作成したプロファイルが表示されていることを確認します。

3-4. 署名ヘルパー(aws_signing_helper)の配置

  1. 仮想マシン(Ubuntu AMD64(x86_64)環境)上で以下のコマンドを実行し、AWS公式の署名ヘルパーをインストールします。
    最新版のダウンロードURLについては、以下をご確認ください。
    https://github.com/aws/rolesanywhere-credential-helper/releases
    # 仮想マシン(AMD64) 用の署名ヘルパーをダウンロード
    wget https://rolesanywhere.amazonaws.com/releases/1.8.0/X86_64/Linux/Amzn2023/aws_signing_helper
    
    # 実行権限を付与し、パスが通った場所に移動
    chmod +x aws_signing_helper
    sudo mv aws_signing_helper /usr/local/bin/

💡 CPUアーキテクチャについて
本記事の検証ではUbuntu(AMD64(x86_64))を想定したURLを記載していますが、お使いのOSがARM64(aarch64)の場合は、URLの X86_64 の部分を Aarch64 に置き換えてダウンロードしてください。

4. CloudWatch Agent への一時クレデンシャル受け渡しとログ送信設定

🚨 注意:CloudWatch Agentの仕様とワークアラウンド
現在のAWSの仕様上、オンプレミス環境のCloudWatch Agentは credential_process (動的なクレデンシャル取得機能)に対応しておらず、アクセスキーが見つからないというエラーが発生します。これを回避するため、「定期的に署名ヘルパーを実行し、取得した一時クレデンシャルを静的なファイルに書き込んでAgentに読み込ませる」という方式を採用しています。

4-1. JSON処理ツール「jq」とAgentのインストール

  1. AWSから返ってくるJSONデータを処理するためのツールと、CloudWatch Agentをインストールします。
    # jqのインストール
    sudo apt-get update
    sudo apt-get install -y jq
    
    # CloudWatch Agentのインストール
    wget https://s3.amazonaws.com/amazoncloudwatch-agent/ubuntu/amd64/latest/amazon-cloudwatch-agent.deb
    sudo dpkg -i -E ./amazon-cloudwatch-agent.deb

4-2. 自動更新スクリプトの作成

  1. 鍵を取得して設定ファイルに書き込むスクリプトを作成します。
    sudo nano /usr/local/bin/update-aws-creds.sh
  2. 以下の内容を貼り付けます(ARNの部分はご自身の環境に合わせて、「3. IAM Roles Anywhereのセットアップ」でメモしたそれぞれのARNに変更してください)。
    #!/bin/bash
    
    # IAM Roles Anywhereから一時クレデンシャルを取得
    CRED_JSON=$(/usr/local/bin/aws_signing_helper credential-process \
    --certificate /etc/ssl/private/client.crt \
    --private-key /etc/ssl/private/private.key \
    --trust-anchor-arn <作成した信頼アンカーのARN> \
    --profile-arn <作成したプロファイルのARN> \
    --role-arn <作成したロールのARN> \
    --duration-seconds 900)
    
    # エラーチェック
    if [ -z "$CRED_JSON" ]; then
      exit 1
    fi
    
    # jqコマンドでJSONから各キーを取り出す
    ACCESS_KEY=$(echo "$CRED_JSON" | jq -r '.AccessKeyId')
    SECRET_KEY=$(echo "$CRED_JSON" | jq -r '.SecretAccessKey')
    SESSION_TOKEN=$(echo "$CRED_JSON" | jq -r '.SessionToken')
    
    # 保存先のディレクトリ(.aws)が存在しない場合は作成する
    mkdir -p /root/.aws
    
    # /root/.aws/config を新規作成(または上書き)して静的な鍵として保存
    cat <<EOF > /root/.aws/config
    [profile iot-role]
    region = ap-northeast-1
    aws_access_key_id = $ACCESS_KEY
    aws_secret_access_key = $SECRET_KEY
    aws_session_token = $SESSION_TOKEN
    EOF

4-3. スクリプトの実行とテスト

  1. スクリプトに実行権限を付与し、手動でテスト実行してみます。
    sudo chmod +x /usr/local/bin/update-aws-creds.sh
    sudo /usr/local/bin/update-aws-creds.sh

4-4. CloudWatch Agentの共通設定とログ収集設定

  1. Agentにプロファイルを使わせるための共通設定を作成します。
    # 共通設定
    sudo nano /opt/aws/amazon-cloudwatch-agent/etc/common-config.toml
    [credentials]
      shared_credential_profile = "profile iot-role"
      shared_credential_file = "/root/.aws/config"
  2. 続いて、ログをCloudWatchに送る設定ファイルを作成します。
    # ログ収集設定
    sudo nano /opt/aws/amazon-cloudwatch-agent/bin/config.json
    {
      "logs": {
        "logs_collected": {
          "files": {
            "collect_list": [
              {
                "file_path": "/var/log/iot_ramdisk/*.log",
                "log_group_name": "/iot/raspberry-pi/syslog",
                "log_stream_name": "{hostname}",
                "timezone": "Local"
              }
            ]
          }
        }
      }
    }

    各パラメーターの役割は以下の通りです。 

    項目
    file_pathCloudWatch Agentが収集対象とするログファイルのパス(場所)です。*(アスタリスク)を使ったワイルドカード指定が可能です。
    log_group_nameCloudWatch Logs 上に作成される「ロググループ」の名前です。ロググループは、関連するログをまとめる大きなフォルダのような役割をします。AWSの管理画面(マネジメントコンソール)でログを探すときは、まずこの名前を探すことになります。
    log_stream_nameロググループの中に作成される「ログストリーム」の名前です。 ログストリームは、ロググループ内の小分けされたファイルのようなものです。
    {hostname} は特別な変数で、Agentが動いているマシンのホスト名(サーバー名やデバイス名)に自動で置き換わります。これにより、どの機器から送られてきたログなのかを一目で区別できます。

4-5. CloudWatch Agentの起動

  1. 設定ファイルを指定して、CloudWatch Agentを起動します。
    sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m onPremise -s -c file:/opt/aws/amazon-cloudwatch-agent/bin/config.json
  2. CloudWatch Agentを起動したあと、以下のコマンドを実行してステータスが「running」になっていることを確認します。
    sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -m onPremise -a status

4-6. CloudWatch Logsでのログ送信確認

Agentを起動して数分待つと、AWSへログの送信が開始されます。AWSのマネジメントコンソールから無事にログが届いているか確認してみます。

  1. AWSマネジメントコンソールにログインし、「CloudWatch」サービスを開きます。
  2. 左側のナビゲーションメニューから 「ログ」>「ロググループ」 をクリックします。
  3. 設定ファイルで指定した /iot/raspberry-pi/syslog という名前のロググループが自動で作成されていることを確認し、クリックします。

  4. ログストリームの一覧に、仮想マシンのホスト名が表示されています。そのストリームを開き、実際に送信されたログのテキストがリアルタイムに表示されていることを確認してください。



5. 一時クレデンシャルの完全自動化(Cron設定)

5-1. Cronを利用した自動更新設定

  1. 取得した一時クレデンシャルは「4-2. 自動更新スクリプトの作成」で指定した通り15分(900秒)で期限が切れるため、スクリプトをCronで定期実行して自動更新されるように設定します。
    ネットワークのわずかな遅延などで更新の瞬間に数秒間だけ権限を失うリスクを防ぐため、余裕を持たせて有効期間の3分の2程度の時間で実行させます。
    sudo crontab -e
  2. 以下の1行を追記し、10分ごとにスクリプトを実行させます。
    */10 * * * * /usr/local/bin/update-aws-creds.sh

6. tmpfsの容量対策(logrotateの設定)

6-1. logrotateによる古いログの自動削除

  1. tmpfsの容量不足を防ぐため、Linux標準の logrotateを使って古いログを自動削除するよう設定します。
    sudo nano /etc/logrotate.d/iot_ramdisk
  2. 以下の内容を貼り付けて保存します。
    /var/log/iot_ramdisk/*.log
    /var/log/iot_ramdisk/*/*.log 
    {
        daily
        maxsize 5M
        rotate 3
        missingok
        notifempty
        compress
        delaycompress
        create 0640 syslog adm
        sharedscripts
        postrotate
            /usr/lib/rsyslog/rsyslog-rotate
        endscript
    }

💡 CloudWatch Agentとlogrotateの相性
CloudWatch Agentは標準で logrotate に対応しており、ファイルが切り替わっても新しいファイルからログを読み取ります。

フェーズ2:運用負荷を削減!AWS Lambdaによる証明書失効(CRL)の完全自動化

ここまでの構成でログの送信自体は完成ですが、本番運用に向けては「証明書の失効確認」が必須となります。
IAM Roles Anywhereで証明書の失効確認を有効にするには、OneGateのCRLファイル(証明書失効リスト)を定期的にAWSへアップロードする必要があります。今回の構成では、この作業をAWS LambdaAmazon EventBridgeを使って完全自動化します。

7. CRLの自動アップロードの構築

7-1. OneGateのCRL URLの確認と初期インポート

現在、AWSのマネジメントコンソール上にはCRLファイルを画面から直接インポートする機能がないため、AWS CloudShellを利用して初期登録を行います。

  1. OneGateの管理画面からCRLファイルのダウンロードURL(CRL配布ポイントURL)を確認し、コピーします。

  2. ブラウザでCRL配布ポイントURLを開き、CRLファイルをダウンロードします。

    💡 CRLファイルをPEM形式でダウンロード
    OneGateでは2026年3月16日以降の新規テナントより、CRLファイルをPEM形式でダウンロードする機能を提供しております。
    PEM形式でダウンロードするには、以下の例のようにCRL配布ポイントURLの末尾に「?type=pem」をつけてCRLファイルをダウンロードしてください。
    例)http://xxxx.ids.soliton-ods.jp/certs/x/certs.crl?type=pem

  3. CRLファイルをDER形式でダウンロードした場合は、OpenSSLを使ってPEM形式に変換します。
    openssl crl -inform DER -in download.crl -outform PEM -out crl_pem.crl
  4. AWSマネジメントコンソール右上のアイコン(>_)から CloudShell を起動します。右上の「アクション」から「ファイルのアップロード」を選択し、PEM形式のCRLファイル「 crl_pem.crl」 をアップロードします。

  5. CloudShell上で以下のコマンドを実行し、CRLファイルをインポートすると同時に信頼アンカーに関連付けます。
    (※ <信頼アンカーのARN>「3-1. 信頼アンカー(Trust Anchor)の作成」でメモしたARNに置き換えてください)
    aws rolesanywhere import-crl \
      --name "OneGate-CRL" \
      --crl-data fileb://crl_pem.crl \
      --trust-anchor-arn "<信頼アンカーのARN>" \
      --enabled
  6. コマンドが成功するとJSON形式で結果が表示されます。その中にある "crlId": "0123456789abcdef..." の値をメモしておきます。

7-2. Lambda実行用IAMロールの作成

AWS Lambdaが「Roles AnywhereのCRLを更新する」ためのポリシーと、「実行ログを保存する」ためのロールを作成します。

  1. AWSマネジメントコンソールで「IAM」サービスを開き、左側メニューの 「ポリシー」 をクリックし、右上にある 「ポリシーの作成」 をクリックします。

  2. ポリシーエディタの画面で 「JSON」を選択し、以下のコードを貼り付けて「次へ」をクリックします。
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Action": [
                    "rolesanywhere:UpdateCrl"
                ],
                "Resource": "*"
            }
        ]
    }


  3. ポリシー名(例:UpdateRolesAnywhereCRLPolicy)を入力し、右下の 「ポリシーの作成」 をクリックします。

  4. 作成したポリシーが表示されることを確認します。

  5. 次に、左側メニューの 「ロール」 をクリックし、右上にある 「ロールを作成」 をクリックします。

  6. 「信頼されたエンティティタイプ」で 「AWS のサービス」 を選択し、「ユースケース」で 「Lambda」 を選択して「次へ」をクリックします。

  7. Lambdaが動いたときのログを自動的にCloudWatchへ保存するために、許可ポリシーの画面で AWSLambdaBasicExecutionRole と検索し、表示されたポリシーの左側にチェックを入れます。

  8. 次に、先ほど作成した UpdateRolesAnywhereCRLPolicy を検索し、表示されたポリシーの左側にチェックを入れて「次へ」をクリックします。(※合計2つのポリシーにチェックが入っています)

  9. ロール名(例:Lambda-UpdateCRL-Role)を入力し、設定を確認してから画面右下の 「ロールを作成」 をクリックします。


  10. 作成したロールが表示されることを確認します。

7-3. Lambda関数の作成

  1. AWSマネジメントコンソールで 「Lambda」 サービスを開き、右上の 「関数を作成」 をクリックします。

  2. 一番上の選択肢で 「一から作成」 が選ばれていることを確認し、以下の通り基本設定を入力して 「関数の作成」をクリックします。
    関数名: わかりやすい名前を入力(例:UpdateRolesAnywhereCRL
    ランタイム: 「Python 3.14」 (または最新のPython 3.x)を選択
    カスタム設定-その他の設定: 「カスタム実行ロール」を有効にして、「既存のロールを選択」より「7-2. Lambda実行用IAMロールの作成」で作成したロール(例:Lambda-UpdateCRL-Role)を選択し「保存」をクリック


  3. 関数が作成されたら、画面中段の 「設定」 タブをクリックし、左側のメニューから 「環境変数」 を選んで 「編集」 ボタンをクリックします。

  4. 「環境変数の追加」をクリックし、以下2つのキーを登録して「保存」をクリックします。 
    キー
    CRL_URL「7-1. OneGateのCRL URLの確認と初期インポート」でメモしたOneGateのCRL配布ポイントURL
    ※PEM形式でのダウンロードが可能な場合は、末尾に「?type=pem」をつけたURL
    CRL_ID「7-1. OneGateのCRL URLの確認と初期インポート」でメモしたAWS上のCRL ID




  5. 外部からのダウンロード時のエラーを防ぐため、「設定」タブの左側メニューから 「一般設定」 を選び、「編集」 ボタンをクリックして「タイムアウト」を 「30秒」 などに変更し、「保存」をクリックします。


  6. 「コード」 タブをクリックし、表示されている lambda_function.py のサンプルコードをすべて消去して、以下のPythonコードを貼り付けます。
    import urllib.request
    import boto3
    import os
    
    def lambda_handler(event, context):
        crl_url = os.environ['CRL_URL']
        crl_id = os.environ['CRL_ID']
        
        # OneGateから最新のCRLをダウンロード
        try:
            req = urllib.request.Request(crl_url)
            with urllib.request.urlopen(req) as response:
                crl_data = response.read()
        except Exception as e:
            print(f"CRLのダウンロードに失敗しました: {e}")
            raise e
            
        # IAM Roles AnywhereのCRLを更新
        try:
            client = boto3.client('rolesanywhere')
            response = client.update_crl(
                crlId=crl_id,
                crlData=crl_data
            )
            print("CRLの更新に成功しました。")
        except Exception as e:
            print(f"CRLの更新に失敗しました: {e}")
            raise e
            
        return {
            'statusCode': 200,
            'body': 'CRL updated successfully'
        }

    💡 補足:CloudWatchでのログの見方について
    コード内に記述されている print の出力内容は、実行時にCloudWatch Logsへ自動的に保存されます。AWSマネジメントコンソールの「CloudWatch」>「ロググループ」から /aws/lambda/(関数名) のロググループを開くことで、処理の正常終了やエラー発生時の詳細なメッセージを確認できます。

  7. コードを貼り付けたら、ファイル一覧の下にある 「Deploy」 ボタンをクリックします。これでプログラムの準備は完了です。

7-4. EventBridgeで定期実行(Rate)の設定

作成したLambda関数を高頻度で自動実行し、OneGateで証明書を失効させた際にいち早くAWS側のCRLを最新化するため、「Amazon EventBridge Scheduler」を使ってスケジュールを設定します。

  1. AWSマネジメントコンソールで 「Amazon EventBridge」 サービスを開きます。
  2. 左側のナビゲーションメニューの「スケジューラ」の下にある 「スケジュール」 をクリックし、右上の 「スケジュールを作成」 をクリックします。

  3. 「スケジュール名」 にわかりやすい名前(例:Daily-CRL-Update-Schedule)を入力します。

  4. 以下の設定を入力し、「次へ」をクリックします。
    頻度: 定期的なスケジュール
    タイムゾーン: Asia/Tokyo
    スケジュールの種類: rate ベースのスケジュール
    rate式: 15 minutes(15分ごと)
    フレックスタイムウィンドウ: オフ(高頻度実行のため)



  5. 「ターゲットの選択」画面で「テンプレート化されたターゲット」を選択し、一覧から 「AWS Lambda: Invoke」 を選択します。
  6. 「Lambda関数」のプルダウンから、「7-3. Lambda関数の作成」で作成したLambda関数(例:UpdateRolesAnywhereCRL)を選択し、「次へ」をクリックします。

  7. 「設定 - オプション」画面はデフォルトのまま進み、ページ下部の「アクセス許可」で 「このスケジュールの新しいロールを作成」 が選ばれていることを確認して「次へ」をクリックします。

  8. 最後に「スケジュールの確認と作成」画面で設定内容を確認し、右下の 「スケジュールを作成」 をクリックします。


これで、証明書失効運用も自動化することができました。

フェーズ3:緊急時の即時アクセス遮断(明示的なDenyポリシー)

ここまでの設定により、OneGateで証明書を失効させると、最大で「EventBridgeの実行間隔(15分)+クレデンシャルの有効期限(15分)」という短い時間でアクセスが自動的に遮断されるようになります。

しかし、端末の紛失などの緊急事態が発生した場合には、CRLの更新を待たずにAWS側でアクセスを即時遮断することも可能です。
その場合は、「3-2. IAMロールの作成(CloudWatchへの書き込み権限付与)」で作成したIAMロールのカスタム信頼ポリシーに「特定のデバイス(証明書のCN)からのアクセスをすべて拒否する」ルールを追加します。

対象のロールに以下のインラインポリシーを追加することで、一時クレデンシャルが有効であっても即座にAWSへのアクセスが弾かれます。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Deny",
            "Action": "*",
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "aws:PrincipalTag/x509Subject/CN": "SyslogServer01"
                }
            }
        }
    ]
}

"SyslogServer01" の部分は、失効させたい対象証明書のCNに置き換えてください。

緊急時にはAWSマネジメントコンソールから直接特定のデバイス(証明書のCN)からのアクセスをすべて拒否する運用ルールにすることで、より強固なセキュリティを担保できます。

まとめ:アクセスキー不要のセキュアなクラウド連携で情報漏洩リスクを排除する

本記事では、AWSのIAM Roles AnywhereとSoliton OneGateを組み合わせ、エッジデバイスからAWS環境へセキュアにアクセスするための検証をご紹介しました。デバイスに長期クレデンシャル(アクセスキー)を直接持たせないことで、情報漏洩リスクを根本から排除した安全なログ転送が実現できます。

また、今回は仮想マシン(Ubuntu OS)を用いた検証として、ログをRAMディスク(tmpfs)へ書き込むことで本番運用を想定したSDカードの寿命問題をクリアしつつ、CloudWatch Agentによるストリーミング送信で、ニアリアルタイムな監視とデータ保護を両立させました。

さらに、実運用において課題となりやすい「証明書の失効(CRL)運用」についても、AWS LambdaAmazon EventBridgeを連携させて完全自動化しました。クレデンシャルの有効期間を最小化することで失効からアクセス遮断までのタイムラグを極小化しつつ、緊急時用の明示的なDeny運用も備えることで、高いセキュリティ水準を保ちながら、管理者の運用負荷を最小限に抑える仕組みが構築できたかと思います。

IoT・エッジコンピューティング環境におけるセキュリティ強化の一環として、「AWS × Soliton OneGate」の組み合わせをぜひご検討いただければ幸いです。

記事を書いた人

ソリトンシステムズ ソリューションアーキテクト 米倉

普段の業務では、パートナー様とのOEM技術支援をはじめ、SCS評価制度を通じたお客様への製品提案など、複数の製品を組み合わせた複合提案を技術面からサポートしています。日々の技術支援で培った知見を活かし、皆様の課題解決や最適なソリューション選びのヒントになるような情報をお届けしていきたいと考えています。