AWS IoT Device Defenderの監査をCDKで設定してみた

2022.01.25

AWS IoT Device Defenderは、IoTデバイスの保護に役立つサービスです。AWS IoTのポリシーやモノなど様々な項目を継続的に監視して、セキュリティのベストプラクティスからの逸脱がないことをチェックします。

環境情報

項目 内容
OS macOS Big Sur 11.6(20G165)
Node.js 14.18.1
TypeScript 3.9.7
AWS CDK 1.131.0

Device Defenderの監査項目

AWS IoT Device Defenderには以下のような監査項目が用意されています。

項目名 重要度 ソースタイプ
認証された Cognito ロールが過度に許容されている
重大 Cognito プール
CA 証明書の有効期限が切れます
ミディアム CA 証明書
CA 証明書のキー品質
重大 CA 証明書
MQTT クライアント ID の競合
クライアント ID
デバイス証明書の有効期限が切れる
ミディアム デバイス証明書
デバイス証明書のキー品質
重大 デバイス証明書
デバイス証明書共有
重大 デバイス証明書
IoT ポリシーが過度に許容されている
重大 ポリシー
ロールのエイリアスは、未使用のサービスへのアクセスを許可する
ミディアム ロールのエイリアス
ロールのエイリアスが過度に許容されている
重大 ロールのエイリアス
ログ記録が無効
アカウント設定
CA 証明書は取り消されましたが、デバイス証明書は依然としてアクティブです
重大 CA 証明書
取り消されたデバイス証明書がまだアクティブである
ミディアム デバイス証明書
認証されていない Cognito ロールが過度に許容されている
重大 Cognito プール

Device Defenderの監査をCDKで設定

Device Defender Auditの設定とスケジュールを作成するCDKを実装します。

lib/cdk-iot-device-defender.ts

import * as iam from '@aws-cdk/aws-iam';
import * as iot from '@aws-cdk/aws-iot';
import * as cdk from '@aws-cdk/core';

export class IotDeviceDefenderStack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const accountId = cdk.Stack.of(this).account;

    const iotDeviceDefenderAuditRole = new iam.Role(
      this,
      'IotDeviceDefenderAuditRole',
      {
        roleName: 'iot-device-defender-audit-role',
        assumedBy: new iam.ServicePrincipal('iot.amazonaws.com'),
        managedPolicies: [
          iam.ManagedPolicy.fromAwsManagedPolicyName(
            'service-role/AWSIoTDeviceDefenderAudit',
          ),
        ],
      },
    );

    const accountAuditConfiguration = new iot.CfnAccountAuditConfiguration(
      this,
      'AccountAuditConfiguration',
      {
        accountId: accountId,
        auditCheckConfigurations: {
          authenticatedCognitoRoleOverlyPermissiveCheck: {
            enabled: true,
          },
          caCertificateExpiringCheck: {
            enabled: true,
          },
          caCertificateKeyQualityCheck: {
            enabled: true,
          },
          conflictingClientIdsCheck: {
            enabled: true,
          },
          deviceCertificateExpiringCheck: {
            enabled: true,
          },
          deviceCertificateKeyQualityCheck: {
            enabled: true,
          },
          deviceCertificateSharedCheck: {
            enabled: true,
          },
          iotPolicyOverlyPermissiveCheck: {
            enabled: true,
          },
          iotRoleAliasAllowsAccessToUnusedServicesCheck: {
            enabled: true,
          },
          iotRoleAliasOverlyPermissiveCheck: {
            enabled: true,
          },
          loggingDisabledCheck: {
            enabled: true,
          },
          revokedCaCertificateStillActiveCheck: {
            enabled: true,
          },
          revokedDeviceCertificateStillActiveCheck: {
            enabled: true,
          },
          unauthenticatedCognitoRoleOverlyPermissiveCheck: {
            enabled: true,
          },
        },
        roleArn: iotDeviceDefenderAuditRole.roleArn,
      },
    );

    const scheduledAudit = new iot.CfnScheduledAudit(
      this,
      'DailyScheduledAudit',
      {
        scheduledAuditName: 'DailyScheduledAudit',
        frequency: 'DAILY',
        targetCheckNames: [
          'AUTHENTICATED_COGNITO_ROLE_OVERLY_PERMISSIVE_CHECK',
          'CA_CERTIFICATE_EXPIRING_CHECK',
          'CA_CERTIFICATE_KEY_QUALITY_CHECK',
          'CONFLICTING_CLIENT_IDS_CHECK',
          'DEVICE_CERTIFICATE_EXPIRING_CHECK',
          'DEVICE_CERTIFICATE_KEY_QUALITY_CHECK',
          'DEVICE_CERTIFICATE_SHARED_CHECK',
          'IOT_POLICY_OVERLY_PERMISSIVE_CHECK',
          'IOT_ROLE_ALIAS_ALLOWS_ACCESS_TO_UNUSED_SERVICES_CHECK',
          'IOT_ROLE_ALIAS_OVERLY_PERMISSIVE_CHECK',
          'LOGGING_DISABLED_CHECK',
          'REVOKED_CA_CERTIFICATE_STILL_ACTIVE_CHECK',
          'REVOKED_DEVICE_CERTIFICATE_STILL_ACTIVE_CHECK',
          'UNAUTHENTICATED_COGNITO_ROLE_OVERLY_PERMISSIVE_CHECK',
        ],
      },
    );

    scheduledAudit.addDependsOn(accountAuditConfiguration);
  }
}

動作確認

AWSのマネージメントコンソールで監査設定が有効になっていることを確認します。

AWS IoT Device Defender Auditの設定

監査スケジュールが作成されていることを確認します。

AWS IoT Device Defenderスケジュール

これで毎日監査が実行されて、結果に監査結果が表示されるようになります。監査を即時実行したい場合は、スケジュールの作成から「今すぐ監査を実行(1回)」を選択することも出来ます。

注意事項

AWSマネージメントコンソールで事前に監査設定をした場合、CloudFormationやCDKなどでデプロイできなくなります。その場合には、以下のコマンドで監査設定を削除します。

aws iot delete-account-audit-configuration

まとめ

簡単な設定でAWS IoTのセキュリティ監査ができるので使わない手はないですね。スケジュールを設定して継続的に監査を実施することで、運用中の作業ミスや不審なアクセスに気がつくことも可能です。また「監査結果の抑制」で例外も設定できます。

次回はAWS IoT Device Defenderの監査結果をSlackに通知する方法を紹介します。

投稿しました!

参考資料