
Mínimo privilegio en AWS para despliegue distribuido y de alta velocidad
Repokid utiliza Access Advisor proporcionado por Aardvark para eliminar permisos que otorgan acceso a servicios no utilizados de las políticas inline de roles IAM en una cuenta de AWS.
mkvirtualenv repokid
git clone [email protected]:Netflix/repokid.git
cd repokid
pip install -e .
repokid config config.json
Necesitarás una tabla DynamoDB llamada repokid_roles (especifica la cuenta y el endpoint en dynamo_db del archivo de configuración).
La tabla debe tener las siguientes propiedades:
RoleId (string) como clave de partición primaria, sin clave de ordenación primariaAccount con una clave de partición primaria de Account y RoleId y Account como atributos proyectadosRoleName con una clave de partición primaria de RoleName y RoleId y RoleName como atributos proyectadosPara desarrollo, puedes ejecutar dynamo localmente.
Para ejecutar localmente:
docker-compose up
El endpoint de DynamoDB será http://localhost:8000. Se puede encontrar un panel de administración de DynamoDB en http://localhost:8001.
Si ejecutas la versión de desarrollo, la tabla y el índice se crearán automáticamente.
Repokid necesita un rol IAM en cada cuenta que se consultará. Además, Repokid debe ejecutarse con un rol o usuario que pueda sts:AssumeRole hacia los diferentes roles de las cuentas.
RepokidInstanceProfile:
sts:AssumeRole hacia todos los RepokidRoles.repokid_roles y todos los índices (especificados en la subsección assume_role de dynamo_db en la configuración) y la capacidad de ejecutar dynamodb:ListTablesRepokidRole:
RepokidInstanceProfile.connection_iam en el archivo de configuración.{
"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": "*"
}
]
}
Por lo tanto, si estás monitoreando n cuentas, siempre necesitarás n+1 roles. (n RepokidRoles y 1 RepokidInstanceProfile).
Ejecutar repokid config config.json crea un archivo que necesitarás editar. Busca y actualiza estos campos:
dynamodb: Si usas dynamo localmente, establece el endpoint en http://localhost:8010. Si usas dynamo alojado en AWS, establece region, assume_role y account_number.aardvark_api_location: La ubicación de tu API REST de Aardvark. Algo como https://aardvark.yourcompany.net/api/1/advisorsconnection_iam: Establece assume_role a RepokidRole, o como lo hayas llamado.Repokid utiliza filtros para decidir qué roles son candidatos a ser repoed. Los filtros pueden configurarse para adaptarse a tu entorno como se describe a continuación.
Los roles pueden excluirse añadiéndolos al filtro Blocklist. Una razón común para excluir un rol es si la carga de trabajo correspondiente realiza acciones ocasionales que pueden no haber sido observadas pero se sabe que son necesarias. Hay dos formas de excluir un rol:
filter_config.BlocklistFilter.allfilter_config.BlocklistFilter.<ACCOUNT_NUMBER>Las listas negras también pueden mantenerse en un archivo S3 blocklist. Deben tener la siguiente forma:
{
"arns": ["arn1", "arn2"],
"names": {"role_name_1": ["all", "account_number_1"], "role_name_2": ["account_number_2", "account_number_3"]}
}
Si prefieres repo solo ciertos roles puedes usar el filtro Exclusive. Quizás quieras considerar solo roles utilizados en producción o por ciertos equipos. Para seleccionar roles para repo puedes listar sus nombres en los archivos de configuración. También se admiten patrones glob estilo shell. La selección de roles puede especificarse por cuenta individual o globalmente. Para activar este filtro pon "repokid.filters.exclusive:ExclusiveFilter" en la sección active_filters del archivo de configuración. Para configurarlo puedes comenzar con el archivo de configuración autogenerado, que tiene un ejemplo de configuración en la sección "filter_config":
"ExclusiveFilter": {
"all": [
"<GLOB_PATTERN>"
],
"<ACCOUNT_NUMBER>": [
"<GLOB_PATTERN>"
]
}
Por defecto el filtro de edad excluye roles que tienen menos de 90 días. Para cambiar esto edita la configuración: filter_config.AgeFilter.minimum_age.
Se pueden crear nuevos filtros para soportar lógica interna. En Netflix tenemos varios que son específicos de nuestros casos de uso. Para activarlos, asegúrate de que estén en el path de Python y agrégalos en la configuración a la lista en la sección active_filters.
Repokid es extensible mediante hooks que se llaman antes, durante y después de varias operaciones, como se lista a continuación.
Los hooks deben adherirse a la siguiente interfaz:
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:
"""Las funciones hook son llamadas con un dict que contiene las claves listadas arriba según el hook objetivo.
Cualquier mutación realizada en la entrada y devuelta en la salida será pasada a las siguientes funciones hook.
"""
...
Ejemplos de implementaciones de hooks se pueden encontrar en repokid.hooks.loggers.
Se pueden escribir filtros personalizados para excluir roles de ser repoed. Los filtros deben adherirse a la siguiente interfaz:
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:
"""Los filtros se inicializan con un dict que contiene el contenido de `filter_config.FilterName`
del archivo de configuración. Este ejemplo se inicializaría con `filter_config.CustomFilterName`.
La configuración se puede acceder via `self.config`
Si no necesitas lógica de inicialización personalizada, puedes omitir esta función en tu
clase de filtro.
"""
super().__init__(config=config)
# la lógica de inicialización personalizada va aquí
...
def apply(self, input_list: RoleList) -> RoleList:
"""Determina los roles a ser excluidos y los devuelve como un RoleList"""
...
Una implementación simple de filtro se puede encontrar en repokid.filters.age. Un ejemplo más complejo está en repokid.blocklist.age.
Una vez configurado Repokid, úsalo de la siguiente manera:
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> -cEn lugar de ejecutar un repo ahora mismo, puedes programar uno (comando schedule_repo). La duración entre la programación y la elegibilidad es configurable, pero por defecto los roles pueden ser repoed 7 días después de la programación. Luego puedes ejecutar un comando repo_scheduled_roles para repo solo roles que ya han sido programados.
Supón que encuentras un permiso dado especialmente peligroso en tu entorno. Aquí usaré s3:PutObjectACL como ejemplo. Puedes usar Repokid para encontrar todos los roles que tienen este permiso (incluso aquellos ocultos en un comodín), y luego eliminar solo ese permiso único.
Buscar y Eliminar:
repokid find_roles_with_permissions <permission>... [--output=ROLE_FILE]repokid remove_permissions_from_roles --role-file=ROLE_FILE <permission>... [-c]Ejemplo:
$ 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 almacena una copia de cada versión de las políticas inline que conoce. Estas se agregan cuando se encuentra una versión diferente de una política durante update_role_cache y cada vez que ocurre una acción de repo. Para restaurar una versión anterior ejecuta:
Ver todas las versiones de roles: repokid rollback_role <ACCOUNT_NUMBER> <ROLE_NAME>
Restaurar una versión específica: repokid rollback_role <ACCOUNT_NUMBER> <ROLE_NAME> --selection=<NUMBER> -c
Repokid mantiene conteos de los permisos totales para cada rol. Las estadísticas se agregan cada vez que ocurre una acción update_role_cache o repo_role. Para exportar todas las estadísticas a un archivo CSV ejecuta: repokid repo_stats <OUTPUT_FILENAME>. Se puede especificar un número de cuenta opcional para exportar estadísticas solo para una cuenta específica.
Nuevo en
v0.14.2
Repokid puede ser llamado como biblioteca usando el módulo 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 está diseñado para escuchar mensajes en una cola y realizar acciones. Hasta ahora las acciones son:
Repokid responderá en un tema SNS configurable con información sobre cualquier éxito o fallo. El componente Dispatcher existe para ayudar con la operacionalización del ciclo de vida de repo en toda tu organización. Puedes optar por exponer la cola directamente a los desarrolladores, pero es más probable que esto deba protegerse porque revertir puede ser una acción destructiva si no se hace con cuidado.
El versionado es manejado por setupmeta. Para crear una nueva versión:
python setup.py version --bump patch --push
# Inspecciona la salida y asegúrate de que es lo que esperas
# Si todo está bien, haz commit y push del nuevo tag:
python setup.py version --bump patch --push --commit
| Nombre del hook | Contexto |
|---|
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 |