Blog de Amazon Web Services (AWS)

Autenticación de Windows sin dominio para Amazon EKS Windows pods

Por Marcio Morales and Hamzah Abdulla, Arquitecto Principal de Soluciones y Consultor de DevOps en AWS 

Introducción

Los desarrolladores de .NET suelen diseñar aplicaciones basadas en Windows con la integración de Active Directory (AD) que se ejecutan en servidores unidos a un dominio para facilitar la autenticación y la autorización entre los servicios y los usuarios. Como los contenedores no se pueden unir a un dominio, ejecutar estas aplicaciones en contenedores basados en Windows requería configurar las cuentas de servicios gestionados (gMSA) grupales, los nodos de Windows de Kubernetes unidos a un dominio, los webhooks y las funciones de clúster para permitir la autenticación de Windows en los contenedores basados en Windows. Esto generaba una sobrecarga de administración adicional, como la limpieza de las cuentas de los equipos de AD en cada evento de escalado, además de aumentar drásticamente el tiempo de arranque en cada nodo de Windows debido al proceso de unión de dominios. Eso era, hasta ahora.

A partir de 2022, en Windows Server 2019/ 2022, Microsoft puso a disposición la interfaz ICCGDomainAuthCredentials, que permitió a los desarrolladores desarrollar un complemento que permitiera a los nodos de Windows no unidos a un dominio recuperar las credenciales de gMSA al reemplazar el enfoque de host unido a un dominio por una identidad de usuario portátil en lugar de una cuenta de equipo host.

AWS desarrolló su propio complemento y, que está integrado en la AMI de Windows optimizada para Amazon Elastic Kubernetes Service (Amazon EKS), resolvió la sobrecarga de administración del escalado y simplificó el proceso de ejecución de cargas de trabajo de contenedores basadas en Windows en Amazon EKS.

Descripción general de la solución

AWS gMSA plugion workflow

  1. En primer lugar, el Windows Pod hace referencia a GMSAcredentialSpec, disponible en la API windows.k8s.io/v1. En segundo lugar, el webhook de validación de GMSA garantiza que el pod de Windows tenga permiso para hacer referencia a GMSAcredentialSpec. Por último, el webhook mutante expande GMSAcredentialSpec al formato JSON completo en el pod.
  2. El proceso ccg.exe que se ejecuta en el nodo de Windows inicia el complemento especificado en CredSpec en el campo PluginID y, a continuación, recupera las credenciales de identidad portátiles de AWS Secrets Manager o AWS System Manager Parameter Store.
  3. El ccg.exe utiliza las credenciales de identidad portátiles para autenticarse con AWS Managed AD o Amazon Elastic Compute Cloud (Amazon EC2) para recuperar la contraseña de gMSA.
  4. El ccg.exe utiliza las credenciales de identidad portátiles para autenticarse con AWS Managed AD o Amazon Elastic Compute Cloud (Amazon EC2) para recuperar la contraseña de gMSA.
  5. El ccg.exe utiliza las credenciales de identidad portátiles para autenticarse con AWS Managed AD o Amazon Elastic Compute Cloud (Amazon EC2) para recuperar la contraseña de gMSA.
  6. El token se almacena en caché y la aplicación se ejecuta como servicio de red o sistema local en el pod, lo que puede autenticar y acceder a los recursos del dominio (es decir, archivos compartidos, bases de datos de SQL Server, sitios de IIS, etc.)

En esta publicación se describen los pasos necesarios para configurar esta funcionalidad para los pods de Windows que se ejecutan en nodos de trabajo de Windows que no están unidos a un dominio en Amazon EKS.

Prerrequisitos y suposiciones:

  • Tiene un clúster de Amazon EKS que ejecuta la versión 1.22 o posterior con nodos de Windows.
  • Nodos de Windows autogestionados o gestionados basados en la AMI de Windows optimizada de Amazon EKS.
  • Ha instalado y configurado correctamente AWS Command Line Interface (AWS CLI) y kubectl en Amazon EC2 Linux.
  • Tiene un servicio de dominio de Active Directory (AD DS) al que se puede acceder desde el clúster de Amazon EKS. Puede ser un AD autogestionado o un AD de Microsoft gestionado por AWS.
  • Los nodos de Windows que se ejecutan en el clúster Amazon EKS pueden resolver el FQDN del dominio AD.

