Category Archives: Azure

Exportar base de datos SQL SERVER a un BLOB en Azure como backup

Decir que Azure, la plataforma Cloud de Microsoft, es una de las más potentes del mercado pese a su corto tiempo de vida no es algo nuevo aunque, precisamente por su juventud, nos encontramos con algunas carencias que hacen algo más complicado las gestiones típicas de un sistema en producción.

Una de estas carencias es la posibilidad de automatizar backups (copias de seguridad) de nuestras bases de datos SQL SERVER algo que necesitamos tener cuando nuestro proyecto pasa el estado de desarrollo.

 

La única posibilidad que nos ofrece Azure en este momento (25/06/2013) es exportar/importar nuestras bases de datos a un blob desde el panel de control a petición pero no podemos programar esta tarea para que se ejecute periódicamente.

 

Esta opción genera en uno de nuestros containers un blob con extensión .bacpac con la copia de seguridad de la base de datos escogida para poder importarla en cualquier momento.

La pregunta es, ¿cómo podemos hacer esto automáticamente? La respuesta, con una aplicación que llame periódicamente a la misma API REST que usa Azure para estas tareas.

 

Azure Sql Server API REST

Azure Sql Server expone un API REST con algunas tareas básicas que podemos invocar (con las debidas credenciales, claro está) para exportar o importar nuestras bases de datos contra Azure Storage.

Cada una de las regiones de Azure Sql Server tiene su propia url del servicio por lo que deberás asegurarte de usar la url correcta en función de en que región se encuentre tu base de datos:

 

 

DataCenter Endpoint
North Central US https://ch1prod-dacsvc.azure.com/DACWebService.svc/
South Central US https://sn1prod-dacsvc.azure.com/DACWebService.svc/
North Europe https://db3prod-dacsvc.azure.com/DACWebService.svc/
West Europe https://am1prod-dacsvc.azure.com/DACWebService.svc/
East Asia https://hkgprod-dacsvc.azure.com/DACWebService.svc/
Southeast Asia https://sg1prod-dacsvc.azure.com/DACWebService.svc/
East US https://bl2prod-dacsvc.azure.com/DACWebService.svc/
West US https://by1prod-dacsvc.azure.com/DACWebService.svc/

 

Las dos tareas expuestas por este servicio son “Export” e “Import” (para exportar e importar respectivamente) por lo que, por ejemplo, para solicitar una exportación de una base de datos alojada en el Norte de Europa deberíamos hacer un POST contra la url: https://db3prod-dacsvc.azure.com/DACWebService.svc/Export

 

Solicitando Exportación desde código

Para automatizar el proceso de exportación podemos programar un pequeño Worker Role de Azure, un servicio de Windows que se ejecute en uno de nuestros servidores locales o incluso que lo implemente nuestra propia web de administración. En mi caso dispongo de un Worker Role propio con varias tareas de mantenimiento que se ejecutan cada cierto tiempo por lo que me fue muy fácil incluir una nueva tarea para hacer este backup.

Para hacer esta exportación, como hemos comentados antes, basta con hacer un POST contra la [url del servicio] + “/Export” incluyendo en el cuerpo de la petición un xml con los datos necesarios para la tarea.

 

Este xml que tenemos que postear tiene el siguiente formato:

[code language=”xml”]

<ExportInput
xmlns="http://schemas.datacontract.org/2004/07/Microsoft.SqlServer.Management.Dac.ServiceTypes"
xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<BlobCredentials
i:type="BlobStorageAccessKeyCredentials">
<Uri>[URL del Blob a crear]</Uri>
<StorageAccessKey>[Clave de acceso del Azure Storage]</StorageAccessKey>
</BlobCredentials>
<ConnectionInfo>
<DatabaseName>[Nombre de la base de datos a exportar]</DatabaseName>
<Password>[Password del usuario de la base de datos]</Password>
<ServerName>[Nombre del servidor en el que se encuentra la base de datos]</ServerName>
<UserName>[Usuario de acceso a la base de datos]</UserName>
</ConnectionInfo>
</ExportInput>

[/code]

Los parámetros que debes rellenar son:

  • [URL del Blob a crear]
    • Url completa del blob que vas a crear con “.bacpac” al final.
      • Ej: https://mistorageenazure.blob.core.windows.net/bak/backup-2013-06-25_09-49.bacpac
  • [Clave de acceso del Azure Storage]
    • La “Primary Access Key” de nuestro Storage en Azure. La podemos encontrar en el panel de administración de Azure > Storage > [el storage al que queremos acceder] > Manage Access Keys
  • [Nombre del servidor en el que se encuentra la base de datos]
    • Nombre completo del servidor de SQL SERVER en el que se encuentra la base de datos a exportar (debe terminar en “database.windows.net”)
      • Ej: server.database.windows.net
  • Datos de la BD
    • Nombre, usuario y contraseña de la base de datos a exportar

 

Con este xml generado ya solo necesitamos hacer un POST contra la url del servicio para solicitar la tarea de exportación.

Este servicio nos devuelve un GUID para la posterior comprobación del estado de la tarea. Podemos guardarlo si queremos para poder saber si ha terminado con éxito o no.

Aquí un ejemplo con el código completo:

[code language=”csharp”]
private Guid RequestExport(string databaseName, string containerUrl, string storageAccessKey, string blobName)
{
// Método que devolvería la URL del Servicio en función de la Región. Yo le paso un tipo enum propio por comodidad
var managementUrl = GetAzureManagementUrlByRegion(AzureRegions.NorthEurope);

var request = WebRequest.Create(managementUrl + "/Export");
request.Method = "POST";

var dataStream = request.GetRequestStream();
// Método que genera el XML que se le pasa como Body con el formato comentado anteriormente
var body = GetExportToBlobBodyRequest(blobUrl, storageAccessKey, databaseName);
var utf8 = new UTF8Encoding();
var buffer = utf8.GetBytes(body);
dataStream.Write(buffer, 0, buffer.Length);

dataStream.Close();
request.ContentType = "application/xml";

// La respuesta HTTP contiene el GUID que representa la tarea serializado como XML
using (var response = request.GetResponse())
{
var encoding = Encoding.GetEncoding(1252);
using (var responseStream = new StreamReader(response.GetResponseStream(), encoding))
{
using (var reader = XmlDictionaryReader.CreateTextReader(responseStream.BaseStream, new XmlDictionaryReaderQuotas()))
{
var serializer = new DataContractSerializer(typeof(Guid));
return (Guid)serializer.ReadObject(reader, true);
}
}
}
}
[/code]

¡Listo! Nuestra tarea de exportación ya se está lanzando y, si todo funciona como debe, en breve se creará un nuevo blob con el contenido de nuestra base de datos para poder importarlo en caso de catástrofe o para replicarlo en otra base de datos distinta para hacer pruebas.

Comprobando el estado de la tarea

Si queremos saber si todo ha ido bien o ha fallado algo podemos hacer GET a otro método del API REST de Azure llamado “Status” indicando el GUID obtenido en la petición de la tarea. Para ello basta con hacer GET de la siguiente url:

[Url del servicio API REST de tu Región]/Status?servername=[servidor de base de datos completo]&username=[usuario de la base de datos]&password=[password de la base de datos]&reqId=[GUID de la tarea]

 

Esta url nos debe devolver un XML con información del estado de la tarea.

 

¡Hecho! Con un simple cliente HTTP podemos hacer exportaciones e importaciones periódicas y automáticas de nuestra base de datos y así protegernos ante cualquier problema que podamos tener.

Como siempre para cualquier duda ya sabéis dónde podéis encontrarme.

 

¡Un saludo y nos vemos Compilando!

Configurar HTTPS en un WebRole de Azure

 

Parece mentira pero algo tan sencillo como permitir el acceso por HTTPS con un dominio personalizado en Azure es algo que no es trivial.

Para empezar, a día de hoy 2 de Abril del 2013, no puedes usar certificados de seguridad en un Web Site de Azure si no estás usando su dominio “azurewebsites.net” por lo que nos hemos visto obligados a mover la web a un WebRole el cual tiene menos opciones de deployment y es más complejo que el Web Site solo para poder poner habilitar el acceso a https://www.midominio.com… lamentable.

Además el proceso completo para poder pedir, instalar y configurar el certificado de seguridad no es nada sencillo así que, para todos los que se vayan a pelear con este tema hasta que lo mejoren, les dedico este artículo.

Crear la solicitud del Certificado

Para poder configurar nuestro certificado de seguridad en Azure necesitamos conocer la clave privada con la que se generó la petición del certificado. Por este motivo no podemos crear la solicitud del certificado desde el IIS ya que no controlamos con qué clave se firma.

El mejor método de hacer esta solicitud es desde el OpenSSL siguiendo estos pasos:

  1. Descargar e instalar OpenSsl para Windows: http://slproweb.com/products/Win32OpenSSL.html
  2. Abrir una consola (cmd.exe) y establecer la variable de entorno para el fichero de configuración del OpenSSL
    set OPENSSL_CONF=c:\[Ruta a la carpeta donde has instalado el OpenSSL]\bin\openssl.cfg
  3. Crear la solicitud de certificado y creación de la clave privada:
    openssl req -nodes -newkey rsa:2048 -keyout private.key -out request.csr
    

    Asegúrate de que tienes permisos de escritura en la carpeta en la que estás depositando el .key y el .csr.
    Al lanzar esta llamada al openssl se te pedirá que rellenes una serie de datos para la solicitud del certificado. Ves introduciendo los datos y pulsa ENTER.
    También se pedirá una contraseña. Anótala ya que la usaremos más adelante.
    IMPORTANTE en “Common Name (e.g. server FQDN or YOUR name) []:” pon el nombre de dominio que quieres proteger (ej: www.compilando.es)

