A ferramenta CFN-NAG procura padrões em modelos de formação de nuvem que podem indicar infraestrutura insegura. AGORAÇÃO falando, ele procurará:
Para obter mais informações sobre a ferramenta, consulte este post no blog de Stelligent:
Encontrar problemas de segurança no início do processo de desenvolvimento de um modelo de formação de nuvem com "CFN-NAG"
Presumindo rubi> = 2.5.x está instalado, a instalação é apenas uma questão de:
gem install cfn-nagNo MacOS ou Linux, você pode instalar alternativamente com a Brew:
brew install ruby brew-gem
brew gem install cfn-nag Para executar cfn_nag como uma ação na CodePiPeline, você pode implantar através do repositório de aplicativos sem servidor da AWS.
Para executar:
cfn_nag_scan --input-path < path to cloudformation json > O caminho pode ser um diretório ou um modelo específico. Se for um diretório, todos os arquivos .json, .template , .yml e .yaml serão processados, incluindo o recurso em subdiretos.
O formato de saída padrão é o texto de forma livre, mas a saída JSON pode ser selecionada com o sinalizador --output-format json .
Opcionalmente, um sinalizador --debug despejará informações sobre os internos do carregamento de regras.
Execute com --help para obter uma lista completa de comutadores suportados.
Para ver uma lista de todas as regras que o CFN-NAG suporta atualmente, existe um utilitário de linha de comando que os despejará para Stdout:
cfn_nag_rules Um Dockerfile é fornecido por conveniência. Ele é publicado no DockerHub como stelligent/cfn_nag .
https://hub.docker.com/r/stelligent/cfn_nag
Você também pode construí -lo localmente.
docker build -t stelligent/cfn_nag .Você pode montar um diretório local que contém modelos no recipiente do docker e depois ligar para CFN_NAG no contêiner. Este exemplo usa os modelos de teste usados no teste de unidade CFN_NAG:
$ docker run -v ` pwd ` /spec/test_templates:/templates -t stelligent/cfn_nag /templates/json/efs/filesystem_with_encryption.json
{
" failure_count " : 0,
" violations " : [
]
}
$ docker run -v ` pwd ` /spec/test_templates:/templates -t stelligent/cfn_nag /templates/json/efs/filesystem_with_no_encryption.json
{
" failure_count " : 1,
" violations " : [
{
" id " : " F27 " ,
" type " : " FAIL " ,
" message " : " EFS FileSystem should have encryption enabled " ,
" logical_resource_ids " : [
" filesystem "
]
}
]
} cfn_nag_scan pode ser executado como parte de um fluxo de trabalho do GitHub para avaliar o código durante os pipelines de integração contínua.
No seu arquivo de fluxo de trabalho do GitHub, crie uma etapa que use a ação CFN_NAG:
- name : Simple test
uses : stelligent/cfn_nag@master
with :
input_path : testsMais informações sobre a ação do GitHub podem ser encontradas aqui.
O CFN-NAG suporta a noção de um "perfil", que é efetivamente uma lista de regras de permitir. O perfil é um arquivo de texto que deve conter um identificador de regra por linha. Quando especificado pelo argumento da linha de comando --profile-path , o CFN-NAG retornará apenas violações dessas regras específicas.
A motivação por trás da criação de um "perfil" é que diferentes desenvolvedores podem se importar com regras diferentes. Por exemplo, um "infraestrutura_developer" pode se importar com as regras do IAM, enquanto um "app_developer" pode nem ser capaz de criar recursos do IAM e, portanto, não se importar com essas regras.
Aqui está um exemplo de perfil:
F1
F2
F27
W3
W5
A lista de negação é basicamente o oposto do perfil: é uma lista de regras nunca se aplicar. Quando especificado através do argumento da linha de comando --deny-list-path , o CFN-NAG nunca retornará violações dessas regras específicas especificadas no arquivo.
Caso uma regra seja especificada em ambos, a lista de nega terá prioridade sobre o perfil e a regra não será aplicada.
O formato é o seguinte. Os únicos dois campos salientes são RulesToSuppress e o id por item. O reason não será interpretado pelo CFN-NAG, mas é recomendável justificar e documentar por que a regra nunca deve ser aplicada.
RulesToSuppress :
- id : W3
reason : W3 is something we never care about at enterprise X No caso de haver uma regra que você deseja suprimir, uma chave Metadata cfn_nag pode ser adicionada ao recurso afetado para dizer ao CFN_NAG para não levantar uma falha ou aviso para essa regra.
Por exemplo, se você estiver configurando um cotovelado voltado para o público que está aberto a conexões de entrada da Internet com recursos como os seguintes:
public_alb.yaml
# Partial template
PublicAlbSecurityGroup :
Properties :
GroupDescription : ' Security group for a public Application Load Balancer '
VpcId :
Ref : vpc
Type : AWS::EC2::SecurityGroup
PublicAlbSecurityGroupHttpIngress :
Properties :
CidrIp : 0.0.0.0/0
FromPort : 80
GroupId :
Ref : PublicAlbSecurityGroup
IpProtocol : tcp
ToPort : 80
Type : AWS::EC2::SecurityGroupIngressCFN_NAG levantará avisos como o seguinte:
$ cfn_nag_scan -i public_alb.yaml
------------------------------------------------------------
public_alb.yaml
------------------------------------------------------------------------------------------------------------------------
| WARN W9
|
| Resources: [ " PublicAlbSecurityGroup " ]
|
| Security Groups found with ingress cidr that is not /32
------------------------------------------------------------
| WARN W2
|
| Resources: [ " PublicAlbSecurityGroup " ]
|
| Security Groups found with cidr open to world on ingress. This should never be true on instance. Permissible on ELB
Failures count: 0
Warnings count: 2Ao adicionar os metadados, esses avisos podem ser suprimidos:
public_alb_with_suppression.yaml
# Partial template
PublicAlbSecurityGroup :
Properties :
GroupDescription : ' Security group for a public Application Load Balancer '
VpcId :
Ref : vpc
Type : AWS::EC2::SecurityGroup
Metadata :
cfn_nag :
rules_to_suppress :
- id : W9
reason : " This is a public facing ELB and ingress from the internet should be permitted. "
- id : W2
reason : " This is a public facing ELB and ingress from the internet should be permitted. "
PublicAlbSecurityGroupHttpIngress :
Properties :
CidrIp : 0.0.0.0/0
FromPort : 80
GroupId :
Ref : PublicAlbSecurityGroup
IpProtocol : tcp
ToPort : 80
Type : AWS::EC2::SecurityGroupIngress $ cfn_nag_scan -i public_alb_with_suppression.yaml
------------------------------------------------------------
public_alb_with_supression.yaml
------------------------------------------------------------
Failures count: 0
Warnings count: 0Os parâmetros do modelo CloudFormation podem apresentar um problema para análise estática, pois os valores são especificados no ponto de implantação. Em outras palavras, os valores não estão disponíveis quando a análise estática é feita - a análise estática só pode olhar para o "código" que está na frente dele. Portanto, uma regra de entrada do grupo de segurança de 0.0.0.0/0 não será sinalizada se o CIDR for parametrizado e o 0.0.0.0/0 for passado no tempo de implantação.
Para permitir a verificação dos valores dos parâmetros, um usuário pode especificar os valores dos parâmetros em um arquivo JSON passado na linha de comando para cfn_nag e cfn_nag_scan com o sinalizador --parameter-values-path=<filename/uri> .
O formato do JSON é uma única chave, "Parâmetros", cujo valor é um dicionário com cada mapeamento de pares de chave/valor para os parâmetros:
{
"Parameters" : {
"Cidr" : " 0.0.0.0/0 "
}
}Isso fornecerá "0.0.0.0/0" ao seguinte parâmetro:
Parameters :
Cidr :
Type : String Cuidado que, se houver parâmetros extras no JSON, eles serão silenciosamente ignorados (para permitir que cfn_nag_scan aplique o mesmo JSON em todos os modelos).
Se o JSON estiver malformado ou não atender à especificação acima, a análise falhará com uma violação fatal.
Antes de 0,5.55, as chamadas para FN :: findinMap foram efetivamente ignoradas. O modelo subjacente os deixaria e, portanto, eles apareceriam como valores de hash das regras. Por exemplo: { "Fn::FindInMap" => [map1, key1, key2]}
A partir de 0.5.55, o modelo tentará calcular o valor de uma chamada para encontrar e apresentar esse valor às regras. Esta avaliação suporta chaves que são:
Se a lógica de avaliação não puder descobrir o valor de uma chave, ela não será inadimplente para o comportamento antigo de retornar o hash para toda a expressão.
Também antes de 0,5,55, as chamadas para as pseudofunções da AWS foram efetivamente ignoradas. O modelo subjacente os deixaria e, portanto, eles apareceriam como valores de hash das regras. Por exemplo: {"Ref"=>"AWS::Region"} . Um caso de uso comum é organizar mapeamentos por região; portanto, a avaliação da pseudo -função é importante para melhor apoiar a avaliação do mapa.
A partir de 0.5.55, o modelo apresentará as seguintes pseudofunções da AWS às regras com os valores padrão:
'AWS::URLSuffix' => 'amazonaws.com',
'AWS::Partition' => 'aws',
'AWS::NotificationARNs' => '',
'AWS::AccountId' => '111111111111',
'AWS::Region' => 'us-east-1',
'AWS::StackId' => 'arn:aws:cloudformation:us-east-1:111111111111:stack/stackname/51af3dc0-da77-11e4-872e-1234567db123',
'AWS::StackName' => 'stackname'
Além disso, o usuário final pode substituir o valor fornecido através do mecanismo tradicional de substituição de parâmetros. Por exemplo:
{
"Parameters" : {
"AWS::Region" : " eu-west-1 "
}
}Até a versão 0.4.66 do CFN_NAG, o modelo subjacente não fez nenhum processamento de FN :: se dentro de um modelo. Isso significava que, se uma propriedade tivesse um valor condicional, cabia à regra analisar o FN :: se. Dado que um FN :: Se pudesse aparecer em qualquer lugar, ele criou uma situação de Whack-A-Mole para os desenvolvedores de regras. Na melhor das hipóteses, a lógica da regra poderia ignorar os valores que estavam presumindo que o valor não fosse um hash em primeiro lugar.
Para resolver esse problema, o comportamento padrão do CFN_NAG agora deve substituir o FN :: se pelo resultado verdadeiro. Isso significa por padrão que as regras não inspecionam os falsos resultados quanto a violações de segurança.
Além de substituir o FN :: Se no nível do valor da propriedade, o mesmo comportamento será aplicado ao FN :: se no nível superior das propriedades. Por exemplo:
Resource1 :
Type : Foo
Properties : !If
- IsNone
- Description : Up
- Description : DOwnParecerá o mesmo que:
Resource1 :
Type : Foo
Properties :
Description : Up Para fornecer algum controle sobre esse comportamento, um usuário pode especificar os valores de condição em um arquivo JSON passado na linha de comando para cfn_nag e cfn_nag_scan com o sinalizador --condition-values-path=<filename/uri> .
O formato do JSON é um dicionário de AA com cada par de teclas/valores mapeando para as condições:
{
"Condition1" : true ,
"Condition2" : false
}A base para o SPCM é descrita na métrica de complexidade proposta de postagem do blog para documentos de política da IAM.
Começando na versão 0.6.0 de cfn_nag:
spcm_scan pode digitalizar um diretório de modelos de formação de nuvem (como CFN_NAG_SCAN) e gerar um relatório com as métricas SPCM em formato JSON ou HTMLcfn_nag_scan --rule-arguments spcm_threshold:100--rule-arguments . O objeto de regra precisa apenas declarar um attr_accessor , por exemplo, attr_accessor :spcm_threshold e cfn_nag cuidarão dos detalhes para injetar valores dos- --rule-arguments A liberação de 0.5.x inclui algumas alterações importantes na forma como as regras personalizadas (podem) ser distribuídas e carregadas. Antes desta versão, havia dois lugares onde as regras eram carregadas: o diretório lib/cfn-nag/custom_rules dentro da Gem Core CFN_NAG e o diretório de regra personalizado especificado na linha de comando.
Existem dois casos de uso que forçaram um redesenho de como/onde as regras personalizadas são carregadas. O mecanismo de carregamento de regras foi generalizado, de modo que os repositórios de regras personalizados possam ser usados para descobrir regras.
Um monte de "arquivos de regra" em um sistema de arquivos não é ótimo do ponto de vista tradicional de desenvolvimento de software. Não existe uma versão ou rastreabilidade nesses arquivos, então 0.5.x apresenta a noção de um "cfn_nag regra gem". Um desenvolvedor pode desenvolver regras personalizadas como parte de uma jóia separada, versá -la e instalá -la ... e essas regras são referenciadas de CFN_NAG, desde que os metadados do gem incluam cfn_nag_rules => true . Para uma jóia como "CFN-NAG-HIPAA-RULES", qualquer *.rb sob Lib/CFN-NAG-HIPAA-RULES será carregado. Quaisquer regras personalizadas devem derivar de CFNNAG :: Baserule em CFN-NAG/BASE_RULE ( não CFN-NAG/Custom-Rules/Base). Se a regra deve derivar de outra coisa, definindo um método cfn_nag_rule? Isso retorna true também fará com que seja carregado como regra.
Quando CFN_NAG está sendo executado em um AWS Lambda - não há realmente um sistema de arquivos (além de /TMP) no sentido tradicional. Portanto, apenas as regras principais são utilizáveis do Lambda. Para suportar regras personalizadas, o CFN_NAG suporta a descoberta de regras de um balde S3 em vez do sistema de arquivos.
Tudo o que você provavelmente viu sobre como desenvolver regras personalizadas em Ruby ainda é verdadeira.
Para descobrir regras de um balde S3, crie um arquivo s3.yml com este conteúdo:
---
repo_class_name : S3BucketBasedRuleRepo
repo_arguments :
s3_bucket_name : cfn-nag-rules-my-enterprise
prefix : /rulesPara aplicar os arquivos *regra.rb no bucket cfn-nag-rules-my-a-Enterprise com o prefixo /regras (por exemplo, /rules/mynewrule.rb), especifique esse arquivo na linha de comando para cfn_nag como tal:
cat my_cfn_template.yml | cfn_nag --rule-repository s3.yml Se as regras estiverem em mais de um balde, crie vários arquivos S3*.yML e especifique-os no argumento --rule-repository .
Se as credenciais do AWS ambiental tiverem permissão para acessar o balde cfn-nag-rules-enterprise , ele encontrará todas as regras como /rules/*Rule.rb . Se um AWS_PROFILE em particular deve ser usado, adicione -o como uma chave em repo_arguments , por exemplo, aws_profile: my_aws_profile
Além do sistema de arquivos, a GEM instala e o S3 - a nova arquitetura teoricamente suporta o desenvolvimento de outros "repositórios de regras" para carregar regras do DynamoDB, bancos de dados relacionais ou outros serviços da Web.
Para criar novas regras para seu próprio uso e/ou contribuição da comunidade, consulte Desenvolvimento de regras personalizadas para obter detalhes.
Um screencast demonstrando sopa a nozes TDD Custom Recurs Desenvolvimento está disponível aqui:
https://www.youtube.com/watch?v=jrzct0nafd4&t=1601s
Para executar as especificações, você precisa garantir que tenha o Docker instalado e as dependências cfn_nag instaladas via
gem install bundle
bundle install Então, para executar todas as especificações, basta executar rake test:all .
Para executar os testes de ponta a ponta, execute rake test:e2e . O script agrupará todas as gemas no GemFile, construirá e instalará a gem CFN_NAG localmente, instalará dependências especiais e executa testes marcados com 'end_to_end'. Ele também retirará os modelos de amostra fornecidos pela Amazon e executará CFN_NAG_SCAN contra eles, para ver se algum modelo conhecido causa exceções no CFN-NAG.
Para instalar a filial Git atual localmente:
bundle install
scripts/deploy_local.shExiste um ambiente de desenvolvimento remoto completo criado e configurado com todas as ferramentas e configurações pré-configuradas para facilitar o desenvolvimento e a criação de regras. Você pode ativar isso usando a funcionalidade de desenvolvimento remoto de código VS.
Folder contains a dev container configuration file. Reopen folder to develop in a container clique no botão Reopen in Container[Dev Container] cfn_nag DevelopmentMais informações sobre a configuração do desenvolvimento remoto do Código VS podem ser encontradas aqui, vs Code Remote Development.
Para relatar um bug ou solicitar um recurso, envie um problema através do Repositório do Github via: https://github.com/stelligent/cfn_nag/issues/new