Descripción general de las tareas que trataremos en esta publicación:

  1. Cree una cuenta de AD GMSA, una identidad portátil y un grupo.
  2. Implemente el controlador Webhook de admisión gMSA de Windows en el clúster Amazon EKS.
  3. Cree un recurso de gMSA CredentialSpec y utilice AWS Secret Manager como almacén de credenciales.
  4. Crea un ClusterRole y un RoleBinding de Kubernetes.
  5. Configure el gMSA CredentialSpec en la especificación del pod de Windows.
  6. Pruebe la autenticación de Windows desde el interior del pod de Windows.
  7. Ubicaciones de registro.
  8. (Opcional) Utilizar el almacén de parámetros de AWS System Manager como almacén de credenciales

Tutorial

1. Crear y configurar una cuenta gMSA en el dominio de Active Directory

Si aún no ha creado una cuenta de servicio de gMSA en su dominio, primero tendrá que generar una clave raíz del Servicio de distribución de claves (KDS). El KDS es responsable de crear, rotar y divulgar la contraseña de gMSA a los anfitriones autorizados. Cuando el archivo ccg.exe necesita recuperar las credenciales de gMSA, se pone en contacto con KDS para recuperar la contraseña actual. Si utiliza AWS Managed AD, puede ir directamente al paso 2.3. Los permisos de gMSA están preconfigurados con su Microsoft AD administrado por AWS. Como resultado, no es necesario que genere la clave raíz de KDS para generar las contraseñas de gMSA.

1.1 Para comprobar si la clave raíz de KDS ya se ha creado, ejecute el siguiente cmdlet de PowerShell con privilegios de administrador de dominio en un controlador de dominio mediante el módulo AD PowerShell:

Get-KdsRootKey

1.2 Si el comando devuelve un identificador de clave, ya está todo listo. De lo contrario, cree la clave raíz de KDS ejecutando el siguiente comando:

Add-KdsRootKey -EffectiveImmediately

Si bien el comando implica que la clave entra en vigor inmediatamente, debe esperar 10 horas antes de que la clave raíz de KDS se replique y esté disponible para su uso en todos los controladores de dominio. Si estás interesado en entender mejor las cuentas de gMSA, consulta la documentación oficial de Microsoft.

1.3 Para crear la cuenta de gMSA y permitir que ccg.exe recupere la contraseña de gMSA, ejecute los siguientes comandos de PowerShell desde un servidor o cliente de Windows con acceso al dominio de AD.

# Install the RSAT AD Feature
Install-WindowsFeature RSAT-AD-PowerShell

# Create the AD group - Replace Name and SamAccountName values with yours preference.
New-ADGroup -Name "Amazon EKS Authorized Portable Identity" -SamAccountName "EKSPortableIdentity" -GroupScope DomainLocal

# Create the gMSA - Replace Name value with yours preference
New-ADServiceAccount -Name "gmsaeks" -DnsHostName "gmsaeks.YOURDOMAIN_FQDN" -ServicePrincipalNames "host/gmsaeks", "host/gmsaeks.YOURDOMAIN_FQDN" -PrincipalsAllowedToRetrieveManagedPassword "EKSPortableIdentity"

# Create the portable identity user account - Replace Name value with yours preference
New-ADUser -Name "eks-portable-identity" -AccountPassword (ConvertTo-SecureString -AsPlainText "YOUR_PASSWORD" -Force) -Enabled 1 

# Add your Windows Worker Node the AD group
Add-ADGroupMember -Identity "EKSPortableIdentity" -Members "eks-portable-identity"

Nota: Sustituya YOURDOMAIN_FQDN por su nombre de dominio completo. Sustituya YOUR_PASSWORD por una contraseña única y guárdela en una tienda secreta para que la recupere el complemento CCG. Reemplazar.

2. Implemente el controlador Webhook de admisión gMSA de Windows en el clúster Amazon EKS

