
AWS Menor Privilégio para Implantação Distribuída e de Alta Velocidade
O Repokid usa o Access Advisor fornecido pelo Aardvark para remover permissões que concedem acesso a serviços não utilizados das políticas inline de funções IAM em uma conta AWS.
mkvirtualenv repokid
git clone [email protected]:Netflix/repokid.git
cd repokid
pip install -e .
repokid config config.json
Você precisará de uma tabela DynamoDB chamada repokid_roles (especifique conta e endpoint em dynamo_db no arquivo de configuração).
A tabela deve ter as seguintes propriedades:
RoleId (string) como chave de partição primária, sem chave de ordenação primáriaAccount com uma chave de partição primária Account e RoleId e Account como atributos projetadosRoleName com uma chave de partição primária RoleName e RoleId e RoleName como atributos projetadosPara desenvolvimento, você pode executar o dynamo localmente.
Para executar localmente:
docker-compose up
O endpoint para o DynamoDB será http://localhost:8000. Um painel de administração do DynamoDB pode ser encontrado em http://localhost:8001.
Se você executar a versão de desenvolvimento, a tabela e o índice serão criados automaticamente para você.
O Repokid precisa de uma função IAM em cada conta que será consultada. Além disso, o Repokid precisa ser iniciado com uma função ou usuário que possa chamar sts:AssumeRole nas funções das diferentes contas.
RepokidInstanceProfile:
sts:AssumeRole em todas as RepokidRoles.repokid_roles e todos os índices (especificados na subseção assume_role de dynamo_db no config) e a capacidade de executar dynamodb:ListTablesRepokidRole:
RepokidInstanceProfile.connection_iam no arquivo de configuração.{
"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": "*"
}
]
}
Portanto, se você está monitorando n contas, sempre precisará de n+1 funções. (n RepokidRoles e 1 RepokidInstanceProfile).
Executar repokid config config.json cria um arquivo que você precisará editar. Encontre e atualize estes campos:
dynamodb: Se estiver usando dynamo localmente, defina o endpoint como http://localhost:8010. Se estiver usando dynamo hospedado na AWS, defina region, assume_role e account_number.aardvark_api_location: A localização da sua API REST Aardvark. Algo como https://aardvark.yourcompany.net/api/1/advisorsconnection_iam: Defina assume_role como RepokidRole, ou como você a chamou.O Repokid usa filtros para decidir quais funções são candidatas a serem reduzidas. Os filtros podem ser configurados para se adequar ao seu ambiente, conforme descrito abaixo.
Funções podem ser excluídas adicionando-as ao filtro Blocklist. Uma razão comum para excluir uma função é se a carga de trabalho correspondente realiza ações ocasionais que podem não ter sido observadas, mas são conhecidas como necessárias. Há duas maneiras de excluir uma função:
filter_config.BlocklistFilter.allfilter_config.BlocklistFilter.<NUMERO_DA_CONTA>As listas de bloqueio também podem ser mantidas em um arquivo S3 blocklist. Elas devem estar no seguinte formato:
{
"arns": ["arn1", "arn2"],
"names": {"role_name_1": ["all", "account_number_1"], "role_name_2": ["account_number_2", "account_number_3"]}
}
Se você preferir reduzir apenas determinadas funções, pode usar o Filtro Exclusivo. Talvez você queira considerar apenas funções usadas em produção ou por certas equipes.
Para selecionar funções para redução, você pode listar seus nomes nos arquivos de configuração. Padrões glob no estilo Shell também são suportados.
A seleção de funções pode ser especificada por conta individual ou globalmente.
Para ativar este filtro, coloque "repokid.filters.exclusive:ExclusiveFilter" na seção active_filters do arquivo de configuração.
Para configurá-lo, você pode começar com o arquivo de configuração gerado automaticamente, que possui um exemplo de configuração na seção "filter_config":
"ExclusiveFilter": {
"all": [
"<PADRAO_GLOB>"
],
"<NUMERO_DA_CONTA>": [
"<PADRAO_GLOB>"
]
}
Por padrão, o filtro de idade exclui funções com menos de 90 dias. Para alterar isso, edite a configuração:
filter_config.AgeFilter.minimum_age.
Novos filtros podem ser criados para apoiar a lógica interna. Na Netflix, temos vários que são específicos para nossos
casos de uso. Para ativá-los, certifique-se de que estejam no caminho Python e adicione-os no config à lista na
seção active_filters.
O Repokid é extensível através de hooks que são chamados antes, durante e depois de várias operações, conforme listado abaixo.
Os hooks devem aderir à seguinte interface:
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:
"""As funções de hook são chamadas com um dicionário contendo as chaves listadas acima com base no hook alvo.
Quaisquer mutações feitas na entrada e retornadas na saída serão passadas para funções de hook subsequentes.
"""
...
Exemplos de implementações de hooks podem ser encontrados em repokid.hooks.loggers.
Filtros personalizados podem ser escritos para excluir funções de serem reduzidas. Os filtros devem aderir à seguinte interface:
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:
"""Os filtros são inicializados com um dicionário contendo o conteúdo de `filter_config.FilterName`
do arquivo de configuração. Este exemplo seria inicializado com `filter_config.CustomFilterName`.
A configuração pode ser acessada via `self.config`
Se você não precisar de lógica de inicialização personalizada, pode deixar esta função de fora da sua
classe de filtro.
"""
super().__init__(config=config)
# lógica de inicialização personalizada vai aqui
...
def apply(self, input_list: RoleList) -> RoleList:
"""Determina funções a serem excluídas e as retorna como um RoleList"""
...
Uma implementação simples de filtro pode ser encontrada em repokid.filters.age. Um exemplo mais complexo está em repokid.blocklist.age.
Uma vez que o Repokid esteja configurado, use-o da seguinte forma:
repokid update_role_cache <NUMERO_DA_CONTA>repokid display_role_cache <NUMERO_DA_CONTA>repokid display_role <NUMERO_DA_CONTA> <NOME_DA_FUNCAO>repokid repo_role <NUMERO_DA_CONTA> <NOME_DA_FUNCAO>repokid repo_all_roles <NUMERO_DA_CONTA> -cEm vez de executar uma redução agora, você pode agendar uma (comando schedule_repo). A duração entre o agendamento e a elegibilidade é configurável, mas por padrão as funções podem ser reduzidas 7 dias após o agendamento. Você pode então executar um comando repo_scheduled_roles para reduzir apenas as funções que já foram agendadas.
Suponha que você considere uma determinada permissão especialmente perigosa no seu ambiente. Aqui usarei s3:PutObjectACL como exemplo. Você pode usar o Repokid para encontrar todas as funções que possuem essa permissão (mesmo aquelas escondidas em um wildcard) e depois remover apenas essa única permissão.
Encontrar e Remover:
repokid find_roles_with_permissions <permissao>... [--output=ARQUIVO_DE_FUNCOES]repokid remove_permissions_from_roles --role-file=ARQUIVO_DE_FUNCOES <permissao>... [-c]Exemplo:
$ 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
O Repokid armazena uma cópia de cada versão das políticas inline que conhece. Estas são adicionadas quando
uma versão diferente de uma política é encontrada durante update_role_cache e sempre que uma ação de redução
ocorre. Para restaurar uma versão anterior, execute:
Ver todas as versões das funções: repokid rollback_role <NUMERO_DA_CONTA> <NOME_DA_FUNCAO>
Restaurar uma versão específica: repokid rollback_role <NUMERO_DA_CONTA> <NOME_DA_FUNCAO> --selection=<NUMERO> -c
O Repokid mantém contagens do total de permissões para cada função. As estatísticas são adicionadas sempre que uma ação update_role_cache ou
repo_role ocorre. Para exportar todas as estatísticas para um arquivo CSV, execute: repokid repo_stats <NOME_DO_ARQUIVO_DE_SAIDA>. Um número de conta opcional pode ser especificado para exportar estatísticas apenas de uma conta específica.
Novo na
v0.14.2
O Repokid pode ser chamado como uma biblioteca usando o 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)
O Repokid Dispatcher foi projetado para ouvir mensagens em uma fila e realizar ações. Até agora, as ações são:
O Repokid responderá em um tópico SNS configurável com informações sobre sucessos ou falhas. O componente Dispatcher existe para ajudar na operacionalização do ciclo de vida de redução em toda a sua organização. Você pode optar por expor a fila diretamente aos desenvolvedores, mas é mais provável que isso deva ser protegido, pois reverter pode ser uma ação destrutiva se não for feita com cuidado.
O versionamento é gerenciado pelo setupmeta. Para criar um novo lançamento:
python setup.py version --bump patch --push
# Inspecione a saída e certifique-se de que é o que você espera
# Se tudo estiver bem, faça commit e envie a nova tag:
python setup.py version --bump patch --push --commit
| Nome do 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 |