
Uma ferramenta para usar credenciais AWS IAM para autenticar em um cluster Kubernetes
Uma ferramenta para usar credenciais AWS IAM para autenticar em um cluster Kubernetes. O trabalho inicial nesta ferramenta foi conduzido pela Heptio. O projeto recebe contribuições de vários engenheiros da comunidade e atualmente é mantido pela Heptio e pelos engenheiros de OSS da Amazon EKS.
Se você é um administrador executando um cluster Kubernetes na AWS, você já precisa gerenciar credenciais AWS IAM para provisionar e atualizar o cluster. Ao usar o AWS IAM Authenticator for Kubernetes, você evita ter que gerenciar uma credencial separada para acesso ao Kubernetes. O AWS IAM também fornece uma série de propriedades interessantes, como uma trilha de auditoria fora de banda (via CloudTrail) e aplicação de 2FA/MFA.
Se você está construindo um instalador Kubernetes na AWS, o AWS IAM Authenticator for Kubernetes pode simplificar seu processo de bootstrap.
Você não precisará, de alguma forma, contrabandear com segurança sua credencial inicial de administrador para fora do cluster recém-instalado.
Em vez disso, você pode criar uma função dedicada KubernetesAdmin no momento do provisionamento do cluster e configurar o Authenticator para permitir logins de administradores de cluster.
Supondo que você tenha um cluster em execução na AWS e queira adicionar suporte ao AWS IAM Authenticator for Kubernetes, você precisa:
Primeiro, você deve criar uma ou mais funções IAM que serão mapeadas para usuários/grupos dentro do seu cluster Kubernetes. A maneira mais fácil de fazer isso é entrar no Console AWS:
Isso criará uma função IAM sem permissões que pode ser assumida por usuários/funções autorizados na sua conta. Anote o Amazon Resource Name (ARN) da sua função, que você precisará abaixo.
Você também pode fazer isso em uma única etapa usando a AWS CLI em vez do Console AWS:```sh
ACCOUNT_ID=$(aws sts get-caller-identity --output text --query 'Account')
POLICY=$(echo -n '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":"arn:aws:iam::'; echo -n "$ACCOUNT_ID"; echo -n ':root"},"Action":"sts:AssumeRole","Condition":{}}]}')
aws iam create-role
--role-name KubernetesAdmin
--description "Kubernetes administrator role (for AWS IAM Authenticator for Kubernetes)."
--assume-role-policy-document "$POLICY"
--output text
--query 'Role.Arn'
Você também pode pular esta etapa e usar:
- Uma função existente (como uma função de acesso entre contas).
- Um usuário IAM (veja `mapUsers` abaixo).
- Uma instância EC2 ou uma função federada (veja `mapRoles` abaixo).
### 2. Execute o servidor
O servidor deve ser executado em cada um dos seus nós master como um DaemonSet com rede do host, para que possa expor uma porta localhost.
Para uma configuração de exemplo de ConfigMap e DaemonSet, veja [`deploy/example.yaml`](https://github.com/kubernetes-sigs/aws-iam-authenticator/blob/HEAD/deploy/example.yaml).
Antes de aplicá-la, atualize estes valores para o seu cluster:
- Substitua os ARNs de IAM de espaço reservado (`arn:aws:iam::000000000000:...`) em `config.yaml`.
- Defina `clusterID` para um valor único para o seu cluster.
- Verifique se as regras de agendamento do DaemonSet correspondem aos rótulos/taints dos seus nós do plano de controle.
Em seguida, implemente-o:```sh
kubectl apply -f deploy/example.yaml
kubectl -n kube-system rollout status daemonset/aws-iam-authenticator
kubectl -n kube-system get pods -l k8s-app=aws-iam-authenticator
Quando o pod estiver em execução em um nó do plano de controle, o aws-iam-authenticator server criará o kubeconfig do webhook no host em /etc/kubernetes/aws-iam-authenticator/kubeconfig.yaml (ou no caminho configurado via --generate-kubeconfig).
Se você estiver criando um instalador automatizado, também pode pré-gerar facilmente os arquivos de certificado, chave e kubeconfig do webhook usando aws-iam-authenticator init.
Este comando gerará os arquivos e os colocará nos diretórios de saída configurados.
Você pode executar isso em cada nó mestre antes de iniciar o servidor de API. Você também pode gerá-los antes de provisionar os nós mestres e instalá-los nos caminhos de host apropriados.
Se você não pré-gerar os arquivos, o aws-iam-authenticator server os gerará sob demanda.
Isso funciona, mas requer que você reinicie o servidor de API do Kubernetes após a instalação.
A API do Kubernetes integra-se ao AWS IAM Authenticator for Kubernetes usando um webhook de autenticação por token.
Quando você executa aws-iam-authenticator server, ele gera um arquivo de configuração do webhook e o salva no sistema de arquivos do host.
Você precisará adicionar um único flag adicional à configuração do seu servidor de API:```
--authentication-token-webhook-config-file=/etc/kubernetes/aws-iam-authenticator/kubeconfig.yaml
Em muitos clusters, o servidor de API é executado como um pod estático.
Você pode adicionar a flag a `/etc/kubernetes/manifests/kube-apiserver.yaml`.
Certifique-se de que o diretório do host `/etc/kubernetes/aws-iam-authenticator/` esteja montado no pod do seu servidor de API.
Você também pode precisar reiniciar o daemon kubelet no seu nó mestre para aplicar a definição atualizada do pod estático:```
systemctl restart kubelet.service
O comportamento padrão do servidor é buscar mapeamentos exclusivamente dos
campos mapUsers e mapRoles do seu arquivo de configuração. Consulte Formato
Completo de Configuração abaixo para detalhes.
Usando a flag --backend-mode, você pode configurar o servidor para buscar
mapeamentos de dois backends adicionais: um ConfigMap no estilo EKS
(--backend-mode=EKSConfigMap) ou recursos personalizados IAMIdentityMapping
(--backend-mode=CRD). O backend padrão, o arquivo de configuração do servidor
que é montado pelo pod do servidor, corresponde a --backend-mode=MountedFile.
Você pode passar uma lista separada por vírgulas desses backends para que o servidor
os pesquise em ordem. Por exemplo, com --backend-mode=EKSConfigMap,MountedFile, o
servidor buscará mapeamentos no ConfigMap no estilo EKS e, se não encontrar um
mapeamento para a função/usuário IAM fornecido, buscará no arquivo de configuração
do servidor. Se um mapeamento para a mesma função/usuário IAM existir em vários
backends, o servidor usará o mapeamento do backend que ocorrer primeiro na lista
separada por vírgulas. Neste exemplo, se um mapeamento for encontrado no ConfigMap
EKS, ele será usado independentemente de existir um mapeamento duplicado ou
conflitante no arquivo de configuração do servidor.
Observe que, ao definir um único backend, o servidor buscará somente nesse
backend e ignorará os demais, mesmo que existam. Por exemplo, com
--backend-mode=CRD, o servidor buscará somente em IAMIdentityMappings
e ignorará o arquivo montado e o ConfigMap EKS.
MountedFileEste é o backend padrão de mapeamentos e é suficiente para a maioria dos usuários. Consulte Formato Completo de Configuração abaixo para detalhes.
CRD (alfa)Este backend modela cada mapeamento IAM como um Recurso Personalizado do
Kubernetes
IAMIdentityMapping. Essa abordagem permite manter mapeamentos de forma nativa do
Kubernetes usando kubectl ou a API. Além disso, erros de sintaxe (como YAML
desalinhado) podem ser capturados mais facilmente e não afetarão todos os
mapeamentos.
Para configurar um IAMIdentityMapping CRD, você precisará primeiro fazer apply
no manifesto do CRD:```
kubectl apply -f deploy/iamidentitymapping.yaml
Com os CRDs implantados, você pode então criar Custom Resources que modelam suas IAM Identities. Veja
[`./deploy/example-iamidentitymapping.yaml`](https://github.com/kubernetes-sigs/aws-iam-authenticator/blob/HEAD/deploy/example-iamidentitymapping.yaml):```
---
apiVersion: iamauthenticator.k8s.aws/v1alpha1
kind: IAMIdentityMapping
metadata:
name: kubernetes-admin
spec:
# Arn of the User or Role to be allowed to authenticate
arn: arn:aws:iam::XXXXXXXXXXXX:user/KubernetesAdmin
# Username that Kubernetes will see the user as, this is useful for setting
# up allowed specific permissions for different users
username: kubernetes-admin
# Groups to be attached to your users/roles. For example `system:masters` to
# create cluster admin, or `system:nodes`, `system:bootstrappers` for nodes to
# access the API server.
groups:
- system:masters
EKSConfigMapO ConfigMap kube-system/aws-auth no estilo EKS serve como backend. O
ConfigMap deve estar exatamente no mesmo formato que nos clusters EKS:
https://docs.aws.amazon.com/eks/latest/userguide/add-user-role.html. Isso é
útil se você estiver migrando de/para o EKS e quiser manter seus mapeamentos, ou se
estiver executando o EKS além de algum(s) outro(s) cluster(s) AWS e quiser ter os mesmos
mapeamentos em cada um.
DynamicFileUm arquivo local especificado por cfg.dynamicfilepath pode servir como backend. O conteúdo do arquivo deve estar exatamente no mesmo formato que o EKSConfigMap. Sempre que o conteúdo deste arquivo mudar, o authenticator o recarregará automaticamente. Isso fornece mais flexibilidade no gerenciamento dos mapeamentos de ARN.
Consulte https://github.com/kubernetes-sigs/aws-iam-authenticator/blob/master/hack/dev/authenticator_with_dynamicfile_mode.yaml sobre como configurar o modo DynamicFile.
Execute make e2e RUNNER=kind para experimentar um cluster kind com o modo DynamicFile habilitado.
O aws-iam-authenticator pode suportar prefixo reservado para nome de usuário k8s. Se o prefixo reservado estiver definido, então o nome de usuário com o prefixo reservado não será autenticado, retornando o erro "o nome de usuário não deve começar com os seguintes prefixos:".
Consulte https://github.com/kubernetes-sigs/aws-iam-authenticator/blob/master/hack/dev/authenticator_with_dynamicfile_mode.yaml sobre como configurar o prefixo reservado.
Por fim, depois que o servidor estiver configurado, você vai querer autenticar.
Você ainda precisará de um kubeconfig que contenha os dados públicos sobre seu cluster (certificado CA do cluster, endereço do endpoint).
A seção users da sua configuração, no entanto, deve incluir uma seção exec (consulte a documentação do plugin de credenciais do kubectl):```yaml
users:
Isto significa que o `kubeconfig` é inteiramente um dado público e pode ser partilhado entre todos os utilizadores do Authenticator.
Pode fazer sentido carregá-lo para uma localização pública fiável como o AWS S3.
Certifique-se de que tem o binário `aws-iam-authenticator` instalado.
Pode instalá-lo com `go install sigs.k8s.io/aws-iam-authenticator/cmd/aws-iam-authenticator@latest`.
Para autenticar, execute `kubectl --kubeconfig /path/to/kubeconfig" [...]`.
O kubectl vai `exec` o binário `aws-iam-authenticator` com os parâmetros fornecidos no seu kubeconfig, o que irá gerar um token e passá-lo para o apiserver.
O token é válido por 15 minutos (o valor mais curto que a AWS permite) e pode ser reutilizado várias vezes.
Também pode especificar o nome da sessão ao gerar o token incluindo o parâmetro `--session-name or -s`. Este parâmetro não pode ser usado juntamente com `--forward-session-name`.
Também pode omitir `-r ROLE_ARN` para assinar o token com as suas credenciais existentes sem assumir uma função dedicada.
Isto é útil se pretender autenticar diretamente como um utilizador do IAM ou se pretender autenticar usando uma função de instância EC2 ou uma função federada.
## Utilização do Kops
Os clusters geridos por [Kops](https://github.com/kubernetes/kops) podem ser configurados para usar o Authenticator. Para instruções de utilização, consulte a [documentação do Kops](https://kops.sigs.k8s.io/authentication/#aws-iam-authenticator).
## Como funciona?
Funciona utilizando o endpoint da API [`sts:GetCallerIdentity`](https://docs.aws.amazon.com/STS/latest/APIReference/API_GetCallerIdentity.html) da AWS.
Este endpoint devolve informações sobre as credenciais AWS IAM que utiliza para se ligar a ele.
#### Lado do cliente (`aws-iam-authenticator token`)
Utilizamos esta API de uma forma algo invulgar, fazendo com que o cliente do Authenticator gere e pré-assine um pedido para o endpoint.
Serializamos esse pedido num token que pode passar pelo sistema de autenticação do Kubernetes.
#### Lado do servidor (`aws-iam-authenticator server`)
O token é passado através do servidor de API do Kubernetes e para o endpoint `/authenticate` do servidor do Authenticator através de uma configuração de webhook.
O servidor do Authenticator valida todos os parâmetros do pedido pré-assinado para garantir que nada parece suspeito.
Depois submete o pedido ao servidor real `https://sts.amazonaws.com`, que valida a assinatura HMAC do cliente e devolve informações sobre o utilizador.
Agora que o servidor conhece a identidade AWS do cliente, traduz essa identidade num utilizador do Kubernetes e em grupos através de um mapeamento estático simples.
Este mecanismo é emprestado, com algumas alterações, do [Vault](https://www.vaultproject.io/docs/auth/aws.html#iam-auth-method).
## O que é um ID de cluster?
O ID de cluster do Authenticator é um identificador único por cluster que impede determinados ataques de repetição.
Especificamente, impede que um servidor do Authenticator (por exemplo, num ambiente de desenvolvimento) utilize o token de um cliente para autenticar noutro servidor do Authenticator noutro cluster.
O ID de cluster precisa de ser único por cluster, mas não precisa de ser um segredo.
Algumas boas opções são:
- Um ID aleatório, como por exemplo de `openssl rand 16 -hex`
- O nome de domínio do seu servidor de API do Kubernetes
A [documentação do Vault](https://www.vaultproject.io/docs/auth/aws.html#iam-auth-method) também explica este ataque (ver `X-Vault-AWS-IAM-Server-ID`).
## Especificar Credenciais & Utilizar Perfis AWS
As credenciais podem ser especificadas para uso com `aws-iam-authenticator` através de qualquer um dos métodos disponíveis no
[AWS SDK para Go](https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials).
Isto inclui especificar credenciais AWS com variáveis de ambiente ou utilizando um ficheiro de credenciais.
Os [perfis nomeados](https://docs.aws.amazon.com/cli/latest/userguide/cli-multiple-profiles.html) da AWS são suportados pelo `aws-iam-authenticator`
através da variável de ambiente `AWS_PROFILE`. Por exemplo, para autenticar com credenciais especificadas no perfil _dev_, o `AWS_PROFILE` pode
ser exportado ou especificado explicitamente (por exemplo, `AWS_PROFILE=dev kubectl get all`). Se nenhum `AWS_PROFILE` estiver definido, o perfil _default_ é utilizado.
O `AWS_PROFILE` também pode ser especificado diretamente no ficheiro kubeconfig
[como parte do fluxo `exec`](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#configuration). Por exemplo, para especificar
que as credenciais do perfil nomeado _dev_ devem ser sempre utilizadas pelo `aws-iam-authenticator`, o seu kubeconfig incluiria uma chave `env`
que define o perfil:```yaml
apiVersion: v1
clusters:
- cluster:
server: ${server}
certificate-authority-data: ${cert}
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: aws
name: aws
current-context: aws
kind: Config
preferences: {}
users:
- name: aws
user:
exec:
apiVersion: client.authentication.k8s.io/v1beta1
command: aws-iam-authenticator
env:
- name: "AWS_PROFILE"
value: "dev"
args:
- "token"
- "-i"
- "mycluster"
Este método permite que o perfil apropriado seja usado implicitamente. Observe que quaisquer variáveis de ambiente definidas como parte do fluxo exec serão
priorizadas em relação ao que já está definido no seu ambiente.
Usuários federados da AWS frequentemente têm um atributo "significativo" mapeado para a função assumida, como um endereço de e-mail, por meio da configuração da AWS da conta.
Essas sessões assumidas têm algumas partes, o role id
e caller-specified-role-name. Por padrão, quando um usuário federado usa a opção --role do aws-iam-authenticator para assumir uma nova função, o
caller-specified-role-name será convertido em um token aleatório e o role id é mantido na função recém-assumida.
Usar aws-iam-authenticator token ... --forward-session-name mapeará o atributo original caller-specified-role-name para a nova sessão assumida do STS.
Isso pode ser útil para tentar associar rapidamente "quem executou a ação X no cluster K8".
Observe que isso não deve ser considerado definitivo e precisa ser referenciado de forma cruzada por meio do role id (que permanece consistente) com os logs do CloudTrail
já que um usuário pode potencialmente alterar isso no lado do cliente.
É possível fazer solicitações à API do Kubernetes a partir de um cliente que esteja fora do cluster, seja usando a
API REST do Kubernetes pura ou um dos clientes Kubernetes específicos de linguagem
(por exemplo, Python). Para isso, você deve criar um token de portador que
seja incluído na solicitação à API. Esse token de portador exige que você acrescente a string k8s-aws-v1. com uma
string codificada em base64 de uma solicitação HTTP assinada para a API de consulta GetCallerIdentity do STS. Em seguida, isso é enviado no
cabeçalho Authorization da solicitação. Algo a observar, no entanto, é que o IAM Authenticator omite explicitamente o
preenchimento base64 para evitar qualquer caractere =, garantindo assim uma string segura para uso em URLs. Abaixo está um exemplo em
Python de como esse token seria construído:```python
import base64
import boto3
import re
from botocore.signers import RequestSigner
def get_bearer_token(cluster_id, region): STS_TOKEN_EXPIRES_IN = 60 session = boto3.session.Session()
client = session.client('sts', region_name=region)
service_id = client.meta.service_model.service_id
signer = RequestSigner(
service_id,
region,
'sts',
'v4',
session.get_credentials(),
session.events
)
params = {
'method': 'GET',
'url': 'https://sts.{}.amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15'.format(region),
'body': {},
'headers': {
'x-k8s-aws-id': cluster_id
},
'context': {}
}
signed_url = signer.generate_presigned_url(
params,
region_name=region,
expires_in=STS_TOKEN_EXPIRES_IN,
operation_name=''
)
base64_url = base64.urlsafe_b64encode(signed_url.encode('utf-8')).decode('utf-8')
# remove any base64 encoding padding:
return 'k8s-aws-v1.' + re.sub(r'=*', '', base64_url)
headers = {'Authorization': 'Bearer ' + get_bearer_token('my_cluster', 'us-east-1')}
## Solução de problemas
Se o seu cliente falhar com um erro como `could not get token: AccessDenied [...]`, você pode tentar assumir a função diretamente com a AWS CLI:```sh
# AWS CLI version of `aws-iam-authenticator token -r arn:aws:iam::ACCOUNT:role/ROLE`:
$ aws sts assume-role --role-arn arn:aws:iam::ACCOUNT:role/ROLE --role-session-name test
If that fails, there are a few possible problems to check for:
Certifique-se de que suas credenciais base da AWS estejam disponíveis no seu shell (aws sts get-caller-identity pode ajudar a solucionar esse problema).
Certifique-se de que a role de destino permite o acesso da sua conta de origem (na política de confiança da role).
Certifique-se de que seu principal de origem (usuário/role/grupo) tenha uma política do IAM que permita sts:AssumeRole para a role de destino.
Certifique-se de que você não possui políticas de negação explícitas anexadas ao seu usuário, grupo ou em AWS Organizations que impeçam o sts:AssumeRole.
Tente simular a chamada sts:AssumeRole no Policy Simulator.
O cliente e o servidor têm o mesmo formato de configuração. Eles podem compartilhar exatamente o mesmo arquivo de configuração, pois não há segredos armazenados na configuração.```yaml
clusterID: my-dev-cluster.example.com
aws-iam-authenticator tokendefaultRole: arn:aws:iam::000000000000:role/KubernetesAdmin
server:
port: 21362 # (default)
stateDir: /var/aws-iam-authenticator # (default)
path where a generated webhook kubeconfig will be stored.generateKubeconfig: /etc/kubernetes/aws-iam-authenticator.kubeconfig # (default)
ec2DescribeInstancesRoleARN: arn:aws:iam::000000000000:role/DescribeInstancesRole
scrubbedAccounts:
@ characters- characters.mapRoles:
mapUsers:
mapAccounts:
backendMode:
## Desenvolvimento
Consulte a página de [desenvolvimento](https://github.com/kubernetes-sigs/aws-iam-authenticator/blob/HEAD/docs/development.md).
## Comunidade, discussão, contribuição e suporte
Aprenda como interagir com a comunidade Kubernetes na [página da comunidade](http://kubernetes.io/community/).
Você pode entrar em contato com os mantenedores deste projeto em:
- [Slack](https://kubernetes.slack.com/messages/sig-aws)
- [Lista de e-mails](https://groups.google.com/forum/#!forum/kubernetes-sig-aws)
### Código de conduta
A participação na comunidade Kubernetes é regida pelo [Código de Conduta do Kubernetes](https://github.com/kubernetes-sigs/aws-iam-authenticator/blob/HEAD/code-of-conduct.md).