
Ferramenta de análise estática e visualização de RBAC do Kubernetes
Análise RBAC do Kubernetes simplificada
Krane é uma ferramenta simples de análise estática de RBAC do Kubernetes. Ela identifica potenciais riscos de segurança no design de RBAC do K8s e sugere maneiras de mitigá-los. O painel do Krane apresenta a postura atual de segurança do RBAC e permite navegar pela sua definição.
Você pode começar com o Krane instalando-o via chart Helm no cluster Kubernetes de destino ou executando-o localmente com Docker.
Presume-se que você tenha o Helm CLI instalado em sua máquina.```sh $ helm repo add appvia https://appvia.github.io/krane $ helm repo update $ helm install krane appvia/krane --namespace krane --create-namespace
Siga a saída da instalação do Helm chart para saber como fazer port-forward do dashboard do Krane.
### Executar com Docker
Presume-se que você tenha o [docker](https://docs.docker.com/get-docker/) em execução na sua máquina local. Instale o [docker-compose](https://docs.docker.com/compose/install/#install-compose) se ainda não o fez.
O Krane depende do RedisGraph. A stack `docker-compose` define tudo o que é necessário para construir e executar o serviço _Krane_ localmente. Ela também cuidará da sua dependência [RedisGraph](https://oss.redislabs.com/redisgraph/).```
docker-compose up -d
A imagem docker do Krane será pré-construída automaticamente se ainda não estiver presente na máquina local.
Observe que ao executar docker-compose localmente, o Krane não iniciará o report e o dashboard do RBAC automaticamente. Em vez disso, o contêiner ficará em espera por 24h por padrão - esse valor pode ser ajustado em docker-compose.override.yml. Execute comandos dentro de um contêiner Krane em execução. O docker-compose local também montará o kube config (~/.kube/config) dentro do contêiner, permitindo que você execute relatórios em qualquer cluster Kubernetes ao qual você já tenha acesso.
Execute dentro de um contêiner Krane em execução.```sh docker-compose exec krane bash
Assim que estiver no contêiner, você pode começar a usar comandos `krane`. Experimente `krane -help`.```sh
krane -h
Para inspecionar quais serviços estão sendo executados e as portas associadas:``` docker-compose ps
Para interromper o _Krane_ e seus serviços de dependência:```
docker-compose down
$ krane --help
NAME:
krane
DESCRIPTION:
Kubernetes RBAC static analysis & visualisation tool
COMMANDS:
dashboard Start K8s RBAC dashboard server
help Display global or [command] help documentation
report Run K8s RBAC report
GLOBAL OPTIONS:
-h, --help
Display help documentation
-v, --version
Display version information
-t, --trace
Display backtrace when an error occurs
AUTHOR:
Marcin Ciszak <[email protected]> - Appvia Ltd <appvia.io>
### Gerar relatório RBAC
#### Com contexto `kubectl` local
Para executar um relatório contra um cluster em execução, você deve fornecer um contexto _kubectl_```
krane report -k <context>
You may also pass -c <cluster-name> flag se você planeja executar a ferramenta contra múltiplos clusters e indexar o gráfico RBAC separadamente para cada nome de cluster.
Para executar um relatório contra arquivos RBAC yaml/json locais, forneça um caminho de diretório``` krane report -d </path/to/rbac-directory>
NOTA: _Krane_ espera que os seguintes arquivos (em formato YAML ou JSON) estejam presentes no caminho de diretório especificado:
- psp
- roles
- clusterroles
- rolebindings
- clusterrolebindings
Se as Pod Security Policies não estiverem em uso, você pode ignorar a expectativa acima criando um arquivo `psp` manualmente com o seguinte conteúdo:```json
{
"items": []
}
Nota, PodSecurityPolicy foi descontinuada no Kubernetes v1.21 e removida do Kubernetes no v1.25.
Para executar um relatório a partir de um contêiner em execução em um cluster Kubernetes``` krane report --incluster
NOTA: A conta de serviço usada pelo _Krane_ precisará de acesso aos recursos RBAC. Consulte [Prerequisites](https://github.com/appvia/krane/blob/HEAD/k8s/one-time/prerequisites.yaml) para obter detalhes.
#### Na pipeline CI/CD
Para validar a definição RBAC como uma etapa na pipeline CI/CD```
krane report --ci -d </path/to/rbac-directory>
NOTA: O Krane espera que determinada convenção de nomenclatura seja seguida para os arquivos de recursos RBAC armazenados localmente. Veja a seção acima. Para executar comandos krane, é recomendado que o executor de CI referencie a imagem docker quay.io/appvia/krane:latest.
O modo CI é ativado pela flag --ci. O Krane retornará um código de status diferente de zero junto com detalhes das regras de risco violadas quando um ou mais perigos forem detectados.
Para visualizar a árvore de facetas RBAC, o grafo de rede e os resultados mais recentes do relatório, você precisa iniciar o servidor do painel primeiro.``` krane dashboard
A flag de cluster `-c <cluster-name>` pode ser passada se quiser executar o dashboard contra um nome de cluster específico. O dashboard procurará dados relacionados ao nome do cluster especificado que estão em cache no sistema de arquivos.
O comando acima iniciará um servidor web local na porta padrão `8000` e exibirá o link do dashboard.
## Arquitetura
### Dados RBAC indexados em um banco de dados Graph local
_Krane_ indexa entidades RBAC no RedisGraph. Isso nos permite consultar a rede de dependências de forma eficiente e simples usando um subconjunto de [CypherQL](https://oss.redislabs.com/redisgraph/cypher_support/) suportado pelo [RedisGraph](https://oss.redislabs.com/redisgraph/).
#### Esquema

#### Nós
Os seguintes nós são criados no Grafo para os objetos RBAC relevantes:
* `Psp` - Um nó PSP contendo atributos relacionados à política de segurança do pod. Apenas aplicável ao trabalhar com K8s < 1.25.
* `Rule` - O nó Rule representa uma regra de controle de acesso referente aos recursos do Kubernetes.
* `Role` - O nó Role representa um determinado Role ou ClusterRole. O atributo `kind` define o tipo de função.
* `Subject` - Subject representa todos os possíveis atores no cluster (`kind`: User, Group e ServiceAccount)
* `Namespace` - Nó de Namespace do Kubernetes.
#### Arestas
* `:SECURITY` - Define um link entre os nós Rule e Psp. Apenas aplicável ao trabalhar com K8s < 1.25.
* `:GRANT` - Define um link entre Role e Rule associados a esse papel.
* `:ASSIGN` - Define um link entre um Ator (Subject) e um determinado Role/ClusterRole (nó Role).
* `:RELATION` - Define um link entre dois nós Ator (Subject) diferentes.
* `:SCOPE` - Define um link entre os nós Role e Namespace.
* `:ACCESS` - Define um link entre os nós Subject e Namespace.
* `:AGGREGATE` - Define um link entre ClusterRoles (um ClusterRole agrega outro) `A-(aggregates)->B`
* `:COMPOSITE` - Define um link entre ClusterRoles (um ClusterRole pode ser agregado em outro) `A<-(is a composite of)-B`
Todas as arestas são bidirecionais, o que significa que o grafo pode ser consultado em qualquer direção.
As únicas exceções são as relações `:AGGREGATE` e `:COMPOSITE` que são unidirecionais, embora envolvam os mesmos nós de aresta.
#### Consultando o Grafo
Para consultar o grafo diretamente, você pode executar um comando em um container `redisgraph` em execução, iniciar o `redis-cli` e executar suas consultas arbitrárias. Siga as [instruções](https://oss.redislabs.com/redisgraph/) oficiais para exemplos de [comandos](https://oss.redislabs.com/redisgraph/commands/).
Você também pode consultar o Grafo do console do _Krane_. Primeiro, acesse o container _Krane_ em execução e então```ruby
# Start Krane console - this will open interactive ruby shell with Krane code preloaded
console
# Instantiate Graph client
graph = Krane::Clients::RedisGraph.client cluster: 'default'
# Run arbitrary CypherQL query against indexed RBAC Graph
res = graph.query(%Q(
MATCH (r:Rule {resource: "configmaps", verb: "update"})<-[:GRANT]-(ro:Role)<-[:ASSIGN]-(s:Subject)
RETURN s.kind as subject_kind, s.name as subject_name, ro.kind as role_kind, ro.name as role_name))
# Print the results
res.print_resultset
Os bytes de uma chave privada podem ser obtidos da seguinte forma:
# load private key
priv_key = objs["ca-priv-key"] # can be a key loaded from a pem file
pub_key = priv_key.public_key()
# generate bytes
pkcs8_der = priv_key.private_bytes(
encoding=serialization.Encoding.DER,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.NoEncryption(),
)
pkcs8_pem = priv_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.NoEncryption(),
)
Executar o código acima produzirá duas strings de bytes diferentes para a mesma chave privada. Essas duas strings de bytes são tecnicamente intercambiáveis porque representam exatamente a mesma chave privada, mas você não pode simplesmente decodificar uma em base64 para obter a outra. Isso é ótimo para nós, porque ao contornar o AV/EDR, você pode usar uma chave privada em um formato não-PEM, até mesmo em um formato não-PKCS8, dificultando muito que o software de segurança determine que você tem uma chave privada na memória.```
+----------------+--------------------------------+-----------+------------------------------------------------+ | subject_kind | subject_name | role_kind | role_name | +----------------+--------------------------------+-----------+------------------------------------------------+ | ServiceAccount | bootstrap-signer | Role | system:controller:bootstrap-signer | | User | system:kube-controller-manager | Role | system::leader-locking-kube-controller-manager | | ServiceAccount | kube-controller-manager | Role | system::leader-locking-kube-controller-manager | | User | system:kube-scheduler | Role | system::leader-locking-kube-scheduler | | ServiceAccount | kube-scheduler | Role | system::leader-locking-kube-scheduler | +----------------+--------------------------------+-----------+------------------------------------------------+
Nota: O exemplo de consulta acima selecionará todos os Subjects com Roles/ClusterRoles atribuídos que concedem acesso a `update configmaps`.
## Configuração
### Regras de Risco RBAC
As regras de risco RBAC são definidas no arquivo [Rules](https://github.com/appvia/krane/blob/HEAD/config/rules.yaml). A estrutura de cada regra é amplamente autoexplicativa.
O conjunto incorporado pode ser expandido/substituído adicionando regras personalizadas extras ao arquivo [Custom Rules](https://github.com/appvia/krane/blob/HEAD/config/custom-rules.yaml).
#### Macros de Regras de Risco
Macros são "contêineres" para um conjunto de atributos comuns/compartilhados, referenciados por uma ou mais regras de risco. Se você optar por usar uma macro em uma determinada regra de risco, precisará referenciá-la pelo nome, ex.: `macro: <nome-da-macro>`. Note que os atributos definidos na macro referenciada terão precedência sobre os mesmos atributos definidos no nível da regra.
Uma macro pode conter qualquer um dos seguintes atributos:
- `query` - [Consulta RedisGraph](#consultando-o-grafo). Tem precedência sobre `template`. Requer que `writer` seja definido.
- `writer` - Writer é uma expressão Ruby usada para formatar o conjunto de resultados da `query`. Writer tem precedência sobre `template`.
- `template` - Nome do modelo de consulta/writer incorporado. Se `query` e `writer` não forem especificados, o gerador de consulta escolhido será usado juntamente com o writer correspondente.
#### Atributos da Regra de Risco
A regra pode conter qualquer um dos seguintes atributos:
- `id` [Obrigatório] O id da regra é um identificador único de regra.
- `group_title` [Obrigatório] Título que se aplica a todos os itens que se enquadram nesta verificação de risco.
- `severity` [Obrigatório] Severidade, como um dos valores: :danger, :warning, :info.
- `info` [Obrigatório] Informação textual sobre a verificação e sugestões sobre como mitigar o risco.
- `query` [Condicional] [Consulta RedisGraph](#consultando-o-grafo).
- Tem precedência sobre `template`. Requer que `writer` seja definido.
- `writer` [Condicional] Writer é uma expressão Ruby usada para formatar o conjunto de resultados da consulta.
- Writer tem precedência sobre `template`. Requer que `query` seja definido.
- `template` [Condicional] Nome do modelo de consulta/writer incorporado. Se `query` e `writer` não forem especificados, o gerador de consulta escolhido será usado juntamente com o writer correspondente.
- Alguns modelos incorporados exigem que o atributo `match_rules` seja especificado no nível da regra individual para construir a consulta correta. Modelos que atualmente exigem isso:
- **_risky-role_** - Constrói uma consulta de grafo com múltiplas correspondências baseada nas regras de acesso especificadas por `match_rules`. A consulta de grafo gerada retorna as seguintes colunas:
- role_name
- role_kind
- namespace_name (um _array_ é retornado se vários itens forem retornados)
- `match_rules` [Condicional] Necessário quando `template` depende de regras de correspondência para construir uma consulta.
- Exemplo:
```yaml
match_rules:
- resources: ['cronjobs']
verbs: ['update']
```
Os atributos e valores seguem a [especificação de role RBAC do Kubernetes](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#role-examples).
- `custom_params` [Opcional] Lista de pares chave-valor personalizados a serem avaliados e substituídos na representação da `query` e do `writer` da regra.
- Exemplo:
```yaml
custom_params:
- attrA: valueA
- attrB: valueB
```
Os placeholders de modelo para as chaves acima `{{attrA}}` e `{{attrB}}` serão substituídos por `valueA` e `valueB` respectivamente.
- `threshold` [Opcional] Valor numérico. Quando definido, estará disponível como placeholder de modelo `{{threshold}}` na expressão do `writer`.
- `macro` [Opcional] Referência a parâmetros comuns definidos em uma macro nomeada.
- `disabled` [Opcional] Quando definido como `true`, desabilitará a regra e a excluirá da avaliação.
Por padrão, todas as regras estão habilitadas.
#### Exemplos de Regras de Risco
##### Consulta explícita e expressão writer```yaml
- id: verbose-rule-example
group_title: Example rule
severity: :danger
info: Risk description and instructions on how to mitigate it goes here
query: |
MATCH
(s:Subject)-[:ACCESS]->(ns:Namespace)
WHERE
NOT s.name IN {{whitelist_subject_names}}
RETURN
s.kind as subject_kind,
s.name as subject_name,
COLLECT(ns.name) as namespace_names
ORDER BY
subject_kind,
subject_name,
namespace_names DESC
threshold: 2
writer: |
if result.namespace_names.count > {{threshold}}
"#{result.subject_kind} #{result.subject_name} can access namespaces: #{result.namespace_names.join(', ')}"
end
disabled: true
O exemplo acima define explicitamente uma query de grafo usada para avaliar o risco RBAC, e uma expressão writer usada para formatar o conjunto de resultados da consulta. A consulta simplesmente seleciona todos os Subjects (excluindo os whitelisted) e Namespaces aos quais eles têm acesso. Observe que o conjunto de resultados incluirá apenas Subjects com acesso a mais de 2 Namespaces (notou o valor threshold ali?). A última expressão do writer será capturada como saída formatada do item de resultado.
O writer pode acessar o item do conjunto de resultados por meio do objeto result com métodos que correspondem aos elementos retornados pela consulta, ex.: result.subject_kind, result.subject_name, etc.
Nota:
{{threshold}} na expressão writer será substituído pelo valor da palavra-chave threshold da regra.{{whitelist_subject_names}} representa um campo personalizado que será interpolado com os valores de Whitelist definidos para um determinado id de regra. Se um nome de campo placeholder não estiver definido na whitelist, ele será substituído por um array vazio [''] por padrão. Leia mais sobre whitelisting abaixo.Os modelos (templates) incorporados simplificam significativamente a definição de regras de risco, no entanto, eles são projetados para extrair um tipo específico de informação e podem não ser adequados para suas regras personalizadas. Se você se encontrar reutilizando as mesmas expressões de query ou writer em várias regras, considere extraí-las para uma macro e referenciá-la em suas regras personalizadas para aplicar o princípio DRY (Don't Repeat Yourself).```yaml
O exemplo acima mostra uma das regras integradas. Ela referencia o template `risky-role` que, ao ser processado, expandirá a regra injetando expressões `query` e `writer` antes que a avaliação da regra seja acionada. `match_rules` será usado para construir a consulta de correspondência apropriada.
### Whitelist de risco RBAC
Uma whitelist opcional contém um conjunto de nomes de atributos personalizados e seus respectivos valores (na whitelist).
#### Atributos da Whitelist
Os nomes dos atributos e seus valores são arbitrários. Eles são definidos no arquivo [Whitelist](https://github.com/appvia/krane/blob/HEAD/config/whitelist.yaml) e divididos em três seções separadas:
- `global` - Escopo de nível superior. Os atributos personalizados definidos aqui se aplicarão a todas as regras de risco, independentemente do nome do cluster.
- `common` - Os atributos personalizados terão como escopo o `id` específico da regra de risco, independentemente do nome do cluster.
- `cluster` (com lista aninhada de nomes de clusters) - Os atributos personalizados se aplicarão ao `id` específico de uma regra de risco para um determinado nome de cluster.
Cada [Regra de Risco](#rbac-risk-rules), ao ser avaliada, tentará interpolar todos os placeholders de parâmetros usados na `query`, por exemplo, `{{your_whitelist_attribute_name}}`. Se um nome de parâmetro placeholder (ou seja, um nome entre as chaves duplas) corresponder a qualquer um dos nomes de atributos permitidos para aquele `id` de Regra de Risco, ele será substituído pelo seu valor calculado.
Se nenhum valor for encontrado para um determinado placeholder, ele será substituído por `['']`.
#### Exemplos de Whitelist
O exemplo de whitelist abaixo produz o seguinte mapeamento `placeholder-key => value` para uma [Regra de Risco](#rbac-risk-rules) com valor de atributo `id` correspondente a _"some-risk-rule-id"_```
{{whitelist_role_names}} => ['acp:prometheus:operator']
{{whitelist_subject_names}} => ['privileged-psp-user', 'another-user']
As chaves de placeholder acima, quando usadas nas consultas personalizadas de grafo, serão substituídas pelos seus respectivos valores durante a avaliação da Regra de Risco.
rules: global: # global scope - applies to all risk rule and cluster names whitelist_role_names: # custom attribute name - acp:prometheus:operator # custom attribute values
common: # common scope - applies to specific risk rule id regardless of cluster name some-risk-rule-id: # this corresponds to risk rule id defined in config/rules.yaml whitelist_subject_names: # custom attribute name - privileged-psp-user # custom attribute values
cluster: # cluster scope - applies to speciifc risk rule id and cluster name default: # example cluster name some-risk-rule-id: # risk rule id whitelist_subject_names: # custom attribute nane - another-user # custom attribute values
## Implantação no Kubernetes
_Krane_ pode ser implantado em clusters Kubernetes locais ou remotos facilmente.
### Pré-requisitos do K8s
Namespace do Kubernetes, service account juntamente com RBAC apropriado devem estar presentes no cluster. Consulte os [Pré-requisitos](https://github.com/appvia/krane/blob/HEAD/k8s/one-time/prerequisites.yaml) para referência.
O ponto de entrada padrão do _Krane_ executa [bin/in-cluster-run](https://github.com/appvia/krane/blob/HEAD/bin/in-cluster-run) que aguarda a instância do RedisGraph ficar disponível antes de iniciar o loop de _report_ do RBAC e o servidor web do _dashboard_.
Você pode controlar certos aspectos da execução no cluster com as seguintes variáveis de ambiente:
* `KRANE_REPORT_INTERVAL` - Define o intervalo em segundos para execução do relatório de análise estática do RBAC. Padrão: `300` (em segundos, ou seja, 5 minutos).
* `KRANE_REPORT_OUTPUT` - Define o formato de saída do relatório de risco do RBAC. Valores possíveis `:json`, `:yaml`, `:none`. Padrão: `:json`.
### Cluster K8s Local ou Remoto
#### Helm Chart
Antes de começar, você precisará das seguintes ferramentas:
* [Helm CLI](https://helm.sh/docs/intro/install/)
Instalar o helm chart:```sh
$ helm repo add appvia https://appvia.github.io/krane
$ helm repo update
$ helm install krane appvia/krane --namespace krane --create-namespace
Consulte o arquivo values.yaml para obter detalhes sobre outras opções e parâmetros configuráveis.
kubectl create
--context
--namespace krane
-f k8s/redisgraph-service.yaml
-f k8s/redisgraph-deployment.yaml
-f k8s/krane-service.yaml
-f k8s/krane-deployment.yaml
Note que o serviço de dashboard do _Krane_ não está exposto por padrão!```sh
kubectl port-forward svc/krane 8000 \
--context=<docker-desktop> \
--namespace=krane
# Open Krane dashboard at http://localhost:8000
Você pode encontrar os manifestos de implantação de exemplo no diretório k8s.
Modifique os manifestos conforme necessário para suas implantações, certificando-se de referenciar a versão correta da imagem docker do Krane em seu arquivo de implantação. Consulte o Registro Docker do Krane para tags disponíveis, ou apenas use latest.
Se o seu cluster K8s possui suporte nativo ao controlador Compose-on-Kubernetes (docker-desktop suporta por padrão), então você pode implantar o Krane e suas dependências com um único comando docker stack :```sh
docker stack deploy
--orchestrator kubernetes
--namespace krane
--compose-file docker-compose.yml
--compose-file docker-compose.k8s.yml krane
Nota: Certifique-se de que seu contexto kube atual está configurado corretamente antes de executar o comando acima! A Stack de aplicação já deve estar implantada em um cluster Kubernetes e todos os serviços prontos e expostos. Note que o _Krane_ iniciará automaticamente seu loop de relatório e servidor de dashboard.```sh
docker stack services --orchestrator kubernetes --namespace krane krane
O comando acima produzirá a seguinte saída:``` ID NAME MODE REPLICAS IMAGE PORTS 0de30651-dd5 krane_redisgraph replicated 1/1 redislabs/redisgraph:1.99.7 *:6379->6379/tcp aa377a5f-62b krane_krane replicated 1/1 quay.io/appvia/krane:latest *:8000->8000/tcp
Verifique a postura de segurança RBAC do seu cluster Kubernetes visitando http://localhost:8000.
Observe que para implantações de cluster remoto você provavelmente precisará fazer port-forward do serviço _Krane_ primeiro.```sh
kubectl --context=my-remote-cluster --namespace=krane port-forward svc/krane 8000
Para excluir a Stack```sh
docker stack rm krane
--orchestrator kubernetes
--namespace krane
## Notificações
Krane notificará você sobre anomalias detectadas de média e alta gravidade através da sua integração com o Slack.
Para ativar as notificações, especifique o `webhook_url` e o `channel` do Slack no arquivo [config/config.yaml](https://github.com/appvia/krane/blob/HEAD/config/config.yaml), ou alternativamente defina ambas as variáveis de ambiente `SLACK_WEBHOOK_URL` e `SLACK_CHANNEL`. As variáveis de ambiente terão precedência sobre os valores do arquivo de configuração.
## Desenvolvimento Local
Esta seção descreve as etapas para habilitar o desenvolvimento local.
### Configuração
Instale as dependências de código do _Krane_ com```sh
./bin/setup
Krane depende do RedisGraph. docker-compose é a maneira mais rápida de obter as dependências do Krane em execução localmente.```sh
docker-compose up -d redisgraph
Para inspecionar se o serviço RedisGraph está ativo:```sh
docker-compose ps
Para parar os serviços:```sh docker-compose down
### Desenvolvimento
Neste ponto, você deve ser capaz de modificar a base de código do _Krane_ e testar resultados executando comandos no shell local.```sh
$ ./bin/krane --help # to get help
$ ./bin/krane report -k docker-desktop # to generate your first report for
# local docker-desktop k8s cluster
...
Para ativar o modo de desenvolvimento local do Dashboard UI```sh $ cd dashboard $ npm install $ npm start
Isso iniciará automaticamente o servidor do Dashboard, abrirá o navegador padrão e observará as alterações nos arquivos de origem.
_Krane_ vem pré-configurado para uma melhor experiência do desenvolvedor com [Skaffold](https://skaffold.dev/). Iterar sobre o projeto e validar a aplicação executando toda a stack em um cluster Kubernetes local ou remoto ficou mais fácil.
O hot-reload de código permite que alterações locais sejam automaticamente propagadas para o container em execução, proporcionando um ciclo de desenvolvimento mais rápido.```sh
skaffold dev --kube-context docker-desktop --namespace krane --port-forward
Execute os testes localmente com```sh bundle exec rspec
## Contribuindo para o Krane
Aceitamos contribuições da comunidade! Dê uma olhada no nosso guia de [contribuição](https://github.com/appvia/krane/blob/HEAD/CONTRIBUTING.md) para mais informações sobre como começar. Se você usa _Krane_, acha útil ou tem interesse geral em segurança de Kubernetes, por favor, nos avise **Favoritando** e **Observando** este repositório. Obrigado!
## Envolva-se
Participe da discussão no nosso [Canal da Comunidade](https://www.appvia.io/join-the-appvia-community).
Krane é um projeto comunitário e agradecemos suas contribuições. Para relatar um bug, sugerir uma melhoria ou solicitar um novo recurso, por favor, abra uma issue no Github. Consulte nosso guia de [contribuição](https://github.com/appvia/krane/blob/HEAD/CONTRIBUTING.md) para mais informações sobre como você pode ajudar.
## Roteiro
Veja nosso [Roteiro](https://github.com/appvia/krane/projects/1) para detalhes sobre nossos planos para o projeto.
## Licença
Autor: Marcin Ciszak <[email protected]>
Copyright (c) 2019-2020 [Appvia Ltd](https://appvia.io)
Este projeto é distribuído sob a [Apache License, Versão 2.0](https://github.com/appvia/krane/blob/HEAD/LICENSE).