
分散型・高速デプロイメントのためのAWS最小権限
Repokid は、Aardvark が提供する Access Advisor を使用して、AWS アカウント内の IAM ロールのインラインポリシーから、未使用のサービスへのアクセスを許可する権限を削除します。
mkvirtualenv repokid
git clone [email protected]:Netflix/repokid.git
cd repokid
pip install -e .
repokid config config.json
DynamoDB テーブル repokid_roles が必要です(コンフィグファイルの dynamo_db でアカウントとエンドポイントを指定します)。
テーブルは以下のプロパティを持つ必要があります:
RoleId(文字列)をプライマリパーティションキーとし、プライマリソートキーはなしAccount という名前のグローバルセカンダリインデックスで、プライマリパーティションキーは Account、プロジェクション属性は RoleId と AccountRoleName という名前のグローバルセカンダリインデックスで、プライマリパーティションキーは RoleName、プロジェクション属性は RoleId と RoleName開発用として、DynamoDB をローカルで実行できます。
ローカルで実行するには:
docker-compose up
DynamoDB のエンドポイントは http://localhost:8000 になります。DynamoDB 管理パネルは http://localhost:8001 で利用できます。
開発バージョンを実行すると、テーブルとインデックスが自動的に作成されます。
Repokid は、クエリ対象の各アカウントに IAM ロールが必要です。さらに、Repokid は、異なるアカウントロールに対して sts:AssumeRole を実行できるロールまたはユーザーで起動する必要があります。
RepokidInstanceProfile:
sts:AssumeRole を呼び出す機能が必要です。repokid_roles テーブルとすべてのインデックスに対する DynamoDB 権限(コンフィグの dynamo_db の assume_role サブセクションで指定)、および dynamodb:ListTables を実行する機能が必要です。RepokidRole:
RepokidInstanceProfile を許可する信頼ポリシーが必要です。connection_iam で指定する必要があります。{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"iam:DeleteInstanceProfile",
"iam:DeleteRole",
"iam:DeleteRolePolicy",
"iam:GetAccountAuthorizationDetails",
"iam:GetInstanceProfile",
"iam:GetRole",
"iam:GetRolePolicy",
"iam:ListInstanceProfiles",
"iam:ListInstanceProfilesForRole",
"iam:ListRolePolicies",
"iam:PutRolePolicy",
"iam:UpdateRoleDescription"
],
"Effect": "Allow",
"Resource": "*"
}
]
}
したがって、n 個のアカウントを監視している場合、常に n+1 個のロールが必要です。(n 個の RepokidRole と 1 個の RepokidInstanceProfile)。
repokid config config.json を実行すると、編集が必要なファイルが作成されます。以下のフィールドを見つけて更新してください:
dynamodb:ローカルで DynamoDB を使用する場合は、エンドポイントを http://localhost:8010 に設定します。AWS ホストの DynamoDB を使用する場合は、region、assume_role、account_number を設定します。aardvark_api_location:Aardvark REST API の場所。例:https://aardvark.yourcompany.net/api/1/advisorsconnection_iam:assume_role を RepokidRole またはその他の名前に設定します。Repokid はフィルターを使用して、リポジトリ対象となるロールを決定します。フィルターは、以下に説明するように環境に合わせて設定できます。
ロールを Blocklist フィルターに追加することで除外できます。ロールを除外する一般的な理由の 1 つは、対応するワークロードが時折実行されるアクションが、まだ観測されていないものの、必要であることがわかっている場合です。ロールを除外するには 2 つの方法があります。
filter_config.BlocklistFilter.all のリストに追加します。filter_config.BlocklistFilter.<ACCOUNT_NUMBER> のリストに追加します。ブロックリストは S3 ブロックリストファイルでも管理できます。以下の形式である必要があります:
{
"arns": ["arn1", "arn2"],
"names": {"role_name_1": ["all", "account_number_1"], "role_name_2": ["account_number_2", "account_number_3"]}
}
特定のロールのみをリポジトリ対象にしたい場合は、Exclusive Filter を使用できます。本番環境や特定のチームで使用されるロールのみを考慮したい場合などです。リポジトリ対象のロールを選択するには、その名前を設定ファイルにリストします。シェルスタイルのグロブパターンもサポートされています。ロールの選択は、個々のアカウントごとまたはグローバルに指定できます。このフィルターを有効にするには、コンフィグファイルの active_filters セクションに "repokid.filters.exclusive:ExclusiveFilter" を追加します。設定は、自動生成されたコンフィグファイルから始めることができます。そのファイルの "filter_config" セクションに設定例があります。
"ExclusiveFilter": {
"all": [
"<GLOB_PATTERN>"
],
"<ACCOUNT_NUMBER>": [
"<GLOB_PATTERN>"
]
}
デフォルトでは、age フィルターは 90 日未満のロールを除外します。これを変更するには、コンフィグ設定 filter_config.AgeFilter.minimum_age を編集します。
新しいフィルターを作成して内部ロジックをサポートできます。Netflix では、ユースケースに固有のフィルターがいくつかあります。これらをアクティブにするには、それらが Python パスにあることを確認し、コンフィグの active_filters セクションのリストに追加します。
Repokid は、以下のリストに示すさまざまな操作の前、最中、後に呼び出されるフックを介して拡張可能です。
フックは以下のインターフェースに準拠する必要があります:
from repokid.hooks import implements_hook
from repokid.types import RepokidHookInput, RepokidHookOutput
@implements_hook("TARGET_HOOK_NAME", 1)
def custom_hook(input_dict: RepokidHookInput) -> RepokidHookOutput:
"""Hook functions are called with a dict containing the keys listed above based on the target hook.
Any mutations made to the input and returned in the output will be passed on to subsequent hook funtions.
"""
...
フック実装の例は repokid.hooks.loggers にあります。
カスタムフィルターを作成して、ロールをリポジトリ対象から除外できます。フィルターは以下のインターフェースに準拠する必要があります:
from repokid.filters import Filter
from repokid.types import RepokidFilterConfig
from repokid.role import RoleList
class CustomFilterName(Filter):
def __init__(self, config: RepokidFilterConfig = None) -> None:
"""Filters are initialized with a dict containing the contents of `filter_config.FilterName`
from the config file. This example would be initialized with `filter_config.CustomFilterName`.
The configuration can be accessed via `self.config`
If you don't need any custom initialization logic, you can leave this function out of your
filter class.
"""
super().__init__(config=config)
# custom initialization logic goes here
...
def apply(self, input_list: RoleList) -> RoleList:
"""Determine roles to be excluded and return them as a RoleList"""
...
簡単なフィルターの実装は repokid.filters.age にあります。より複雑な例は repokid.blocklist.age にあります。
Repokid が設定されたら、次のように使用します:
repokid update_role_cache <ACCOUNT_NUMBER>repokid display_role_cache <ACCOUNT_NUMBER>repokid display_role <ACCOUNT_NUMBER> <ROLE_NAME>repokid repo_role <ACCOUNT_NUMBER> <ROLE_NAME>repokid repo_all_roles <ACCOUNT_NUMBER> -c今すぐリポジトリを実行する代わりに、スケジュールすることもできます(schedule_repo コマンド)。スケジュールから実行可能になるまでの期間は設定可能ですが、デフォルトではスケジュールから 7 日後にロールをリポジトリできます。その後、repo_scheduled_roles コマンドを実行すると、スケジュール済みのロールのみをリポジトリできます。
特定の権限が特に危険であると判断したとします。ここでは例として s3:PutObjectACL を使用します。Repokid を使用して、この権限を持つすべてのロール(ワイルドカードに隠れているものも含む)を見つけ、その単一の権限だけを削除できます。
検索と削除:
repokid find_roles_with_permissions <permission>... [--output=ROLE_FILE]repokid remove_permissions_from_roles --role-file=ROLE_FILE <permission>... [-c]例:
$ repokid find_roles_with_permissions "s3:putobjectacl" "sts:assumerole" --output=myroles.json
...
$ repokid remove_permissions_from_roles --role-file=myroles.json "s3:putobjectacl" "sts:assumerole" -c
Repokid は、認識しているインラインポリシーの各バージョンのコピーを保存します。これらは、update_role_cache 中に異なるバージョンのポリシーが見つかった場合や、リポジトリアクションが発生するたびに追加されます。以前のバージョンを復元するには、次のコマンドを実行します:
ロールのすべてのバージョンを表示: repokid rollback_role <ACCOUNT_NUMBER> <ROLE_NAME>
特定のバージョンを復元: repokid rollback_role <ACCOUNT_NUMBER> <ROLE_NAME> --selection=<NUMBER> -c
Repokid は、各ロールの権限の総数を保持します。統計は update_role_cache または repo_role アクションが発生するたびに追加されます。すべての統計を CSV ファイルに出力するには、repokid repo_stats <OUTPUT_FILENAME> を実行します。オプションでアカウント番号を指定すると、特定のアカウントのみの統計を出力できます。
v0.14.2の新機能
Repokid は repokid.lib モジュールを使用してライブラリとして呼び出すことができます:
from repokid.lib import display_role, repo_role, update_role_cache
account_number = "123456789012"
display_role(account_number, "superCoolRoleName")
update_role_cache(account_number)
repo_role(account_number, "superCoolRoleName", commit=True)
Repokid Dispatcher は、キュー上のメッセージをリッスンしてアクションを実行するように設計されています。現在のアクションは次のとおりです:
Repokid は、設定可能な SNS トピックで成功または失敗に関する情報を応答します。Dispatcher コンポーネントは、組織全体でのリポジトリライフサイクルの運用を支援するために存在します。キューを開発者に直接公開することも選択できますが、ロールバックは注意して行わないと破壊的なアクションになる可能性があるため、保護する方が適切です。
バージョニングは setupmeta によって処理されます。新しいリリースを作成するには:
python setup.py version --bump patch --push
# Inspect output and make sure it's what you expect
# If all is well, commit and push the new tag:
python setup.py version --bump patch --push --commit
| フック名 | コンテキスト |
|---|
AFTER_REPO | role, errors |
AFTER_REPO_ROLES | roles, errors |
BEFORE_REPO_ROLES | account_number, roles |
AFTER_SCHEDULE_REPO | roles |
DURING_REPOABLE_CALCULATION | role_id, arn, account_number, role_name, potentially_repoable_permissions, minimum_age |
DURING_REPOABLE_CALCULATION_BATCH | role_batch, potentially_repoable_permissions, minimum_age |