El repositorio gMSA de Windows implementa dos webhooks, según la documentación de Kubernetes, que son:

  1. Un webhook mutante que expande las referencias a los GMSA (por su nombre de una especificación de Pod) al CredentialSpec completo en formato JSON dentro de la especificación de Pod.
  2. Un webhook de validación garantiza que la cuenta de servicio Pod autorice el uso de todas las referencias a los GMSA.

Según la documentación de firma de certificados de Amazon EKS, todos los clústeres que ejecuten la versión 1.22 o posterior de Amazon EKS admiten el firmante beta.eks.amazonaws.com/app-serving para las solicitudes de firma de certificados (CSR) de Kubernetes. Como resultado, sustituiremos el firmante kubernetes.io/kubelet-serving del archivo del certificado de webhook de admisión de gMSA por el firmante beta.eks.amazonaws.com/app-serving compatible con Amazon EKS.

2.1 Desde un sistema basado en Linux, ejecute el siguiente comando. Esto implementa el controlador de admisión gMSA Webhook y actualiza el archivo del firmante.

git clone https://github.com/kubernetes-sigs/windows-gmsa.git
cd windows-gmsa/admission-webhook/deploy
sed -i.back "s/signerName: kubernetes.io\/kubelet-serving/signerName: beta.eks.amazonaws.com\/app-serving/g" create-signed-cert.sh
K8S_GMSA_DEPLOY_DOWNLOAD_REV='v0.6.0' ./deploy-gmsa-webhook.sh --file ./gmsa-manifests --image registry.k8s.io/gmsa-webhook/k8s-gmsa-webhook:v0.6.0

Nota: Comprueba siempre la versión más reciente de gMSA admission-webhook en kubernetes-sigs/windows-gmsa.

El resultado debería tener el siguiente aspecto:

3. Cree recursos de gMSA CredentialSpec y utilice AWS Secret Manager como almacén de credenciales.

Una vez que los recursos de gMSA se hayan implementado correctamente en el clúster de Amazon EKS, junto con los webhooks CRD y gMSA de CredentialSpec para rellenar y validar el recurso en todo el clúster, ahora generaremos e implementaremos el recurso GMSA CredentialSpec en el clúster de Amazon EKS.

El gMSA CredentialSpec contiene metadatos que el proceso ccg.exe del nodo host utiliza para determinar qué cuenta de gMSA recuperar, las credenciales de identidad portátiles y el ID del complemento que se va a utilizar. En este primer ejemplo, utilizaremos AWS Secrets Manager para almacenar la credencial de identidad portátil.

3.1 Primero, creemos un AWS Secret Manager para almacenar la credencial de identidad portátil. Ejecute el siguiente comando de AWS CLI y sustituya el usuario, la contraseña y el nombre de dominio para que coincidan con su entorno y guarde el ARN para usarlo en el paso 4.2.

aws secretsmanager create-secret \
--name gmsa-plugin-input \
--description "Amazon EKS - gMSA Portable Identity." \
--secret-string "{\"user\":\"eks-portable-identity\",\"password\":\"YOURPASSWORD\",\"domainName\":\"YOURDOMAIN_FQDN\"}"

Nota: Reemplace el usuario por su credencial de identidad portátil. Sustituya YOUR_PASSWORD, la contraseña de identidad portátil, por la que creó en el paso 1.3. Sustituya YOURDOMAIN_FQDN por su nombre de dominio completo.

3.2 En segundo lugar, añada la siguiente política en línea de AWS Identity and Access Management (AWS IAM) al rol de AWS IAM existente en el nodo de Windows. Esta política de AWS IAM permite a los nodos de Windows leer el secreto creado en el paso anterior.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "secretsmanager:GetSecretValue",
            "Resource": "ARN-SECRET"
        }
    ]
}

Nota: Sustituya SECRET-ARN por su ARN secreto creado en AWS Secret Manager.

3.3 Ahora, vamos a crear el archivo gMSA CredentialSpec y aplicarlo al clúster de Amazon EKS. Crea un archivo que contenga el siguiente código y guárdalo como domainless-credspec-secretmanager.yaml.

apiVersion: windows.k8s.io/v1
kind: GMSACredentialSpec
metadata:
  name: gmsaeks-domainless
