c# - microsoft - porta azure
Error al realizar la llamada a la API de Azure Management Library al autenticar con el directorio activo azul (1)
Creo que está en el camino correcto en cuanto a por qué se encuentra con este problema.
Esto es lo que está sucediendo:
Esencialmente, el permiso para ejecutar
Service Management API
es un
delegated permission and not an application permission
.
En otras palabras, la API se ejecuta en el contexto del usuario para el que se adquiere el token.
Ahora está obteniendo este token para su aplicación (especificado por la identificación / secreto del cliente).
Sin embargo, su aplicación no tiene acceso a su suscripción de Azure porque el registro de usuario creado para esta aplicación en su Azure AD es del tipo
Service Principal
.
Dado que este director de servicio no tiene acceso a su suscripción de Azure, está recibiendo este
Forbidden Error
(debo decir que el error es engañoso porque no está utilizando el certificado).
Hay algunas cosas que puedes hacer:
-
Cambie a la API de Azure Resource Manager (ARM): la API de
ARM es la próxima generación de API de administración de servicios (SM API) y Azure se está moviendo solo en esta dirección.
Funciona exclusivamente fuera del token de Azure AD.
Si es posible, utilícelo para administrar sus recursos de Azure (aunque debe tener en cuenta que a partir de hoy no todos los recursos de Azure se pueden administrar a través de la API de ARM).
La forma en que lo hace es tomar su Principal de Servicio y asignarlo a un rol particular usando el nuevo
Azure Portal
. Consulte este enlace para obtener más detalles al respecto: https://azure.microsoft.com/en-in/documentation/articles/resource-group-create-service-principal-portal/ . - Use el certificado X509 : siempre puede usar la autorización basada en el certificado X509 para autorizar sus solicitudes SM API. Consulte este enlace para obtener más detalles al respecto: https://msdn.microsoft.com/en-us/library/azure/ee460782.aspx#bk_cert . La desventaja de este enfoque es que la aplicación (o quien tenga acceso a este certificado) obtendrá acceso completo a su suscripción de Azure y puede hacer todo lo que esté allí (incluida la eliminación de recursos).
-
Adquiera token para un usuario en lugar de una aplicación
: este es otro enfoque que puede adoptar.
Esencialmente solicite a sus usuarios que inicien sesión en Azure AD a través de su aplicación de consola y adquieran tokens para ese usuario.
Nuevamente, tenga en cuenta que este usuario debe ser un
Co-Admin
en su suscripción de Azure y tendrá acceso completo a su suscripción de Azure, ya que con SM API no hay ningún concepto deRole-based access control
.
Mi empresa está investigando la posibilidad de informar sobre Azure. Solo queremos que nuestros clientes nos den credenciales de solo lectura para que las usemos. Investigué un poco y parece que Azure Active Directory hace exactamente eso. Por lo tanto, estoy buscando autenticarme con una aplicación Azure Directory de solo lectura.
Para comenzar, seguí este blog sobre el uso de la API de administración a través de Azure Active Directory.
https://msdn.microsoft.com/en-us/library/azure/dn722415.aspx
Aparte de que el enfoque muestra que es muy hostil, no funciona = (
Recibo este error después de iniciar sesión como administrador global:
"AADSTS90014: el cuerpo de la solicitud debe contener el siguiente parámetro: ''client_secret o client_assertion''".
Investigué un poco y descubrí que este estilo de autenticación era para aplicaciones nativas y NO para aplicaciones web (a pesar de lo que dice la publicación del blog de otra manera ...). Entonces hice un ajuste. Mi GetAuthorizationHeader ahora se ve así:
private static string GetAuthorizationHeader()
{
AuthenticationResult result = null;
var context = new AuthenticationContext("https://login.windows.net/" + ConfigurationManager.AppSettings["tenantId"]);
string clientId = ConfigurationManager.AppSettings["clientId"];
string clientSecret = ConfigurationManager.AppSettings["clientSecret"];
ClientCredential clientCred = new ClientCredential(clientId, clientSecret);
var thread = new Thread(() =>
{
result = context.AcquireToken(
"https://management.core.windows.net/",
clientCred);
});
thread.SetApartmentState(ApartmentState.STA);
thread.Name = "AquireTokenThread";
thread.Start();
thread.Join();
if (result == null)
{
throw new InvalidOperationException("Failed to obtain the JWT token");
}
string token = result.AccessToken;
return token;
}
Puedo obtener el token de acceso (yay). Pero ahora, cuando trato de usar esto con el cliente de la biblioteca de Azure Management, aparece este error:
"Error prohibido: el servidor no pudo autenticar la solicitud. Verifique que el certificado sea válido y esté asociado con esta suscripción".
Verifiqué dos veces mis permisos en mi aplicación. Se veía bien. Traté de dar acceso completo a todo para ver si eso habría marcado la diferencia.
Verifiqué dos veces mi tenantId, clientId y SubscribeId, todo se veía bien.
Me aseguré de que la suscripción que estoy usando apunte al AD en el que se encuentra mi aplicación.
Intenté hacer una nueva clave secreta.
Supongo que este es el problema: Sin embargo, en esta IU no puedo seleccionar ningún valor para esa propiedad. No estoy seguro de si esto es el resultado de un error o una característica inacabada. ¿Me estoy perdiendo de algo?
Gracias
Aquí está mi código completo para referencia:
class Program
{
static void Main(string[] args)
{
var token = GetAuthorizationHeader();
var credential = new TokenCloudCredentials(ConfigurationManager.AppSettings["subscriptionId"], token);
using (var computeClient = new ComputeManagementClient(credential))
{
var images = computeClient.VirtualMachineOSImages.List();
}
}
private static string GetAuthorizationHeader()
{
AuthenticationResult result = null;
var context = new AuthenticationContext("https://login.windows.net/" + ConfigurationManager.AppSettings["tenantId"]);
string clientId = ConfigurationManager.AppSettings["clientId"];
string clientSecret = ConfigurationManager.AppSettings["clientSecret"];
ClientCredential clientCred = new ClientCredential(clientId, clientSecret);
var thread = new Thread(() =>
{
result = context.AcquireToken(
"https://management.core.windows.net/",
clientCred);
});
thread.SetApartmentState(ApartmentState.STA);
thread.Name = "AquireTokenThread";
thread.Start();
thread.Join();
if (result == null)
{
throw new InvalidOperationException("Failed to obtain the JWT token");
}
string token = result.AccessToken;
return token;
}
}
EDITAR: Se han realizado progresos. Como discutí con Gaurav, ¡necesitaba deshacerme de la Biblioteca de administración de Azure porque en este momento no parece admitir la API de Azure Resource Manager (ARM)! Entonces, en su lugar, hice solicitudes web sin procesar. Y funciona según lo previsto. Si elimino el acceso a roles de mi aplicación AD, obtengo acceso denegado. Cuando lo tengo recupero los datos.
Una cosa de la que no estoy seguro es hacer que mi aplicación se agregue automáticamente a nuevos recursos.
Además, ¿hay alguna forma de enumerar los grupos de recursos que sean accesibles para mi aplicación AD?
Nuevo código:
class Program
{
static void Main(string[] args)
{
var token = GetAuthorizationHeader();
string subscriptionId = ConfigurationManager.AppSettings["subscriptionId"];
string resourceGroupName = ConfigurationManager.AppSettings["resourceGroupName"];
var uriListMachines = string.Format("https://management.azure.com/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Compute/virtualmachines?api-version=2015-05-01-preview", subscriptionId, resourceGroupName);
var t = WebRequest.Create(uriListMachines);
t.ContentType = "application/json";
t.Headers.Add("Authorization", "Bearer " + token);
var response = (HttpWebResponse)t.GetResponse();
string result = "";
using (var reader = new StreamReader(response.GetResponseStream()))
{
result = reader.ReadToEnd();
}
//Original Attempt:
//var credential = new TokenCloudCredentials(ConfigurationManager.AppSettings["subscriptionId"], token);
//using (var client = CloudContext.Clients.CreateComputeManagementClient(credential))
//{
// var images = client.VirtualMachineVMImages.List();
//}
}
private static string GetAuthorizationHeader()
{
AuthenticationResult result = null;
var context = new AuthenticationContext("https://login.windows.net/" + ConfigurationManager.AppSettings["tenantId"]);
string clientId = ConfigurationManager.AppSettings["clientId"];
string clientSecret = ConfigurationManager.AppSettings["clientSecret"];
ClientCredential clientCred = new ClientCredential(clientId, clientSecret);
var thread = new Thread(() =>
{
result = context.AcquireToken(
"https://management.core.windows.net/",
clientCred);
});
thread.SetApartmentState(ApartmentState.STA);
thread.Name = "AquireTokenThread";
thread.Start();
thread.Join();
if (result == null)
{
throw new InvalidOperationException("Failed to obtain the JWT token");
}
string token = result.AccessToken;
return token;
}
}
EDITAR EDITAR: descubrí mi colgado. Los recursos creados en el portal OLD obtendrán su propio grupo de recursos distinto.
Por lo que puedo decir, no puede agregar un recurso hecho en el antiguo grupo de recursos existente del portal (boooo). Los recursos creados en el nuevo portal podrán asignar el recurso a un grupo existente (también conocido como uno que da acceso a un rol a mi aplicación AD).
¡Esto es un desastre! Pero al menos sé lo que está pasando ahora.