
repokid v0.19.8
Moindre privilège AWS pour un déploiement distribué et à haute vélocité
Repokid
Repokid utilise Access Advisor fourni par Aardvark pour supprimer les autorisations donnant accès à des services inutilisés des politiques inline des rôles IAM dans un compte AWS.
Pour commencer
Installation
mkvirtualenv repokid
git clone [email protected]:Netflix/repokid.git
cd repokid
pip install -e .
repokid config config.json
DynamoDB
Vous aurez besoin d'une table DynamoDB appelée repokid_roles (spécifiez le compte et le point de terminaison dans dynamo_db du fichier de configuration).
La table doit avoir les propriétés suivantes :
RoleId(string) comme clé de partition primaire, pas de clé de tri primaire- Un index secondaire global nommé
Accountavec une clé de partition primaireAccountet les attributs projetésRoleIdetAccount - Un index secondaire global nommé
RoleNameavec une clé de partition primaireRoleNameet les attributs projetésRoleIdetRoleName
Pour le développement, vous pouvez exécuter Dynamo localement.
Pour exécuter localement :
docker-compose up
Le point de terminaison pour DynamoDB sera http://localhost:8000. Un panneau d'administration DynamoDB se trouve à http://localhost:8001.
Si vous exécutez la version de développement, la table et l'index seront créés automatiquement pour vous.
Permissions IAM
Repokid a besoin d'un rôle IAM dans chaque compte qui sera interrogé. De plus, Repokid doit être lancé avec un rôle ou un utilisateur capable d'utiliser sts:AssumeRole pour accéder aux différents rôles des comptes.
RepokidInstanceProfile :
- Créez-en un seul.
- Doit être capable d'appeler
sts:AssumeRolesur tous les RepokidRoles. - Permissions DynamoDB pour la table
repokid_roleset tous les index (spécifiés dans la sous-sectionassume_rolededynamo_dbdans la configuration) et la capacité d'exécuterdynamodb:ListTables
RepokidRole :
- Doit exister dans chaque compte géré par repokid.
- Doit avoir une politique de confiance autorisant
RepokidInstanceProfile. - Le nom doit être spécifié dans
connection_iamdu fichier de configuration. - Possède ces autorisations :
{
"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": "*"
}
]
}
Donc si vous surveillez n comptes, vous aurez toujours besoin de n+1 rôles. (n RepokidRoles et 1 RepokidInstanceProfile).
Modification de config.json
L'exécution de repokid config config.json crée un fichier que vous devrez modifier. Trouvez et mettez à jour ces champs :
dynamodb: Si vous utilisez Dynamo localement, définissez le point de terminaison surhttp://localhost:8010. Si vous utilisez Dynamo hébergé par AWS, définissezregion,assume_roleetaccount_number.aardvark_api_location: L'emplacement de votre API REST Aardvark. Quelque chose commehttps://aardvark.yourcompany.net/api/1/advisorsconnection_iam: Définissezassume_rolesurRepokidRole, ou le nom que vous lui avez donné.
Configuration optionnelle
Repokid utilise des filtres pour décider quels rôles sont candidats à être repoés. Les filtres peuvent être configurés pour s'adapter à votre environnement comme décrit ci-dessous.
Filtre de blocage
Les rôles peuvent être exclus en les ajoutant au filtre de blocage. Une raison courante d'exclure un rôle est si la charge de travail correspondante effectue des actions occasionnelles qui n'ont peut-être pas été observées mais qui sont connues comme étant nécessaires. Il y a deux façons d'exclure un rôle :
- Exclure le nom du rôle pour tous les comptes : ajoutez-le à une liste dans la configuration
filter_config.BlocklistFilter.all - Exclure le nom du rôle pour un compte spécifique : ajoutez-le à une liste dans la configuration
filter_config.BlocklistFilter.<NUMERO_COMPTE>
Les listes de blocage peuvent également être maintenues dans un fichier de blocage S3. Elles doivent être sous la forme suivante :
{
"arns": ["arn1", "arn2"],
"names": {"role_name_1": ["all", "account_number_1"], "role_name_2": ["account_number_2", "account_number_3"]}
}
Filtre exclusif
Si vous préférez ne repoer que certains rôles, vous pouvez utiliser le filtre exclusif. Vous voudrez peut-être ne considérer que les rôles utilisés en production ou par certaines équipes. Pour sélectionner les rôles à repoer, vous pouvez lister leurs noms dans les fichiers de configuration. Les motifs glob de type shell sont également pris en charge. La sélection des rôles peut être spécifiée par compte individuel ou globalement. Pour activer ce filtre, mettez "repokid.filters.exclusive:ExclusiveFilter" dans la section active_filters du fichier de configuration. Pour le configurer, vous pouvez commencer par le fichier de configuration autogénéré, qui contient un exemple de configuration dans la section "filter_config" :
"ExclusiveFilter": {
"all": [
"<GLOB_PATTERN>"
],
"<ACCOUNT_NUMBER>": [
"<GLOB_PATTERN>"
]
}
Filtre d'âge
Par défaut, le filtre d'âge exclut les rôles de moins de 90 jours. Pour modifier cela, modifiez le paramètre de configuration : filter_config.AgeFilter.minimum_age.
Filtres actifs
De nouveaux filtres peuvent être créés pour prendre en charge la logique interne. Chez Netflix, nous en avons plusieurs qui sont spécifiques à nos cas d'utilisation. Pour les rendre actifs, assurez-vous qu'ils sont dans le chemin Python et ajoutez-les dans la configuration à la liste de la section active_filters.
Étendre Repokid
Hooks
Repokid est extensible via des hooks qui sont appelés avant, pendant et après diverses opérations comme listé ci-dessous.
| Nom du hook | Contexte |
|---|---|
AFTER_REPO | rôle, erreurs |
AFTER_REPO_ROLES | rôles, erreurs |
BEFORE_REPO_ROLES | numéro_compte, rôles |
AFTER_SCHEDULE_REPO | rôles |
DURING_REPOABLE_CALCULATION | role_id, arn, numéro_compte, nom_rôle, permissions_potentiellement_repoables, âge_minimum |
DURING_REPOABLE_CALCULATION_BATCH | lot_rôles, permissions_potentiellement_repoables, âge_minimum |
Les hooks doivent adhérer à l'interface suivante :
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.
"""
...
Des exemples d'implémentations de hooks peuvent être trouvés dans repokid.hooks.loggers.
Filtres
Des filtres personnalisés peuvent être écrits pour exclure des rôles du repo. Les filtres doivent adhérer à l'interface suivante :
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"""
...
Une implémentation simple de filtre peut être trouvée dans repokid.filters.age. Un exemple plus complexe se trouve dans repokid.blocklist.age.
Comment utiliser
Une fois Repokid configuré, utilisez-le comme suit :
Flux standard
- Mettre à jour le cache des rôles :
repokid update_role_cache <NUMERO_COMPTE> - Afficher le cache des rôles :
repokid display_role_cache <NUMERO_COMPTE> - Afficher les informations sur un rôle spécifique :
repokid display_role <NUMERO_COMPTE> <NOM_ROLE> - Repoer un rôle spécifique :
repokid repo_role <NUMERO_COMPTE> <NOM_ROLE> - Repoer tous les rôles d'un compte :
repokid repo_all_roles <NUMERO_COMPTE> -c
Planification
Plutôt que d'exécuter un repo immédiatement, vous pouvez en planifier un (commande schedule_repo). La durée entre la planification et l'éligibilité est configurable, mais par défaut, les rôles peuvent être repoés 7 jours après la planification. Vous pouvez ensuite exécuter une commande repo_scheduled_roles pour ne repoer que les rôles déjà planifiés.
Cibler une autorisation spécifique
Supposons que vous trouviez une autorisation particulièrement dangereuse dans votre environnement. Ici, je vais utiliser s3:PutObjectACL comme exemple. Vous pouvez utiliser Repokid pour trouver tous les rôles qui ont cette autorisation (même ceux cachés dans un caractère générique), puis supprimer cette seule autorisation.
Rechercher et supprimer :
- Assurez-vous que le cache des rôles est mis à jour avant de commencer.
- Trouver les rôles avec une autorisation donnée :
repokid find_roles_with_permissions <permission>... [--output=FICHIER_ROLES] - Supprimer l'autorisation des rôles :
repokid remove_permissions_from_roles --role-file=FICHIER_ROLES <permission>... [-c]
Exemple :
$ 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
Revenir en arrière
Repokid stocke une copie de chaque version des politiques inline qu'il connaît. Elles sont ajoutées lorsqu'une version différente d'une politique est trouvée lors de update_role_cache et à chaque fois qu'une action de repo a lieu. Pour restaurer une version précédente, exécutez :
Voir toutes les versions des rôles : repokid rollback_role <NUMERO_COMPTE> <NOM_ROLE>
Restaurer une version spécifique : repokid rollback_role <NUMERO_COMPTE> <NOM_ROLE> --selection=<NUMERO> -c
Statistiques
Repokid conserve le nombre total d'autorisations pour chaque rôle. Les statistiques sont ajoutées à chaque fois qu'une action update_role_cache ou repo_role a lieu. Pour exporter toutes les statistiques vers un fichier CSV, exécutez : repokid repo_stats <NOM_FICHIER_SORTIE>. Un numéro de compte optionnel peut être spécifié pour n'exporter que les statistiques d'un compte spécifique.
Bibliothèque
Nouveau dans
v0.14.2
Repokid peut être appelé comme une bibliothèque en utilisant le module 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)
Dispatcher
Le Dispatcher Repokid est conçu pour écouter les messages sur une file d'attente et effectuer des actions. Jusqu'à présent, les actions sont :
- Lister les services repoables d'un rôle
- Définir ou supprimer une exclusion
- Lister et effectuer des rollbacks pour un rôle
Repokid répondra sur un sujet SNS configurable avec des informations sur les succès ou échecs. Le composant Dispatcher existe pour aider à l'opérationnalisation du cycle de vie du repo dans votre organisation. Vous pouvez choisir d'exposer la file d'attente directement aux développeurs, mais il est plus probable qu'elle devrait être protégée car le rollback peut être une action destructive si elle n'est pas faite avec précaution.
Développement
Publication
La gestion des versions est assurée par setupmeta. Pour créer une nouvelle version :
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