credspec:
  CmsPlugins:
  - ActiveDirectory
  DomainJoinConfig:
    Sid: gMSA-ACCOUNT-SID
    MachineAccountName: gMSA-ACCOUNT-NAME
    Guid: gMSA-ACCOUNT-GUID
    DnsTreeName: YOURDOMAIN_FQDN
    DnsName: YOURDOMAIN_FQDN
    NetBiosName: YOURDOMAIN_NETBIOS
  ActiveDirectoryConfig:
    GroupManagedServiceAccounts:
    - Name: gMSA-ACCOUNT-NAME
      Scope: YOURDOMAIN_FQDN
    - Name: gMSA-ACCOUNT-NAME
      Scope: YOURDOMAIN_NETBIOS
    HostAccountConfig:
      PortableCcgVersion: "1"
      PluginGUID: "{859E1386-BDB4-49E8-85C7-3070B13920E1}"
      PluginInput: "{\"credentialArn\":\"ARN-SECRET\"}"

Nota: Sustituya los valores para que coincidan con su entorno. Puede ejecutar el siguiente comando de PowerShell en una terminal de Windows con acceso a su dominio de Active Directory para recuperar el SID y el GUID de la cuenta de GMSA: Get-ADServiceAccount -Identity gMSA-account-name

El archivo debería tener el siguiente aspecto:

apiVersion: windows.k8s.io/v1
kind: GMSACredentialSpec
metadata:
  name: gmsaeks-domainless
credspec:
  CmsPlugins:
  - ActiveDirectory
  DomainJoinConfig:
    Sid: S-1-5-21-857038504-468933455-1338018723
    MachineAccountName: gmsaeks
    Guid: 59d60a02-be02-4fd3-8a7f-c7c6c0daceaa
    DnsTreeName: marciomorales.local
    DnsName: marciomorales.local
    NetBiosName: marciomorales
  ActiveDirectoryConfig:
    GroupManagedServiceAccounts:
    - Name: gmsaeks
      Scope: marciomorales.local
    - Name: gmsaeks
      Scope: marciomorales
    HostAccountConfig:
      PortableCcgVersion: "1"
      PluginGUID: "{859E1386-BDB4-49E8-85C7-3070B13920E1}"
      PluginInput: "{\"credentialArn\":\"arn:aws:secretsmanager:us-east-1:0123456789:secret:gmsa-plugin-input-tBOL0j\"}"

3.4 Cree el recurso gMSA CredentialSpec en el clúster con el siguiente comando:

kubectl create -f domainless-credspec-secretmanager.yaml

4. Crea un ClusterRole y un RoleBinding de Kubernetes

Se necesitan un ClusterRole y un RoleBinding para que su pod pueda utilizar la gMSA CredentialSpec.

4.1 Cree un archivo que contenga el código siguiente y guárdelo como gmsa-domainless-clusterrole.yaml.

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: eksgmsa-role-domainless
rules:
- apiGroups: ["windows.k8s.io"]
  resources: ["gmsacredentialspecs"]
  verbs: ["use"]
  resourceNames: ["gmsaeks-domainless"]
  
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: gmsa-assign-role-domainless
  namespace: default
subjects:
- kind: ServiceAccount
  name: default
  namespace: default
roleRef:
  kind: ClusterRole
  name: eksgmsa-role-domainless
  apiGroup: rbac.authorization.k8s.io

Nota: Sustituya ResourceNames por el generado en el paso 4.3 si es diferente de lo que especificamos.

4.2 Cree ClusterRole y RoleBinding en el clúster con el siguiente comando:

kubectl apply -f gmsa-domainless-clusterrole.yaml

5. Configure el gMSA CredentialSpec en la especificación del pod de Windows

Para comprobar que nuestra configuración funciona, tendremos que implementar un pod de Windows con el campo de especificación SecurityContext.WindowsOptions.gmsAcredentialSpecName para hacer referencia a nuestro recurso personalizado GMSA CredentialSpec que creamos e implementamos en el paso 4.

5.1 Cree un archivo que contenga el código siguiente y guárdelo como windows-auth-pod.yaml.

piVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: amazon-eks-gmsa-domainless
  name: amazon-eks-gmsa-domainless
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      run: amazon-eks-gmsa-domainless
  template:
    metadata:
      labels:
        run: amazon-eks-gmsa-domainless
    spec:
      securityContext:
        windowsOptions:
          gmsaCredentialSpecName: gmsaeks-domainless
      containers:
      - image: mcr.microsoft.com/windows/servercore:ltsc2019
        imagePullPolicy: Always
        name: gmsadomainless
        command:
          - "powershell.exe"
          - "-Command"
          - "while (1) { sleep 1 }"
      nodeSelector:
        kubernetes.io/os: windows

Nota: Sustituya el valor GMSAcredentialSpecName por el nombre del gMSA CredentialSpec que creó en el paso 4.2. Para esta publicación, utilizamos gmsaeks-domainless.

5.2 Despliegue el pod de Windows mediante el siguiente comando:

kubectl apply -f windows-auth-pod.yaml

6. Pruebe la autenticación de Windows desde el interior del pod de Windows

6.1 Ejecute el siguiente comando para abrir una sesión de PowerShell en nuestro pod de prueba desde el paso 7.2:

kubectl exec -it PODNAME -- powershell.exe

Nota: Reemplaza PODNAME por el nombre de tu pod. Puedes recuperar el nombre del pod de la lista de salidas cuando ejecutas kubectl get pods.

6.2 Desde la sesión de PowerShell del pod, ejecute el siguiente comando para verificar la identidad de gMSA y el nombre del cliente. En este post, gmsaeks es la identidad, esto se puede ver en el siguiente diagrama.

klist get krbtgt

6.3 Además, puede utilizar nltest para comprobar que la conexión DC de confianza se ha realizado correctamente ejecutando el siguiente comando:

nltest /sc_verify:YOURDOMAINFQDN

7. Ubicaciones de registro

  • Los eventos se registran en el archivo de registro Microsoft-Windows-Containers-CCG y se encuentran en el Event Viewer, en Applications and Services Logs\Microsoft\Windows\Containers-CCG\Admin. Consulte más consejos de depuración en la guía proporcionada por Microsoft: Solucionar problemas de GMSA para contenedores de Windows.
  • Registro básico para el complemento en el nodo de Windows no unido a un dominio: C: \ProgramData\Amazon\GMSA-Plugin/

8. (Opcional) Utilizar el almacén de parámetros de AWS System Manager como almacén de credenciales.

Es posible que prefiera utilizar el almacén de parámetros de AWS System Manager como almacén de credenciales en lugar de AWS Secret Manager. El complemento de AWS admite ambas opciones, pero solo se puede usar una por identidad portátil. Si este es el caso, cree el parámetro en SSM para almacenar la credencial de identidad portátil.

8.1 Cree un archivo JSON que contenga los valores que compondrán el parámetro SSM:

{
    "Name": "gmsa-plugin-input",
    "Value": "{\n\"username\": \"eks-portable-identity\",\n\"password\": \"YOUR_PASSWORD\",\n\"domainName\": \"YOURDOMAIN_FQDN\"\n}",
    "Type": "SecureString"
}

Nota: Sustituya el nombre de usuario por su credencial de identidad portátil. Sustituya YOUR_PASSWORD, la contraseña de identidad portátil, por la que creó en el paso 1.3. Sustituya YOURDOMAIN_FQDN por su nombre de dominio completo.

8.2 Cree el parámetro SSM mediante el siguiente comando:

aws ssm put-parameter \
    --type "SecureString" \
    --key-id "KMS-KEY-ARN" \
    --cli-input-json file://gmsa-json-parameterstore.json

Nota: Sustituya el valor del identificador de clave por el ARN de la clave de KMS en el que desea cifrar el parámetro. Reemplaza la ruta del archivo por la que guardaste el archivo JSON.

8.3 Añada la siguiente política en línea de AWS IAM al rol de AWS IAM de nodo de Windows existente. Esta política de AWS IAM permite a los nodos de Windows leer el secreto almacenado en el almacén de parámetros de AWS System Manager.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ssm:GetParameters"
            ],
            "Resource": [
                "ARN-PARAMETER-STORE"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "kms:Decrypt"
            ],
            "Resource": [
                "ARN-KMS-KEY"
            ]
        }
    ]
}

