
Uno strumento per utilizzare le credenziali AWS IAM per autenticarsi a un cluster Kubernetes
Uno strumento per utilizzare le credenziali AWS IAM per autenticarsi su un cluster Kubernetes. Il lavoro iniziale su questo strumento è stato guidato da Heptio. Il progetto riceve contributi da diversi ingegneri della community ed è attualmente mantenuto da Heptio e dagli ingegneri OSS di Amazon EKS.
Se sei un amministratore che gestisce un cluster Kubernetes su AWS, devi già gestire le credenziali AWS IAM per il provisioning e l'aggiornamento del cluster. Utilizzando AWS IAM Authenticator for Kubernetes eviti di dover gestire una credenziale separata per l'accesso a Kubernetes. AWS IAM offre anche una serie di proprietà interessanti come una traccia di audit esterna (tramite CloudTrail) e l'applicazione di 2FA/MFA.
Se stai creando un installer Kubernetes su AWS, AWS IAM Authenticator for Kubernetes può semplificare il tuo processo di bootstrap.
Non dovrai introdurre di nascosto la tua credenziale admin iniziale in modo sicuro dal cluster appena installato.
Invece, puoi creare un ruolo dedicato KubernetesAdmin in fase di provisioning del cluster e configurare Authenticator per consentire gli accessi degli amministratori del cluster.
Supponendo che tu abbia un cluster in esecuzione su AWS e che tu voglia aggiungere il supporto per AWS IAM Authenticator for Kubernetes, devi:
Per prima cosa, devi creare uno o più ruoli IAM che verranno mappati a utenti/gruppi all'interno del tuo cluster Kubernetes. Il modo più semplice per farlo è accedere alla console AWS:
In questo modo verrà creato un ruolo IAM senza autorizzazioni che può essere assunto da utenti/ruoli autorizzati nel tuo account. Prendi nota dell'Amazon Resource Name (ARN) del tuo ruolo, che ti servirà in seguito.
Puoi anche farlo in un unico passaggio usando la AWS CLI invece della 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'
Puoi anche saltare questo passaggio e usare:
- Un ruolo esistente (come un ruolo di accesso cross-account).
- Un utente IAM (vedi `mapUsers` sotto).
- Un'istanza EC2 o un ruolo federato (vedi `mapRoles` sotto).
### 2. Esegui il server
Il server è pensato per essere eseguito su ciascuno dei tuoi nodi master come DaemonSet con networking host, così da poter esporre una porta localhost.
Per una ConfigMap e una configurazione DaemonSet di esempio, vedi [`deploy/example.yaml`](https://github.com/kubernetes-sigs/aws-iam-authenticator/blob/HEAD/deploy/example.yaml).
Prima di applicarla, aggiorna questi valori per il tuo cluster:
- Sostituisci gli ARN IAM segnaposto (`arn:aws:iam::000000000000:...`) in `config.yaml`.
- Imposta `clusterID` su un valore univoco per il tuo cluster.
- Verifica che le regole di pianificazione del DaemonSet corrispondano alle etichette/taint dei tuoi nodi del control plane.
Poi distribuiscilo:```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
Una volta che il pod è in esecuzione su un nodo del piano di controllo, aws-iam-authenticator server creerà il kubeconfig del webhook sull'host nel percorso /etc/kubernetes/aws-iam-authenticator/kubeconfig.yaml (o nel percorso configurato tramite --generate-kubeconfig).
Se stai creando un programma di installazione automatizzato, puoi anche pre-generare facilmente i file del certificato, della chiave e del kubeconfig del webhook usando aws-iam-authenticator init.
Questo comando genererà i file e li collocherà nelle directory di output configurate.
Puoi eseguirlo su ogni nodo master prima di avviare il server API. Potresti anche generarli prima del provisioning dei nodi master e installarli nei percorsi host appropriati.
Se non pre-generi i file, aws-iam-authenticator server li genererà su richiesta.
Questa soluzione funziona, ma richiede di riavviare il server API di Kubernetes dopo l'installazione.
L'API di Kubernetes si integra con AWS IAM Authenticator for Kubernetes utilizzando un webhook di autenticazione token.
Quando esegui aws-iam-authenticator server, questo genererà un file di configurazione del webhook e lo salverà sul filesystem dell'host.
Dovrai aggiungere un unico flag aggiuntivo alla configurazione del tuo server API:```
--authentication-token-webhook-config-file=/etc/kubernetes/aws-iam-authenticator/kubeconfig.yaml
Su molti cluster, il server API viene eseguito come pod statico.
Puoi aggiungere il flag a `/etc/kubernetes/manifests/kube-apiserver.yaml`.
Assicurati che la directory host `/etc/kubernetes/aws-iam-authenticator/` sia montata nel pod del server API.
Potrebbe anche essere necessario riavviare il demone kubelet sul nodo master per applicare la definizione aggiornata del pod statico:```
systemctl restart kubelet.service
Il comportamento predefinito del server è quello di recuperare le mappature esclusivamente dai campi mapUsers e mapRoles del proprio file di configurazione. Vedi Formato Completo di Configurazione qui sotto per i dettagli.
Utilizzando il flag --backend-mode, puoi configurare il server per recuperare le mappature da due backend aggiuntivi: una ConfigMap in stile EKS (--backend-mode=EKSConfigMap) o risorse personalizzate IAMIdentityMapping (--backend-mode=CRD). Il backend predefinito, ovvero il file di configurazione del server montato dal pod del server, corrisponde a --backend-mode=MountedFile.
Puoi passare un elenco separato da virgole di questi backend per fare in modo che il server li cerchi in ordine. Ad esempio, con --backend-mode=EKSConfigMap,MountedFile, il server cercherà le mappature nella ConfigMap in stile EKS e, se non trova una mappatura per il ruolo/utente IAM dato, nel file di configurazione del server. Se una mappatura per lo stesso ruolo/utente IAM esiste in più backend, il server userà la mappatura nel backend che compare per primo nell'elenco separato da virgole. In questo esempio, se una mappatura viene trovata nella ConfigMap EKS, verrà usata indipendentemente dal fatto che esista una mappatura duplicata o in conflitto nel file di configurazione del server.
Nota che quando si imposta un singolo backend, il server recupererà solo le mappature da quello e ignorerà gli altri anche se esistono. Ad esempio, con --backend-mode=CRD, il server recupererà solo dalle IAMIdentityMappings e ignorerà il file montato e la ConfigMap EKS.
MountedFileQuesto è il backend predefinito delle mappature ed è sufficiente per la maggior parte degli utenti. Vedi Formato Completo di Configurazione qui sotto per i dettagli.
CRD (alpha)Questo backend modella ogni mappatura IAM come una risorsa personalizzata Kubernetes IAMIdentityMapping. Questo approccio ti consente di mantenere le mappature in modo nativo per Kubernetes usando kubectl o l'API. Inoltre, gli errori di sintassi (come YAML disallineato) possono essere individuati più facilmente e non influenzeranno tutte le mappature.
Per configurare un CRD IAMIdentityMapping, dovrai prima eseguire apply del manifest del CRD:```
kubectl apply -f deploy/iamidentitymapping.yaml
Con i CRD distribuiti puoi quindi creare Custom Resources che modellano le tue
IAM Identities. Vedi
[`./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
EKSConfigMapLa ConfigMap kube-system/aws-auth in stile EKS funge da backend. Ci si aspetta che la ConfigMap sia esattamente nello stesso formato delle cluster EKS: https://docs.aws.amazon.com/eks/latest/userguide/add-user-role.html. Questo è utile se stai migrando da/a EKS e vuoi mantenere i tuoi mapping, oppure se stai eseguendo EKS oltre ad altre cluster AWS e vuoi avere gli stessi mapping in ciascuna.
DynamicFileUn file locale specificato da cfg.dynamicfilepath può fungere da backend. Il contenuto del file deve essere esattamente nello stesso formato della EKSConfigMap. Ogni volta che il contenuto di questo file cambia, authenticator lo ricaricherà automaticamente. Questo offre maggiore flessibilità nella gestione dei mapping ARN.
Consulta https://github.com/kubernetes-sigs/aws-iam-authenticator/blob/master/hack/dev/authenticator_with_dynamicfile_mode.yaml su come configurare la modalità DynamicFile.
Esegui make e2e RUNNER=kind per provare un cluster kind con la modalità DynamicFile abilitata.
aws-iam-authenticator può supportare un prefisso riservato per il nome utente k8s. Se il prefisso riservato è impostato, il nome utente con il prefisso riservato non verrà autenticato e restituirà l'errore "username must not begin with with the following prefixes:".
Consulta https://github.com/kubernetes-sigs/aws-iam-authenticator/blob/master/hack/dev/authenticator_with_dynamicfile_mode.yaml su come configurare il prefisso riservato.
Infine, una volta configurato il server, vorrai autenticarti.
Avrai comunque bisogno di un kubeconfig che contenga i dati pubblici del tuo cluster (certificato CA del cluster, indirizzo dell'endpoint).
La sezione users della tua configurazione, tuttavia, dovrebbe includere una sezione exec (consulta la documentazione del plugin per le credenziali kubectl):```yaml
users:
Ciò significa che il `kubeconfig` è interamente un dato pubblico e può essere condiviso tra tutti gli utenti di Authenticator.
Può avere senso caricarlo in una posizione pubblica attendibile come AWS S3.
Assicurati di avere installato il binario `aws-iam-authenticator`.
Puoi installarlo con `go install sigs.k8s.io/aws-iam-authenticator/cmd/aws-iam-authenticator@latest`.
Per autenticarti, esegui `kubectl --kubeconfig /path/to/kubeconfig" [...]`.
kubectl eseguirà (`exec`) il binario `aws-iam-authenticator` con i parametri forniti nel tuo kubeconfig, che genererà un token e lo passerà all'apiserver.
Il token è valido per 15 minuti (il valore più breve consentito da AWS) e può essere riutilizzato più volte.
Puoi anche specificare il nome della sessione quando generi il token includendo il parametro `--session-name or -s`. Questo parametro non può essere usato insieme a `--forward-session-name`.
Puoi anche omettere `-r ROLE_ARN` per firmare il token con le tue credenziali esistenti senza assumere un ruolo dedicato.
Ciò è utile se vuoi autenticarti direttamente come utente IAM o se vuoi autenticarti usando un ruolo di istanza EC2 o un ruolo federato.
## Utilizzo con Kops
I cluster gestiti da [Kops](https://github.com/kubernetes/kops) possono essere configurati per usare Authenticator. Per le istruzioni d'uso, consulta la [documentazione di Kops](https://kops.sigs.k8s.io/authentication/#aws-iam-authenticator).
## Come funziona?
Funziona usando l'endpoint API [`sts:GetCallerIdentity`](https://docs.aws.amazon.com/STS/latest/APIReference/API_GetCallerIdentity.html) di AWS.
Questo endpoint restituisce informazioni sulle credenziali AWS IAM che usi per connetterti.
#### Lato client (`aws-iam-authenticator token`)
Usiamo questa API in un modo piuttosto insolito: facciamo generare al client Authenticator una richiesta all'endpoint e pre-firmarla.
Serializziamo quella richiesta in un token che può attraversare il sistema di autenticazione Kubernetes.
#### Lato server (`aws-iam-authenticator server`)
Il token viene passato attraverso il server API Kubernetes e all'endpoint `/authenticate` del server Authenticator tramite una configurazione webhook.
Il server Authenticator valida tutti i parametri della richiesta pre-firmata per assicurarsi che nulla sembri sospetto.
Successivamente invia la richiesta al vero server `https://sts.amazonaws.com`, che valida la firma HMAC del client e restituisce informazioni sull'utente.
Ora che il server conosce l'identità AWS del client, traduce questa identità in un utente Kubernetes e in gruppi tramite una semplice mappatura statica.
Questo meccanismo è ripreso con alcune modifiche da [Vault](https://www.vaultproject.io/docs/auth/aws.html#iam-auth-method).
## Cos'è un cluster ID?
Il cluster ID di Authenticator è un identificatore univoco per cluster che previene alcuni attacchi di replay.
In particolare, impedisce a un server Authenticator (ad esempio in un ambiente di sviluppo) di usare il token di un client per autenticarsi presso un altro server Authenticator in un altro cluster.
Il cluster ID deve essere univoco per cluster, ma non deve essere un segreto.
Alcune buone scelte sono:
- Un ID casuale come ad esempio da `openssl rand 16 -hex`
- Il nome di dominio del tuo server API Kubernetes
Anche la [documentazione di Vault](https://www.vaultproject.io/docs/auth/aws.html#iam-auth-method) spiega questo attacco (vedi `X-Vault-AWS-IAM-Server-ID`).
## Specificare le credenziali e usare i profili AWS
Le credenziali possono essere specificate per l'uso con `aws-iam-authenticator` tramite uno qualsiasi dei metodi disponibili nell'[AWS SDK for Go](https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials).
Ciò include specificare le credenziali AWS tramite variabili d'ambiente o utilizzando un file delle credenziali.
I [profili nominati](https://docs.aws.amazon.com/cli/latest/userguide/cli-multiple-profiles.html) di AWS sono supportati da `aws-iam-authenticator`
tramite la variabile d'ambiente `AWS_PROFILE`. Ad esempio, per autenticarti con le credenziali specificate nel profilo _dev_, `AWS_PROFILE` può
essere esportata o specificata esplicitamente (ad esempio `AWS_PROFILE=dev kubectl get all`). Se `AWS_PROFILE` non è impostato, viene usato il profilo _default_.
La `AWS_PROFILE` può anche essere specificata direttamente nel file kubeconfig
[come parte del flusso `exec`](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#configuration). Ad esempio, per specificare
che le credenziali del profilo nominato _dev_ debbano essere sempre usate da `aws-iam-authenticator`, il tuo kubeconfig dovrebbe includere una chiave `env` che imposta il profilo:```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"
Questo metodo consente di utilizzare il profilo appropriato in modo implicito. Nota che qualsiasi variabile d'ambiente impostata come parte del flusso exec avrà precedenza su ciò che è già impostato nel tuo ambiente.
Gli utenti AWS federati spesso hanno un attributo "significativo" mappato sul loro ruolo assunto, come un indirizzo email, tramite la configurazione AWS dell'account. Queste sessioni assunte hanno alcune parti, il role id e caller-specified-role-name. Per impostazione predefinita, quando un utente federato usa l'opzione --role di aws-iam-authenticator per assumere un nuovo ruolo, il caller-specified-role-name viene convertito in un token casuale e il role id viene propagato al ruolo appena assunto.
L'uso di aws-iam-authenticator token ... --forward-session-name mapperà l'attributo originale caller-specified-role-name sulla nuova sessione assunta di STS. Questo può essere utile per tentare rapidamente di associare "chi ha eseguito l'azione X sul cluster K8".
Si prega di notare, questo non deve essere considerato definitivo e deve essere incrociato tramite il role id (che rimane coerente) con i log di CloudTrail, poiché un utente potrebbe potenzialmente modificarlo lato client.
È possibile effettuare richieste all'API Kubernetes da un client esterno al cluster, sia utilizzando la nuda API REST Kubernetes sia uno dei client Kubernetes specifici per linguaggio (ad es. Python). Per farlo, è necessario creare un bearer token da includere nella richiesta all'API. Questo bearer token richiede di anteporre la stringa k8s-aws-v1. a una stringa codificata in base64 di una richiesta HTTP firmata all'API Query GetCallerIdentity di STS. Questa viene poi inviata nell'intestazione Authorization della richiesta. Da notare, tuttavia, che IAM Authenticator omette esplicitamente il padding base64 per evitare qualsiasi carattere =, garantendo così una stringa sicura per l'uso negli URL. Di seguito è riportato un esempio in Python di come verrebbe costruito questo token:```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')}
## Risoluzione dei problemi
Se il tuo client fallisce con un errore come `could not get token: AccessDenied [...]`, puoi provare ad assumere il ruolo direttamente con l'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
Se ciò non funziona, ci sono alcuni possibili problemi da verificare:
Assicurati che le tue credenziali AWS di base siano disponibili nella tua shell (aws sts get-caller-identity può aiutare a risolvere questo problema).
Assicurati che il ruolo di destinazione consenta l'accesso dal tuo account di origine (nella policy di trust del ruolo).
Assicurati che il tuo principale di origine (utente/ruolo/gruppo) abbia una policy IAM che consenta sts:AssumeRole per il ruolo di destinazione.
Assicurati di non avere policy di rifiuto esplicite collegate al tuo utente, gruppo o in AWS Organizations che possano impedire sts:AssumeRole.
Prova a simulare la chiamata sts:AssumeRole nel Policy Simulator.
Il client e il server hanno lo stesso formato di configurazione. Possono condividere esattamente lo stesso file di configurazione, poiché non ci sono segreti memorizzati nella configurazione.```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:
## Sviluppo
Vedi la pagina [sviluppo](https://github.com/kubernetes-sigs/aws-iam-authenticator/blob/HEAD/docs/development.md).
## Community, discussione, contributi e supporto
Scopri come interagire con la community di Kubernetes nella [pagina community](http://kubernetes.io/community/).
Puoi contattare i manutentori di questo progetto su:
- [Slack](https://kubernetes.slack.com/messages/sig-aws)
- [Mailing List](https://groups.google.com/forum/#!forum/kubernetes-sig-aws)
### Codice di condotta
La partecipazione alla community di Kubernetes è regolata dal [Codice di condotta di Kubernetes](https://github.com/kubernetes-sigs/aws-iam-authenticator/blob/HEAD/code-of-conduct.md).