
Alliance AuthのDiscord統合用のリコンシリエーション監査ツール:Authが付与したことのないAA管理ロールを保持するギルドメンバーを検出し、オペレーター制御のポリシーに基づいてそれらのロールを剥奪またはメンバーをキックします。スタンドアロンのコミュニティDjangoアプリ。
Alliance AuthのDiscord連携向けの整合性監査ツールです。設定されたDiscordギルドにおける実際のロール割り当てを、Alliance Auth側で表現されている状態(ユーザーごとのグループ+ステート)と比較し、モデレーターがAAが把握していないユーザーに対してAA名のロールを手動で割り当てられるというギャップを解消します。
ステータス: アルファ版(
0.1.x)。パブリックAPIおよび設定は1.0より前に変更される可能性があります。
監査はデフォルトで安全です:
InitialAuditAcknowledgement(管理者またはシェルのみ)が必要です。reportです — 破壊的なアクションはオプトインです。AuditRun、AuditFinding、AuditInvocation、ConfigChangeLog)はマネージャー層とインスタンス層で追記専用です。一括のupdate() / bulk_update()はブロックされます。各ギルドメンバーは1つのカテゴリに分類されます:
| カテゴリ | 意味 |
|---|---|
unknown_guest | AAが何も把握していないDiscordメンバー |
linked_no_perm | AAに認識されているがdiscord.access_discordを持たない |
bot_filtered | 設定されたボットアカウント — 一切のアクション対象外 |
オペレーターは各カテゴリを1つのアクションにマッピングします:
| アクション | 動作 |
|---|---|
report | 検出結果を記録;Discord側の変更なし |
strip | AA管理のロールを削除 |
strip_kick | AA管理のロールを削除し、その後ギルドからキック |
マッピングはAA_DISCORD_AUDIT_POLICY設定です。グループごとおよびステートごとのオーバーライドは各カテゴリ内にネストされます。
allianceauth.services.modules.discord)がインストールおよび設定済みであること(ボットトークン+ギルド)pip install aa-discord-audit
Auth の local.py にて:
# `aa_discord_audit` must appear AFTER
# `allianceauth.services.modules.discord` so the discord module's
# models load first; `apps.ready()` raises `ImproperlyConfigured`
# otherwise.
INSTALLED_APPS += ["aa_discord_audit"]
MIDDLEWARE += [
"aa_discord_audit.current_user.CurrentUserMiddleware",
]
次にマイグレーションを実行します:
python manage.py migrate aa_discord_audit
CurrentUserMiddleware は必須です — これが欠けていると apps.ready() が
ImproperlyConfigured を発生させます。これにより、ConfigChangeLog のシグナルハンドラが
管理者による編集を <system> ではなく実際のユーザーに帰属させることができます。
監査を実行するオペレーターロールに aa_discord_audit.run_audit を付与します。
ドライラン監査を実行します:
python manage.py audit_discord_roles --action report
Auth ダッシュボードの Discord Audit → Audit runs で検出結果を確認します。
初回実行ロックを解除します — 管理者経由で
InitialAuditAcknowledgement 行を作成するか、
python manage.py audit_acknowledge_initial を実行します。どちらも
aa_discord_audit.run_audit および
aa_discord_audit.acknowledge_initial_audit が必要です。
準備ができたら、任意の破壊的アクションを指定して再実行します。
| コードネーム | 制御対象 |
|---|---|
aa_discord_audit.run_audit | 管理コマンド、beat タスク、実行の削除 |
aa_discord_audit.run_audit_destructive | strip / strip_kick の Web 起動ゲート(run_audit とは別) |
aa_discord_audit.acknowledge_initial_audit | 初回実行ドライランロックの解除 |
aa_discord_audit.manage_discord_identity | DiscordIdentity 管理 |
aa_discord_audit.manage_role_exception | ManagedRoleException 管理 |
aa_discord_audit.manage_protected_member | ProtectedDiscordMember 管理 |
aa_discord_audit.manage_bot_account_uid | BotAccountUid 管理 |
aa_discord_audit.manage_finding_override | FindingActionOverride 管理 |
aa_discord_audit.view_auditrun (および関連) | Auth ダッシュボードの読み取り専用監査証跡 |
manage_* コードネームは影響範囲ごとに分割されているため、
manage_bot_account_uid を持つジュニアユーザーが
ManagedRoleException を編集して監査を無効化することはできません。
すべての設定は任意です。デフォルトは安全です。
# Action policy. Bare-string form below is shorthand for
# {"default": "<action>"}; use the nested form for per-group / per-state
# overrides keyed by AA group name and state name.
AA_DISCORD_AUDIT_POLICY = {
"unknown_guest": "report",
"linked_no_perm": "report",
# "strip" is rejected at startup for linked_no_perm (it conflicts with
# AA's update_groups task); use "strip_kick" instead.
# "linked_no_perm": {
# "default": "strip_kick",
# "by_state": {"Guest": "report"},
# "by_group": {"Directors": "report"},
# },
}
# AA-notify fan-out to permission holders.
AA_DISCORD_AUDIT_NOTIFY_ADMINS = True
# Discord webhook for run summaries. Treat as a credential.
AA_DISCORD_AUDIT_WEBHOOK_URL = None
# uids skipped as bot accounts (in addition to the BotAccountUid admin
# table).
AA_DISCORD_AUDIT_BOT_UIDS = []
# Auto-discover bot accounts by Discord nickname heuristics. Reserved
# for v2; not implemented in the MVP. The startup validator raises
# ImproperlyConfigured if set to True — keep this False and use the
# explicit BotAccountUid admin table instead.
AA_DISCORD_AUDIT_AUTO_DISCOVER_BY_NICKNAME = False
# Retention. 0 disables pruning; the validator refuses 0 unless the
# acknowledged flag below is also set.
AA_DISCORD_AUDIT_RUN_RETENTION_DAYS = 180
AA_DISCORD_AUDIT_RETENTION_OPT_OUT_ACKNOWLEDGED = False
# Idempotency-key TTL. When positive, prune_audit_runs releases
# AuditRun.idempotency_key on rows older than the cutoff while the
# row itself stays for RUN_RETENTION_DAYS. 0 (default) disables the
# expiry; the key dies with the row.
AA_DISCORD_AUDIT_IDEMPOTENCY_KEY_TTL_DAYS = 0
# Per-run deadline. The Celery task's soft_time_limit follows.
AA_DISCORD_AUDIT_RUN_DEADLINE_MINUTES = 60
# Rolling 24h rate limit on accepted audit triggers per user.
# DISABLED is an opt-out gate; refuses to take effect unless
# explicitly toggled.
AA_DISCORD_AUDIT_RUN_RATE_LIMIT_PER_DAY = 5
AA_DISCORD_AUDIT_RUN_RATE_LIMIT_DISABLED = False
# Discord webhook delivery tuning.
AA_DISCORD_AUDIT_WEBHOOK_TIMEOUT = 10
AA_DISCORD_AUDIT_WEBHOOK_MAX_RETRIES = 3
# Opt-in: bulk PATCH role strip. Faster on large guilds; off by default
# while we collect operator feedback on Discord-side rate-limit shape.
AA_DISCORD_AUDIT_USE_BULK_ROLE_STRIP = False
# Periodic (Celery beat) audit. Destructive actions on the unattended
# beat require this explicit opt-in, independent of the one-shot
# first-run lock: a beat run carrying strip/kick is coerced to report
# otherwise, with a startup warning on mismatch.
AA_DISCORD_AUDIT_BEAT_ALLOW_DESTRUCTIVE = False
# Coarse global floor between beat runs, in minutes. 0 (default)
# disables it — the Celery beat schedule is the primary cadence
# control. A backstop against a misconfigured fast schedule
# (QueueOnce only dedupes concurrent ticks, not back-to-back ones).
AA_DISCORD_AUDIT_BEAT_MIN_INTERVAL_MINUTES = 0
# Pin the CLI acting user to a Django username (the "service principal"
# pattern). The management command has no HTTP request, so the actor is
# normally derived from the OS login; set this for clean, stable
# ConfigChangeLog attribution from cron and manual CLI alike. Resolved
# and permission-checked per invocation.
AA_DISCORD_AUDIT_CLI_ACTOR = None