
Ferramenta de coleta de inventário AWS multithread com foco em recursos e metadados relevantes para segurança.
Uma ferramenta de coleta de inventário multi-thread focada em segurança AWS, escrita em Ruby.
Esta ferramenta foi criada para facilitar a coleta eficiente de uma grande quantidade de atributos e metadados de recursos AWS. Seu objetivo é coletar quase tudo que seja relevante para a configuração de segurança e postura de um ambiente AWS.
Ferramentas existentes (ex.: AWS Config) que realizam algum tipo de coleta de recursos não possuem a cobertura e especificidade necessárias para medir com precisão a postura de segurança (ex.: dados detalhados de atributos de recursos, documentos de política totalmente analisados e relacionamentos aninhados entre recursos).
O AWS Recon lida com a coleta de grandes contas utilizando retentativas automáticas (seja por confiabilidade de rede ou limitação de API), paginação automática de respostas grandes (> 100 recursos por chamada de API) e solicitações paralelas multi-thread para acelerar a coleta.
** o uso não implica endosso
O AWS Recon precisa de uma função ou credenciais de conta AWS com ReadOnlyAccess. AdministratorAccess total é excessivamente privilegiado, mas também funcionará. A política SecurityAudit não é suficiente, pois omite acesso a muitos serviços.
Use Docker versão 19.x ou superior para executar a imagem pré-construída sem precisar instalar nada.
Se você já tem Ruby instalado (2.6.x ou 2.7.x), pode instalar a gem Ruby.
O AWS Recon pode ser executado localmente via um contêiner Docker ou instalando a gem Ruby.
Para executar via um contêiner Docker, passe as credenciais AWS necessárias no comando docker run. Por exemplo:
$ docker run -t --rm \
-e AWS_REGION \
-e AWS_ACCESS_KEY_ID \
-e AWS_SECRET_ACCESS_KEY \
-e AWS_SESSION_TOKEN \
-v $(pwd)/output.json:/recon/output.json \
darkbitio/aws_recon:latest \
aws_recon -v -s EC2 -r global,us-east-1,us-east-2
Para executar localmente, primeiro instale a gem:
$ gem install aws_recon
Fetching aws_recon-0.5.17.gem
Fetching aws-sdk-3.0.1.gem
Fetching parallel-1.20.1.gem
...
Successfully installed aws-sdk-3.0.1
Successfully installed parallel-1.20.1
Successfully installed aws_recon-0.5.17
Ou adicione ao seu Gemfile usando bundle:
$ bundle add aws_recon
Fetching gem metadata from https://rubygems.org/
Resolving dependencies...
...
Using aws-sdk 3.0.1
Using parallel-1.20.1
Using aws_recon 0.5.17
O AWS Recon aproveitará qualquer credencial AWS (veja requisitos) disponível no ambiente em que é executado. Se você estiver coletando de várias contas, pode ser útil usar algo como aws-vault para gerenciar diferentes credenciais.
$ aws-vault exec profile -- aws_recon
Variáveis de ambiente simples também funcionarão.
$ AWS_PROFILE=<profile> aws_recon
Para executar de um contêiner Docker usando credenciais gerenciadas por aws-vault (saída para stdout):
$ aws-vault exec <vault_profile> -- docker run -t --rm \
-e AWS_REGION \
-e AWS_ACCESS_KEY_ID \
-e AWS_SECRET_ACCESS_KEY \
-e AWS_SESSION_TOKEN \
darkbitio/aws_recon:latest \
aws_recon -j -s EC2 -r global,us-east-1,us-east-2
Para executar de um contêiner Docker usando credenciais gerenciadas por aws-vault e salvar a saída em um arquivo, você precisará atender a alguns requisitos. Primeiro, o Docker precisa ter acesso ao caminho que você especificar (ou um caminho pai acima dele). Segundo, você precisa criar um arquivo vazio para salvar a saída (ex.: output.json). Isso ocorre porque apenas esse arquivo é montado no contêiner Docker em tempo de execução. Por exemplo:
Crie um arquivo vazio.
$ touch output.json
Execute o contêiner aws_recon, especificando o arquivo de saída.
$ aws-vault exec <vault_profile> -- docker run -t --rm \
-e AWS_REGION \
-e AWS_ACCESS_KEY_ID \
-e AWS_SECRET_ACCESS_KEY \
-e AWS_SESSION_TOKEN \
-v $(pwd)/output.json:/recon/output.json \
darkbitio/aws_recon:latest \
aws_recon -s EC2 -v -r global,us-east-1,us-east-2
Você pode querer usar a flag -v ou --verbose inicialmente para ver o status e a atividade enquanto a coleta está em execução.
No modo verbose, a saída do console mostrará:
<thread>.<region>.<service>.<operation>
O prefixo t indica em qual thread uma solicitação específica está sendo executada. Região, serviço e operação indicam qual operação de solicitação está em andamento e onde.
$ aws_recon -v
t0.global.EC2.describe_account_attributes
t2.global.S3.list_buckets
t3.global.Support.describe_trusted_advisor_checks
t2.global.S3.list_buckets.acl
t5.ap-southeast-1.WorkSpaces.describe_workspaces
t6.ap-northeast-1.Lightsail.get_instances
...
t2.us-west-2.WorkSpaces.describe_workspaces
t1.us-east-2.Lightsail.get_instances
t4.ap-southeast-1.Firehose.list_delivery_streams
t7.ap-southeast-1.Lightsail.get_instances
t0.ap-south-1.Lightsail.get_instances
t1.us-east-2.Lightsail.get_load_balancers
t7.ap-southeast-2.WorkSpaces.describe_workspaces
t2.eu-west-3.SageMaker.list_notebook_instances
t3.eu-west-2.SageMaker.list_notebook_instances
Finalizado em 46 segundos. Salvando recursos em output.json.
# coletar recursos globais do S3 e EC2, além de us-east-1 e us-east-2
$ AWS_PROFILE=<profile> aws_recon -s S3,EC2 -r global,us-east-1,us-east-2
# coletar recursos globais do S3 e EC2, além de us-east-1 e us-east-2
$ AWS_PROFILE=<profile> aws_recon --services S3,EC2 --regions global,us-east-1,us-east-2
# salvar saída em bucket S3
$ AWS_PROFILE=<profile> aws_recon \
--services S3,EC2 \
--regions global,us-east-1,us-east-2 \
--verbose \
--s3-bucket my-recon-bucket
# salvar saída em bucket S3 com uma região inicial diferente de us-east-1
$ AWS_PROFILE=<profile> aws_recon \
--services S3,EC2 \
--regions global,us-east-1,us-east-2 \
--verbose \
--s3-bucket my-recon-bucket:us-west-2
Exemplo de saída formatada para OpenCSPM (NDJSON).
$ AWS_PROFILE=<profile> aws_recon -l \
-s S3,EC2 \
-r global,us-east-1,us-east-2 \
-f custom
ou
$ AWS_PROFILE=<profile> aws_recon -j \
-s S3,EC2 \
-r global,us-east-1,us-east-2 \
-f custom > output.json
Exceções de API relacionadas a permissões são ignoradas silenciosamente na maioria dos casos. Esses erros geralmente são devidos a um dos seguintes casos:
No modo verbose, você verá logs de exceção na saída:
t2.us-east-1.EC2.describe_subnets.0
t4.us-east-1.SSM.describe_instance_information.0
t6.us-east-1.SecurityHub.InvalidAccessException <-----
t2.us-east-1.EC2.describe_addresses.0
t4.us-east-1.SSM.describe_parameters.0
t1.us-east-1.GuardDuty.list_detectors.0
Use a opção -q para relançar essas exceções, facilitando a solução de problemas de acesso.
Traceback (most recent call last):
arn:aws:sts::1234567890:assumed-role/role/my-audit-role is not authorized to perform:
codepipeline:GetPipeline on resource: arn:aws:codepipeline:us-west-2:1234567890:pipeline
(Aws::CodePipeline::Errors::AccessDeniedException)
A operação exata da API que acionou a exceção é indicada na última linha do stack trace. Se não for possível resolver o acesso necessário, você deve excluir esses serviços com -x ou --not-services, ou omitir a opção -q para que a coleta possa continuar.
O AWS Recon usa múltiplas threads para tentar superar alguns dos desafios de E/S ao realizar muitas chamadas de API para endpoints em todo o mundo.
Para serviços globais como IAM, Shield e Support, as solicitações não são multi-thread. O módulo S3 é multi-thread, pois cada bucket requer várias chamadas adicionais para coletar metadados completos.
Para serviços regionais, uma thread (até o limite de threads) é criada para cada serviço em uma região. Por padrão, até 8 threads são usadas. Se sua conta tiver recursos distribuídos em muitas regiões, você poderá notar uma melhoria de velocidade aumentando as threads com -t X, onde X é o número de threads.
O AWS Recon fará um mínimo de ~2.000 chamadas de API em uma conta nova/vazia, apenas para consultar os serviços suportados em todas as 20 regiões padrão (exceto GovCloud e China). É muito provável que encontre limitação de taxa (throttling) em contas grandes se você habilitar mais threads do que o padrão (8).
O Recon fará automaticamente backoff e respeitará os limites de retentativa na resposta da API. Se você observar pausas longas durante a coleta, provavelmente é isso que está acontecendo. Execute a coleta novamente com a opção -d ou --debug para observar o trace e ver se está sendo limitado. Considere usar menos threads ou solicitar limites de taxa mais altos da AWS se estiver sendo limitado com frequência.
A maioria dos usuários deseja limitar a coleta a serviços e regiões relevantes. Executar sem exclusões tentará coletar todos os recursos de todas as regiões ativadas para a conta.
$ aws_recon -h
AWS Recon - Coletor de Inventário AWS (0.5.17)
Uso: aws_recon [opções]
-r, --regions [REGIÕES] Regiões a serem varridas, separadas por vírgula (padrão: todas)
-n, --not-regions [REGIÕES] Regiões a serem ignoradas, separadas por vírgula (padrão: nenhuma)
-s, --services [SERVIÇOS] Serviços a serem varridos, separados por vírgula (padrão: todos)
-x, --not-services [SERVIÇOS] Serviços a serem ignorados, separados por vírgula (padrão: nenhum)
-c, --config [CONFIG] Especificar arquivo de configuração para serviços e regiões (ex.: config.yaml)
-b, --s3-bucket [BUCKET:REGIÃO] Escrever arquivo de saída em bucket S3 (padrão: '')
-o, --output [SAÍDA] Especificar arquivo de saída (padrão: output.json)
-f, --format [FORMATO] Especificar formato de saída (padrão: aws)
-t, --threads [THREADS] Especificar número máximo de threads (padrão: 8, máximo: 128)
-l, --json-lines Saída no formato NDJSON/JSONL (padrão: falso)
-u, --user-data Coletar dados de usuário de instâncias EC2 (padrão: falso)
-z, --skip-slow Ignorar operações lentas (padrão: falso)
-g, --skip-credential-report Ignorar geração de relatório de credenciais IAM (padrão: falso)
-j, --stream-output Transmitir linhas JSON para stdout (padrão: falso)
-v, --verbose Exibir progresso do cliente e operação atual
-q, --quit-on-exception Parar coleta se um erro de API for encontrado (padrão: falso)
-d, --debug Exibir depuração com informações de trace
-h, --help Exibir estas informações de ajuda
A saída é sempre alguma forma de JSON — linhas JSON ou JSON simples. A saída é escrita em um arquivo (padrão) ou enviada para stdout (com -j).
Ao escrever em um bucket S3, a saída JSON é automaticamente compactada com gzip.
Se você habilitou regiões habilitadas manualmente:
e está usando STS para assumir uma função em uma conta, você precisará ativar tokens STS v2 na conta da qual você está assumindo a função para poder executar o AWS Recon nessas regiões.
Tokens da versão 1 são válidos apenas nas regiões AWS disponíveis por padrão. Esses tokens não funcionam em regiões habilitadas manualmente, como Ásia-Pacífico (Hong Kong). Tokens da versão 2 são válidos em todas as regiões. No entanto, tokens da versão 2 são mais longos e podem afetar sistemas onde você armazena tokens temporariamente.
Se você estiver usando uma chave de acesso/secreta estática, pode coletar dessas regiões independentemente da versão do token STS.
A "cobertura" atual por serviço está listada abaixo. Os serviços sem cobertura serão eventualmente adicionados. PRs são certamente bem-vindos. :)
O AWS Recon tem como objetivo coletar todos os recursos e metadados relevantes para determinar a postura de segurança da(s) sua(s) conta(s) AWS. No entanto, ele não examina os recursos em si quanto à postura de segurança — essa é a tarefa de outras ferramentas que usam a saída do AWS Recon como entrada.
Uma das principais motivações para o AWS Recon foi construir uma ferramenta fácil de manter e estender. Se você acha que a cobertura poderia ser melhorada para um serviço específico, recebemos PRs para esse fim. Qualquer pessoa com familiaridade moderada com Ruby será capaz de imitar o padrão usado pelos coletores existentes para consultar um serviço específico e adicionar os resultados à coleção de recursos.
Clone este repositório:
$ git clone [email protected]:darkbitio/aws-recon.git
$ cd aws-recon
Crie um gemset fixo se estiver usando RVM:
$ rvm use 2.7.2@aws_recon_dev --create --ruby-version
Execute bin/setup para instalar as dependências. Em seguida, execute rake test para rodar os testes. Você também pode executar bin/console para um prompt interativo que permitirá experimentar.
Para instalar esta gem em sua máquina local, execute bundle exec rake install. Para lançar uma nova versão, atualize o número da versão em version.rb e, em seguida, execute bundle exec rake release, que criará uma tag git para a versão, enviará commits e tags git, e enviará o arquivo .gem para rubygems.org.
O AWS Recon foi inspirado pelo excelente trabalho das pessoas e equipes por trás destas ferramentas: