Cómo eliminar registros de la tabla de trazas en Azure

Dentro de las buenas prácticas a la hora de implementar un cloud service en Azure, ya se trate de un webrole o un worker role, es la de configurar la transferencia de datos de diagnóstico a Azure Storage para poder ver cómo se está comportando nuestro servicio. En el artículo “Enabling Diagnostics in Windows Azure” se detalla paso a paso cómo habilitar cada uno de los tipos de diagnóstico.

Una vez configuradas las fuentes de datos de diagnóstico –IIS logs, Windows Events logs, etc.-, los datos son transferidos a Azure Storage en ciclos de X minutos según hayamos configurado. Uno de estas fuentes de datos son los Windows Azure logs, conteniendo los mensajes enviados a través de operaciones de traza (“Trace.WriteInformation”, etc.), y yendo a parar a la tabla “WADLogsTable” en Azure Storage.

WADLogsTable

Esta información es una de nuestras primeras herramientas de diagnóstico en la que podemos escribir información de traza. Personalmente también añado un listener para tener la misma información en el Event Viewer de mi aplicación ya que así no tengo que esperar al mínimo de 1 minuto de transferencia a Storage, accediendo al mismo a través de RDP.

Y si bien en el caso del visor de sucesos podemos indicar diversos métodos de eliminación automática de sucesos –por fecha, por tamaño en Mb, etc.-, no existe una opción similar para eliminar esta información de forma automática de la tabla WADLogsTable de Azure Storage. Es cierto que el almacenamiento de Azure Storage es muy económico, pero cuando vas acumulando información de traza, es muy probable que los mensajes que fueron generados hace varios meses o años atrás deje de ser relevante, y haya que realizar algún mantenimiento en la misma sin perder los últimos datos relevantes (vamos, sin eliminar la tabla completamente).

De este modo, una de las opciones que tenemos es la de ir eliminando registros de la tabla a través de algún filtro, algo que podemos hacer programáticamente o a través de uno de los comandos Powershell disponibles en el conjunto de Windows Azure Management Cmdlets.

Instalando Windows Azure Management Cmdlets

InstallWPILa forma más sencilla de instalar estos comandos de PowerShell es a través de Web Platform Installer. Siguiendo este enlace (http://go.microsoft.com/?linkid=9811175&clcid=0x409) se iniciará la instalación de paquete en cuestión.

Si lo que deseas es automatizar la instalación de estos Cmdlets dentro de tu instancia de Windows Azure, puedes usar la herramienta de línea de comandos de Web Platform Installer con una línea de comandos como la siguiente (visita mi post anterior Configurando Web Platform Installer y WebDeploy en un Azure WebRole para ampliar información):

   1: ~dp0WebPICMD.exe /Install /Products:WindowsAzurePowerShell /AcceptEULA

Realizando mantenimiento de WADLogsTable

Una vez instalados los Cmdlets, abrimos la consola de Windows Azure PowerShell. Para ello, buscamos en el menú de inicio el acceso directo para iniciarla.

WAPowerShell

Una vez iniciada la consola de comandos, procedemos a buscar la ayuda del Cmdlet para realizar mantenimiento de esta tabla, escribiendo “help Clear-WindowsAzureLog”:

PS C:> help clear-windowsazurelog

 

NAME

    Clear-WindowsAzureLog

 

SYNOPSIS

    Removes Windows Azure trace log data from a storage account.

 

SYNTAX

    Clear-WindowsAzureLog [-DeploymentId <String>] [-From <DateTime>] [-To <DateTime>] [-StorageAccountName <String>]

    [-StorageAccountKey <String>] [-UseDevelopmentStorage] [-StorageAccountCredentials

    <StorageCredentialsAccountAndKey>] [<CommonParameters>]

 

    Clear-WindowsAzureLog [-DeploymentId <String>] [-FromUtc <DateTime>] [-ToUtc <DateTime>] [-StorageAccountName

    <String>] [-StorageAccountKey <String>] [-UseDevelopmentStorage] [-StorageAccountCredentials

    <StorageCredentialsAccountAndKey>] [<CommonParameters>]

 

DESCRIPTION

    The Clear-WindowsAzureLog cmdlet clears trace log data exported by Windows Azure Diagnostics to the WADLogsTable

    of the specified storage account.A subset of the data available can be removed by specifying a period of time for

    which to clear data.

 

RELATED LINKS

    Get-WindowsAzureLog

    Set-WindowsAzureLog

 

REMARKS

    To see the examples, type: "get-help Clear-WindowsAzureLog -examples".

    For more information, type: "get-help Clear-WindowsAzureLog -detailed".

    For technical information, type: "get-help Clear-WindowsAzureLog -full".

    For online help, type: "get-help Clear-WindowsAzureLog -online"

De este modo, un ejemplo para eliminar todas las entradas anteriores al 20 de noviembre de 2012 en DevFabric sería algo así:

PS C:> Clear-WindowsAzureLog -ToUtc 2012-11-20T00:00:00 -UseDevelopmentStorage

47 record(s) were deleted in the 'WADLogsTable' table.

Como véis, muy simple. De hecho, una buena idea para automatizar esta tarea sería:

  1. Automatizar la instalación de los Cmdlets en el role con la herramienta de línea de comandos de WPI (ver apartado anterior)
  2. Crear una tarea programada en el role startup que llame al cmdlet de powershell para eliminar entradas anteriores a X días

Para no inventar nada nuevo respecto a la creación de tareas programadas, la mejor forma es utilizar el propio planificador de tareas del sistema dentro del mismo role. Sin embargo, para no alargar más esta entrada, lo veremos en el próximo “capítulo”.

Un saludo y Happy Coding!

Cómo desencriptar una password de RDP de Azure olvidada

password-decrypting-600x394¿Alguna vez te ha pasado que has olvidado la contraseña que pusiste al publicar tu servicio hospedado en Azure y ahora no te puedes conectar por RDP?

Actualmente, hay una solución muy sencilla –y recomendada-, que es volver a restablecer la contraseña a través del portal de Windows Azure, siguiendo los pasos siguientes:

  1. Acceder al portal de Windows Azure
  2. Ir al servicio hospedado e ir a la sección “Configurar”
  3. Hacer click en el botón “Remoto” de la barra de herramientas inferior
  4. Restablecer la contraseña introduciéndola en los campos solicitados, reconfigurando así las credenciales del usuario RDP.

ResetPassword

Esto cambiará el estado del role a “Actualizando” y al cabo de unos minutos ya podremos acceder con la nueva contraseña.

Si bien esta operación restablece correctamente los credenciales, a veces no nos conviene por un motivo u otro realizar este cambio. Así que aquí va el truco siguiente.

Desencriptar una contraseña RDP olvidada de Windows Azure

Para poder desencriptar la contraseña olvidada necesitamos:

  • Tener la cadena de texto de la contraseña encriptada
  • Tener instalado en el equipo local el certificado con la que fue encriptada

La contraseña encriptada se almacena en el archivo .cscfg con el que fue desplegado tu servicio, si bien éste puede ser distinto si alguien la ha modificado siguiendo el método anterior. Para asegurarnos de tener la última contraseña, puedes seguir los pasos siguientes:

  1. Acceder al portal anterior de Windows Azure a través de la URL https://windows.azure.com (te solicitará tus credenciales) y luego mostrará la versión anterior del portal en Silverlight
  2. Ir al servicio en cuestión y seleccionar el despliegue. En la parte derecha aparecerán las propiedades del mismo con los valores actuales
  3. Copiar al portapapeles el valor de la propiedad “Microsoft.WindowsAzure.Plugins.RemoteAccess.AccountEncryptedPassword”

PasswordEncripted

Ahora que tienes la contraseña, puedes usar el certificado almacenado en tu almacén de certificados local para desencriptarla, del mismo modo que hace el agente de RDP de Windows Azure para crear las credenciales en el role startup.

El código para ello sería la función siguiente:

   1: private static string DecryptPassword(string encryptedPassword)

   2: {

   3:     if (string.IsNullOrEmpty(encryptedPassword))

   4:     {

   5:         throw new ArgumentNullException("encryptedPassword");

   6:     }

   7:     SecureString secPassword;

   8:     try

   9:     {

  10:         var encryptedBytes = Convert.FromBase64String(encryptedPassword);

  11:         var envelope = new EnvelopedCms();

  12:         envelope.Decode(encryptedBytes);

  13:         var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);

  14:         store.Open(OpenFlags.ReadOnly);

  15:         envelope.Decrypt(store.Certificates);

  16:         char[] passwordChars = Encoding.UTF8.GetChars(envelope.ContentInfo.Content);

  17:         secPassword = new SecureString();

  18:         foreach (var character in passwordChars)

  19:         {

  20:             secPassword.AppendChar(character);

  21:         }

  22:         Array.Clear(envelope.ContentInfo.Content, 0, envelope.ContentInfo.Content.Length);

  23:         Array.Clear(passwordChars, 0, passwordChars.Length);

  24:         secPassword.MakeReadOnly();

  25:     }

  26:     catch (CryptographicException cex)

  27:     {

  28:         throw new SecurityException("Unable to decrypt password. Make sure that the cert used for encryption was uploaded to the Azure service", cex);

  29:     }

  30:     catch (FormatException fex)

  31:     {

  32:         throw new SecurityException("Encrypted password is not a valid base64 string", fex);

  33:     }

  34:  

  35:     return GetUnsecuredString(secPassword);

  36: }

  37:  

  38: private static string GetUnsecuredString(SecureString secureString)

  39: {

  40:     if (secureString == null)

  41:     {

  42:         throw new ArgumentNullException("secureString");

  43:     }

  44:  

  45:     IntPtr ptrUnsecureString = IntPtr.Zero;

  46:     try

  47:     {

  48:         ptrUnsecureString = Marshal.SecureStringToGlobalAllocUnicode(secureString);

  49:         return Marshal.PtrToStringUni(ptrUnsecureString);

  50:     }

  51:     finally

  52:     {

  53:         Marshal.ZeroFreeGlobalAllocUnicode(ptrUnsecureString);

  54:     }

  55: }

  56:  

Adjunto una solución con el código de ejemplo por si alguno le interesa.

Un saludo y happy coding!