Adición de un certificado a una aplicación mediante Microsoft Graph
Artículo
Azure Active Directory (Azure AD) admite tres tipos de credenciales para autenticar aplicaciones y entidades de servicio: contraseñas (secretos de aplicación), certificados y credenciales de identidad federada. Si no puede usar credenciales de identidad federada para la aplicación, se recomienda encarecidamente usar certificados en lugar de secretos.
Puede agregar o quitar certificados mediante el Azure Portal. Sin embargo, en escenarios de automatización, es posible que tenga que automatizar la sustitución de certificados para la aplicación o la entidad de servicio.
En este artículo se proporcionan instrucciones para usar scripts de Microsoft Graph y PowerShell para actualizar las credenciales de certificado mediante programación para un registro de aplicaciones.
Requisitos previos
Para completar este tutorial, necesita los siguientes recursos y privilegios:
Un inquilino activo de Azure AD.
Un cliente de API como Graph Explorer. Inicie sesión como usuario con un rol de administrador de aplicaciones o un usuario con permiso para crear y administrar aplicaciones en el inquilino.
El uso de certificados es muy recomendable sobre los secretos; sin embargo, no se recomienda usar certificados autofirmados. Pueden reducir la barra de seguridad de la aplicación debido a diversos factores, como el uso de un hash y conjuntos de cifrado obsoletos o la falta de validación. Se recomienda adquirir certificados de una entidad de certificación de confianza conocida.
Paso 1: Leer los detalles del certificado
Para agregar un certificado mediante programación mediante Microsoft Graph, necesita la clave del certificado. Opcionalmente, puede agregar la huella digital del certificado.
[Opcional] Obtención de la huella digital del certificado
Es opcional agregar la huella digital del certificado a la carga de la solicitud. Si desea agregar la huella digital, puede ejecutar la siguiente solicitud de PowerShell para leer la huella digital del certificado. En esta solicitud se supone que ha generado y exportado el certificado a la unidad local.
Solicitud
Get-PfxCertificate -Filepath "C:\Users\admin\Desktop\20230112.cer" | Out-File -FilePath "C:\Users\admin\Desktop\20230112.cer.thumbprint.txt" ## Replace the file path with the source of your certificate
Respuesta
La salida que se guarda en el archivo .txt puede ser similar a la siguiente.
Para leer la clave del certificado mediante PowerShell, ejecute la siguiente solicitud.
Solicitud
[convert]::ToBase64String((Get-Content C:\Users\admin\Desktop\20230112.cer -Encoding byte)) | Out-File -FilePath "C:\Users\admin\Desktop\20230112.key.txt" ## Replace the file path with the location of your certificate
Respuesta
La salida que se guarda en el archivo .txt puede ser similar a la siguiente.
Nota: La clave que se muestra aquí se ha acortado para mejorar la legibilidad.
Paso 2: Agregar los detalles del certificado mediante Microsoft Graph
Solicitud
La siguiente solicitud agrega los detalles del certificado a una aplicación. La configuración es la siguiente:
StartDateTime es la fecha en que o después de crear el certificado.
EndDateTime puede ser un máximo de un año desde startDateTime. Si no se especifica, el sistema asignará automáticamente una fecha un año después de startDateTime.
El tipo y el uso deben ser AsymmetricX509Cert y Verify respectivamente.
Asigne el nombre del firmante del certificado a la propiedad displayName .
La clave es el valor codificado en Base64 que generó en el paso anterior.
Nota:
Si la aplicación tiene un certificado válido existente que desea seguir usando para la autenticación, incluya los detalles del certificado actual y el nuevo en el objeto keyCredentials de la aplicación. Dado que se trata de una llamada PATCH, que por protocolo reemplaza el contenido de la propiedad por los nuevos valores, incluido solo el nuevo certificado reemplazará los certificados existentes por el nuevo.
En el ejemplo siguiente se agrega un nuevo certificado y se reemplazan los certificados existentes.
Nota: La clave que se muestra aquí se ha acortado para mejorar la legibilidad.
// Code snippets are only available for the latest version. Current version is 5.x
var graphClient = new GraphServiceClient(requestAdapter);
var requestBody = new Application
{
KeyCredentials = new List<KeyCredential>
{
new KeyCredential
{
EndDateTime = DateTimeOffset.Parse("2024-01-11T15:31:26Z"),
StartDateTime = DateTimeOffset.Parse("2023-01-12T15:31:26Z"),
Type = "AsymmetricX509Cert",
Usage = "Verify",
Key = Convert.FromBase64String("base64MIIDADCCAeigAwIBAgIQP6HEGDdZ65xJTcK4dCBvZzANBgkqhkiG9w0BAQsFADATMREwDwYDVQQDDAgyMDIzMDExMjAeFw0yMzAxMTIwODExNTZaFw0yNDAxMTIwODMxNTZaMBMxETAPBgNVBAMMCDIwMjMwMTEyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAseKf1weEacJ67D6/...laxQPUbuIL+DaXVkKRm1V3GgIpKTBqMzTf4tCpy7rpUZbhcwAFw6h9A=="),
DisplayName = "CN=20230112",
},
},
};
var result = await graphClient.Applications["{application-id}"].PatchAsync(requestBody);
<?php
// THIS SNIPPET IS A PREVIEW FOR THE KIOTA BASED SDK. NON-PRODUCTION USE ONLY
$graphServiceClient = new GraphServiceClient($requestAdapter);
$requestBody = new Application();
$keyCredentialsKeyCredential1 = new KeyCredential();
$keyCredentialsKeyCredential1->setEndDateTime(new DateTime('2024-01-11T15:31:26Z'));
$keyCredentialsKeyCredential1->setStartDateTime(new DateTime('2023-01-12T15:31:26Z'));
$keyCredentialsKeyCredential1->setType('AsymmetricX509Cert');
$keyCredentialsKeyCredential1->setUsage('Verify');
$keyCredentialsKeyCredential1->setKey(base64_decode('base64MIIDADCCAeigAwIBAgIQP6HEGDdZ65xJTcK4dCBvZzANBgkqhkiG9w0BAQsFADATMREwDwYDVQQDDAgyMDIzMDExMjAeFw0yMzAxMTIwODExNTZaFw0yNDAxMTIwODMxNTZaMBMxETAPBgNVBAMMCDIwMjMwMTEyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAseKf1weEacJ67D6/...laxQPUbuIL+DaXVkKRm1V3GgIpKTBqMzTf4tCpy7rpUZbhcwAFw6h9A=='));
$keyCredentialsKeyCredential1->setDisplayName('CN=20230112');
$keyCredentialsArray []= $keyCredentialsKeyCredential1;
$requestBody->setKeyCredentials($keyCredentialsArray);
$result = $graphServiceClient->applications()->byApplicationId('application-id')->patch($requestBody);
En el ejemplo siguiente se agrega un nuevo certificado sin reemplazar el certificado existente identificado por la huella digital 52ED9B5038A47B9E2E2190715CC238359D4F8F73.
Nota: La clave que se muestra aquí se ha acortado para mejorar la legibilidad.
// Code snippets are only available for the latest version. Current version is 5.x
var graphClient = new GraphServiceClient(requestAdapter);
var requestBody = new Application
{
KeyCredentials = new List<KeyCredential>
{
new KeyCredential
{
EndDateTime = DateTimeOffset.Parse("2024-01-11T15:31:26Z"),
StartDateTime = DateTimeOffset.Parse("2023-01-12T09:31:26Z"),
Type = "AsymmetricX509Cert",
Usage = "Verify",
Key = Convert.FromBase64String("base64MIIDADCCAeigAwIBAgIQejfrj3S974xI//npv7hFHTANBgkqhkiG9w0BAQsFADATMREwDwYDVQQDDAgyMDIzMDExNDAeFw0yMzAxMTIwOTA4NThaFw0yNDAxMTIwOTI4NThaMBMxETAPBgNVBAMMCDIwMjMwMTE0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt5vEj6j1l5wOVHR4eDGe77HWslaIVJ1NqxrXPm/...+R+U7sboj+kUvmFzXI+Ge73Liu8egL2NzOHHpO43calWgq36a9YW1yhBQR1ioEchu6jmudW3rF6ktmVqQ=="),
DisplayName = "CN=20230114",
},
new KeyCredential
{
CustomKeyIdentifier = Convert.FromBase64String("52ED9B5038A47B9E2E2190715CC238359D4F8F73"),
Type = "AsymmetricX509Cert",
Usage = "Verify",
Key = Convert.FromBase64String("base64MIIDADCCAeigAwIBAgIQfoIvchhpToxKEPI4iMrU1TANBgkqhkiG9w0BAQsFADATMREwDwYDVQQDDAgyMDIzMDExMzAeFw0yMzAxMTIwODI3NTJaFw0yNDAxMTIwODQ3NTJaMBMxETAPBgNVBAMMCDIwMjMwMTEzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw+iqg1nMjYmFcFJh/.../S5X6qoEOyJBgtfpSBANWAdA=="),
DisplayName = "CN=20230113",
},
},
};
var result = await graphClient.Applications["{application-id}"].PatchAsync(requestBody);
<?php
// THIS SNIPPET IS A PREVIEW FOR THE KIOTA BASED SDK. NON-PRODUCTION USE ONLY
$graphServiceClient = new GraphServiceClient($requestAdapter);
$requestBody = new Application();
$keyCredentialsKeyCredential1 = new KeyCredential();
$keyCredentialsKeyCredential1->setEndDateTime(new DateTime('2024-01-11T15:31:26Z'));
$keyCredentialsKeyCredential1->setStartDateTime(new DateTime('2023-01-12T09:31:26Z'));
$keyCredentialsKeyCredential1->setType('AsymmetricX509Cert');
$keyCredentialsKeyCredential1->setUsage('Verify');
$keyCredentialsKeyCredential1->setKey(base64_decode('base64MIIDADCCAeigAwIBAgIQejfrj3S974xI//npv7hFHTANBgkqhkiG9w0BAQsFADATMREwDwYDVQQDDAgyMDIzMDExNDAeFw0yMzAxMTIwOTA4NThaFw0yNDAxMTIwOTI4NThaMBMxETAPBgNVBAMMCDIwMjMwMTE0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt5vEj6j1l5wOVHR4eDGe77HWslaIVJ1NqxrXPm/...+R+U7sboj+kUvmFzXI+Ge73Liu8egL2NzOHHpO43calWgq36a9YW1yhBQR1ioEchu6jmudW3rF6ktmVqQ=='));
$keyCredentialsKeyCredential1->setDisplayName('CN=20230114');
$keyCredentialsArray []= $keyCredentialsKeyCredential1;
$keyCredentialsKeyCredential2 = new KeyCredential();
$keyCredentialsKeyCredential2->setCustomKeyIdentifier(base64_decode('52ED9B5038A47B9E2E2190715CC238359D4F8F73'));
$keyCredentialsKeyCredential2->setType('AsymmetricX509Cert');
$keyCredentialsKeyCredential2->setUsage('Verify');
$keyCredentialsKeyCredential2->setKey(base64_decode('base64MIIDADCCAeigAwIBAgIQfoIvchhpToxKEPI4iMrU1TANBgkqhkiG9w0BAQsFADATMREwDwYDVQQDDAgyMDIzMDExMzAeFw0yMzAxMTIwODI3NTJaFw0yNDAxMTIwODQ3NTJaMBMxETAPBgNVBAMMCDIwMjMwMTEzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw+iqg1nMjYmFcFJh/.../S5X6qoEOyJBgtfpSBANWAdA=='));
$keyCredentialsKeyCredential2->setDisplayName('CN=20230113');
$keyCredentialsArray []= $keyCredentialsKeyCredential2;
$requestBody->setKeyCredentials($keyCredentialsArray);
$result = $graphServiceClient->applications()->byApplicationId('application-id')->patch($requestBody);
Ha usado Microsoft Graph para actualizar las credenciales de certificado de un objeto de aplicación. Este proceso es una alternativa mediante programación al uso de la Azure Portal. También puede actualizar las credenciales de certificado de una entidad de servicio siguiendo un proceso similar y llamando al punto de https://graph.microsoft.com/v1.0/servicePrincipals/ conexión.