8.4 Cree el recurso gMSA CredentialSpec en el clúster que apunta a usar el almacén de parámetros con el siguiente comando y guárdelo como domainless-credspec-parameterstore.yaml.

apiVersion: windows.k8s.io/v1
kind: GMSACredentialSpec
metadata:
  name: gmsaeks-domainless
credspec:
  CmsPlugins:
  - ActiveDirectory
  DomainJoinConfig:
    Sid: gMSA-ACCOUNT-SID
    MachineAccountName: gMSA-ACCOUNT-NAME
    Guid: gMSA-ACCOUNT-GUID
    DnsTreeName: YOURDOMAIN_FQDN
    DnsName: YOURDOMAIN_FQDN
    NetBiosName: YOURDOMAIN_NETBIOS
  ActiveDirectoryConfig:
    GroupManagedServiceAccounts:
    - Name: gMSA-ACCOUNT-NAME
      Scope: YOURDOMAIN_FQDN
    - Name: gMSA-ACCOUNT-NAME
      Scope: YOURDOMAIN_NETBIOS
    HostAccountConfig:
      PortableCcgVersion: "1"
      PluginGUID: "{859E1386-BDB4-49E8-85C7-3070B13920E1}"
      PluginInput: "{\"credentialArn\":\"ARN-PARAMETER-STORE\"}"

8.5 Cree el recurso gMSA CredentialSpec en el clúster con el siguiente comando:

kubectl create -f domainless-credspec-parameterstore.yaml

Lecturas adicionales:

En esta publicación, le mostramos un enfoque integral para configurar la autenticación de Windows para los pods de Windows que se ejecutan en nodos de trabajo de Windows que no están unidos a un dominio en un clúster de Amazon EKS. Nuestro enfoque incluía el uso del complemento de AWS para recuperar una contraseña de gMSA del AD y cambiarla por un ticket de Kerberos que permitía a los pods de Windows autenticarse con los recursos de AD. Muchas aplicaciones de ASP.NET reconfiguradas para ejecutarse sobre Amazon EKS pueden utilizar esta funcionalidad para seguir ofreciendo la autenticación de Windows basada en el protocolo Kerberos v5.

Lecturas adicionales:

Autenticação do Windows ingressada no domínio no Amazon EKS

Contêiner do Windows e contas de serviço

Solucionar problemas de gMSAs para contêineres do Windows

Configurar GMSA para pods e contêineres do Windows (documentação oficial do Kubernetes)

Este artículo fue traducido del Blog de AWS en Inglés

Acerca de los autores

Marcio Morales es arquitecto principal de soluciones en Amazon Web Services. Marcio es una pyme global dedicada a Windows Containers y ayuda a los clientes de AWS a diseñar, crear, proteger y optimizar las cargas de trabajo de Windows Container en AWS.

 

 

 

 

Hamzah Abdulla es consultor de DevOps en AWS Professional Services. Aprovecha su experiencia en MLOps, Kubernetes e IaC para acelerar el viaje de adopción de la nube para los clientes en la industria de servicios financieros. Ha estado en AWS desde julio de 2021. Fuera del trabajo, le gusta caminar, viajar, leer y actualmente está aprendiendo español en su tiempo libre.

 

 

 

 

Revisores

Luciano Bernardes Bernardes trabaja actualmente como arquitecto de soluciones sénior en AWS y se especializa en cargas de trabajo de Microsoft. Con 16 años de experiencia en el mercado, trabajó principalmente en consultoría técnica especializada en Microsoft, con clientes de diversos sectores, con demandas centradas en la infraestructura local y en la nube. Como SA, trabaja en estrecha colaboración con clientes y socios consultores en EE. UU. y Latinoamérica para ayudarlos a tomar decisiones y revisar la arquitectura de las cargas de trabajo de Microsoft en la nube de AWS.

 

 

 

 

JuanMa Silva quien es arquitecto de soluciones con especialidad en Microsoft para México y MCO. Cuenta con 15 años de experiencia en la industria de IT, en posiciones de Sysadmin, consultor para ayudar a migrar clientes a la nube y modernización de aplicaciones, soporte aplicaciones de misión crítica basados en tecnologia Microsoft.