Con el “.csr” creado ya podemos pedir a nuestro proveedor de SSL de confianza que nos genere un certificado de seguridad instalable en nuestro servidor.

 

Exportar el fichero .PFX

Para poder configurar el Web Role en Azure necesitamos obtener el fichero que contiene el certificado de seguridad y la clave privada que generó la petición por eso debemos obtener este fichero .pfx mediante otra llamada al OpenSSL usando el “.crt” que nos ha enviado el proveedor de SSL junto con el “.key” que creamos en el paso anterior.

Supongamos que nuestro proveedor nos envía el fichero de certficado llamado “compilando.crt”

Para ello seguimos los siguientes pasos:

  • Abrimos el certificado que nos envía el proveedor, si no está en formato pkcs12 tenemos que convertirlo antes. Para ello abrimos una consola (cmd.exe) y ejecutamos el siguiente comando de openssl (ejemplo de conversión desde pkcs7):
    openssl pkcs7 -print_certs -in compilando.crt -out compilando_pkcs12.crt
  • Con el certificado ya en formato pkcs12 exportamos el pfx:
    openssl pkcs12 -export -in compilando.crt -inkey private.key -out azure.pfx
  • En la consola nos solicitarán la contraseña que pusimos en el primer paso cuando creamos “private.key” (por eso dije de anotarla ;-))

Con esto obtenemos un fichero llamado “azure.pfx” que ya podemos usar para configurar nuestro WebRole.

 

Configurar HTTP en Azure

Con el certificado correctamente generado y exportado ya podemos configurar nuestro WebRole para disponer de un endpoint funcionando con HTTPS.

Lo primero que debemos hacer es subir el .PFX que acabamos de generar a Azure. 

Para ello nos conectamos al panel de administración de Azure (https://manage.windowsazure.com/) y hacemos lo siguiente:

  • Cloud Services > [Web Role] > Certificates > Upload
  • Escogemos el fichero .PFX que acabamos de crear y escribimos la contraseña (la misma que pusimos al crear el .key y al exportar el .pfx)

 

  • Una vez subido veremos el certificado en el listado y copiamos el GUID de la columna “Thumbprint”

Ahora lo que nos queda es configurar el EndPoint en el Visual Studio. Para ello vamos a la solución en la que tenemos nuestro proyecto de Azure y editamos la definición del Servicio (ServiceDefinition.csdef) y los ficheros de configuracón del Servicio (ServiceConfiguration.XXXX.cscfg) tal y como se ve en los ejemplos que hay a continuación:

ServiceDefinition.csdef

<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="Compilando.WebRole" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition" schemaVersion="2012-10.1.8">
  <WebRole name="Compilando.WebRole" vmsize="Small">
<Sites> <Site name="Web"> <Bindings> <Binding name="Endpoint1" endpointName="Endpoint1" /> <Binding name="HttpsIn" endpointName="HttpsIn" /> </Bindings> </Site> </Sites> <Endpoints> <InputEndpoint name="Endpoint1" protocol="http" port="80" /> <InputEndpoint name="HttpsIn" protocol="https" port="443" certificate="www.compilando.es" /> </Endpoints> <Certificates> <Certificate name="www.compilando.es" storeLocation="LocalMachine" storeName="CA" /> </Certificates> </WebRole> </ServiceDefinition>

Como veis, se crea un nuevo EndPoint con el protocolo https apuntando al puerto 443 y usando el nuevo certificado que hemos subido.

ServiceConfiguration.Cloud.cscfg

<?xml version="1.0" encoding="utf-8"?>
<ServiceConfiguration serviceName="Predeploy.Terminis.Web.Azure" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration" osFamily="3" osVersion="*" schemaVersion="2012-10.1.8">
  <Role name="Compilando.WebRole">
<Instances count="1" /> <Certificates> <Certificate name="www.compilando.es" thumbprint="F319BC716E1B17FC8824B9325059EC503B6609AE" thumbprintAlgorithm="sha1" /> </Certificates> </Role> </ServiceConfiguration>

En este caso, en la configuración Cloud de nuestra web “Compilando.WebRole” indicamos que el certificado llamado “www.compilando.es” tiene el Thumbprint que hemos copiado del panel de control de Azure. Con esto ya podríamos publicar el WebRole (recordando subir los cscfg y csdef actualizados) para que use el nuevo certificado y ya podríamos visitar nuestra web https://www.compilando.es sin problema alguno :)

 

¡Nos vemos Compilando!