【実務・中級編】 ABAC(属性ベースアクセス制御)による動的なアクセス制御 – インフラ・ネットワーク & クラウドセキュリティ防御ガイド

「静的な権限管理」は死んだ:ABACで実現するゼロトラストなアクセス制御

現場でインシデント対応をしていると、「権限管理はロール(RBAC)で十分」と信じ切っているチームに何度も出会う。だが、現実はどうか。退職したエンジニアの権限が残っていた、あるいはVPNを突破された瞬間に社内LANが全開放される状況……これらはすべて「静的なルール」に依存した設計の敗北だ。

今日は、攻撃者が最も嫌う「動的な防御」、すなわち ABAC (Attribute-Based Access Control) の実装について、現場の泥臭い知見を交えて解説する。

—

なぜRBACだけでは突破されるのか?

RBAC(ロールベースアクセス制御)は、ユーザーに「管理者」や「編集者」といったラベルを貼る。しかし、攻撃者はその「ラベル」を奪い取る(セッションハイジャックやクレデンシャルスタッフィング)。

ここでABACの出番だ。ABACは「誰か」だけでなく、以下の属性(Attributes)を掛け合わせてアクセス可否を動的に判定する。

  • Subject(主体の属性): デバイスの健全性(EDR導入済みか)、所属部署、MFAの実施状況
  • Action(操作の属性): 読み込みか、書き込みか、削除か
  • Resource(リソースの属性): データの重要度、機密フラグ
  • Environment(環境の属性): IPアドレス(社内か)、時刻(業務時間内か)、接続元リージョン

攻撃者が正しいID/PWを持っていても、深夜の海外IPからのアクセスであれば、ABACエンジンが「否認」を叩き出す。これが現代の要塞化の基本だ。

—

【実装編】PythonによるABACポリシー評価エンジン

複雑なフレームワークを入れる前に、ABACの本質を理解しよう。これは「属性の組み合わせを条件判定するロジック」に過ぎない。

以下は、アクセスリクエストを評価するシンプルなPythonコードだ。実務ではこれをミドルウェアやAPIゲートウェイ層に組み込む。

def evaluate_access(user, resource, environment):
    """
    ABACポリシーエンジン
    戻り値: True (許可) / False (拒否)
    """
    
    # 1. 時間外アクセスのブロック(環境属性)
    if environment['hour'] < 9 or environment['hour'] > 18:
        print("警告: 業務時間外のアクセスを検知")
        return False

    # 2. デバイス健全性のチェック(主体属性)
    if not user['is_device_compliant']:
        print("警告: デバイスが検知対象外(EDR未稼働など)")
        return False

    # 3. IP制限と権限の組み合わせ(環境と主体の属性)
    if resource['is_sensitive'] and environment['ip_type'] != 'office':
        print("拒否: 機密リソースへの社外からのアクセス")
        return False

    return True

# 判定シミュレーション
user_context = {'id': 'dev_01', 'is_device_compliant': True}
resource_info = {'id': 'db_prod_01', 'is_sensitive': True}
env_info = {'ip_type': 'home', 'hour': 14}

if evaluate_access(user_context, resource_info, env_info):
    print("アクセス許可")
else:
    print("アクセス拒否")

—

インフラ層でのABAC的アプローチ(Nginx + Lua)

アプリケーションコードまでリクエストを到達させないことが、最大の防御だ。Nginxの auth_request モジュールを使えば、リクエストの属性(ヘッダー、IP、証明書)を前段で検証できる。

# Nginx設定例: 特定の属性を持つリクエストのみ通す
location /api/private/ {
    # 認証サブクエリを呼び出す
    auth_request /auth_check;
    
    # ... そのままバックエンドへ転送
    proxy_pass http://backend_cluster;
}

location = /auth_check {
    internal;
    # ここでLua等を使って、ヘッダーのX-Device-Stateや
    # 送信元IPを判定して200か403を返す
    proxy_pass_request_body off;
    proxy_set_header Content-Length "";
    # 判定ロジックへリダイレクト
}

—

現場のエンジニアへ:明日からのアクションプラン

1. 「とりあえず許可」をやめる: デフォルト拒否(Default Deny)を徹底せよ。
2. 属性の可視化: 現在のシステムで「IP」「時刻」「デバイス情報」がログとして取得できているか確認せよ。これらがなければABACは実装できない。
3. まずは「時刻」と「IP」から: 難解なポリシー言語を覚える前に、まずは「深夜の管理画面アクセスを遮断する」といった単純なABACから着手しよう。

セキュリティ・チーフからの教訓

セキュリティは「一度設定して終わり」の静的な壁ではない。攻撃者が環境を変化させる以上、我々の制御もまた、常に「文脈(コンテキスト)」に応じて変化し続けなければならない。

ツールに依存せず、この「コンテキストを判定するロジック」を自身のアーキテクチャに組み込む勇気を持ってほしい。それが、君たちのプロダクトを真の意味で守る唯一の道だ。

何か実装で詰まったら、いつでも聞きに来い。現場のコードは嘘をつかない。

コメント

タイトルとURLをコピーしました