Cursos Asterisk 2011

jueves, 10 de marzo de 2011 1 comentario

Hola, paso a dejar un lindo chivo aviso sobre cursos de Asterisk que están armando un grupo de gente conocida y amiga, en su versión 2011:

Bitsense, empresa dedicada a la implementación de soluciones telefónicas, dará comienzo a su curso de capacitación de Telefonía IP denominado BiaC (Bitsense Initial Asterisk Course) edición 2011, el mismo es el primer curso en la Argentina dictado por dos instructores certificados dCAP (Digium-certified Asterisk Professional) junto con el apoyo de certificados Cisco y Juniper. Este curso está orientado a brindarle las herramientas y conocimientos necesarios para implementar una infreastructura de Telefonía IP basado en Asterisk desde su inicio.

Para solicitar mas informacion envienos un mail a capacitacion@bitsense.com.ar y un representante se comunicará con usted o llamenos al telefono 5353.9858 (opción 2).

Le informamos también que referenciando esta publicación (si, ¡este blog!) usted accederá a un descuento especial.

http://www.bitsense.com.ar/cursos/biac/

Saludos

Categories: codear, misceláneos Tags:

Estableciendo conexiones HTTPS «bien seguras» en Python

sábado, 19 de febrero de 2011 2 comentarios

Hace unos días que tenía pendiente colgar esto acá, ya que a alguien en PyAr le fue útil.

HTTPS es la manera de establecer conexiones HTTP pero seguras, en el sentido de que previo al diálogo HTTP estándar pero luego de establecerse la conexión TCP contra el servidor, se negocia entre los participantes una conexión/sesión «especial» entre ambos.  Allí se intercambian certificados con el fin de autenticar contra quién se «está hablando», para luego, si hubo éxito en la dicha comprobación, encriptar (o no) todo lo que va para el otro lado, tanto del Servidor al Cliente (generalmente un navegador), como del Cliente al Servidor.

Todo eso forma parte de SSL 3.0 (hoy TLS 1.0), y si bien se puede utilizar para cualquier conexión TCP (SMTP, IMAP, etc., lo pueden usar también), su uso más común se da cuando uno entra a su casilla de Webmail o su cuenta del Banco desde el navegador;  lo que sucede allí es que nuestro navegador autentica al Servidor, y si todo va bien nos muestra el famoso «candadito» e informa que la sesión «es segura». Ahora bien, en esos casos, el Banco o Webmail no nos autentica a nosotros como Cliente y deja que cualquiera se conecte a su página, ya que eso requiere varios pasos más (sería realmente engorroso que sea obligatorio).

Sin embargo, en nuestra vida de programadores nos solemos encontrar con necesidades del entorno que nos obliguen a esta situación un tanto extrema y bastante más segura: que tanto el Cliente que desarrollamos autentique al Servidor como que el Servidor autentique al Cliente, amén de que la conexión muy probablemente deberá estar encriptada. Esto nos permitirá asegurarnos que los Clientes (software) que se conecten a nuestro Servidor sean únicamente quienes queremos que sean (o casi).

Python, dentro del módulo httplib nos provee de la clase HTTPSConnection, que maneja y nos abstrae en varias de estas cuestiones de SSL/TLS y nos deja trabajar a nivel HTTP (una capa más arriba). Lo que hay que observar bien (y que recién en la versión 2.7 de la documentación apareció en rojo), es que esta clase aún cuando uno le puede pasar como parámetro los paths a certificados, en realidad no hace ninguna comprobación de validez del certificado que el Servidor exporta. Con lo cual, hay un potencial problema: que nuestro cliente mande los datos a cualquier lado menos a nuestro Servidor de confianza.

¿Y cómo se fuerza a que nuestro programa Cliente chequee el certificado del Servidor? Armé esta clase que extiende sólo lo necesario a HTTPSConnection, que funciona en Python 2.6.x y que me permite hacer eso.

Le agregué un ejemplo en la llamada a __main__ para mostrar cómo se usa:

#!/usr/bin/env python
#-*- coding: utf-8 -*-
 
import socket
import ssl
import httplib
 
class HTTPSClientAuthConnection(httplib.HTTPSConnection):
    """ Class to make a HTTPS connection, with support for full client-based
        SSL Authentication.
    """
 
    def __init__(self, host, port, key_file, cert_file, ca_file, timeout=None):
        httplib.HTTPSConnection.__init__(self, host, key_file=key_file,
                                                   cert_file=cert_file)
        self.key_file = key_file
        self.cert_file = cert_file
        self.ca_file = ca_file
        self.timeout = timeout
 
    def connect(self):
        """ Connect to a host on a given (SSL) port.
            If ca_file is pointing somewhere, use it to check Server Certificate.
 
            Redefined/copied and extended from httplib.py:1105 (Python 2.6.x).
            This is needed to pass cert_reqs=ssl.CERT_REQUIRED as parameter
            to ssl.wrap_socket(), which forces SSL to check server certificate
            against our client certificate.
        """
        sock = socket.create_connection((self.host, self.port), self.timeout)
        if self._tunnel_host:
            self.sock = sock
            self._tunnel()
        # If there's no CA File, don't force Server Certificate Check
        if self.ca_file:
            self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file,
                        ca_certs=self.ca_file, cert_reqs=ssl.CERT_REQUIRED)
        else:
            self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file,
                                              cert_reqs=ssl.CERT_NONE)
 
if __name__ == '__main__':
    # Little test-case of our class
    import sys
    if len(sys.argv) != 6:
        print 'usage: ./https_auth_handler.py host port key_file cert_file ca_file'
        sys.exit(1)
    else:
        host, port, key_file, cert_file, ca_file = sys.argv[1:]
    conn = HTTPSClientAuthConnection(host, port, key_file=key_file,
                                           cert_file=cert_file, ca_file=ca_file)
    conn.request('GET', '/')
    response = conn.getresponse()
    print response.status, response.reason
    data = response.read()
    print data
    conn.close()

En cuanto a la generación de las claves de Cliente, Servidor y CA hay unos cuantos artículos y es relativamente sencillo una vez que se entiende qué se está haciendo. Por otra parte que en estos casos es muy común que el Servidor exija que el Cliente si o sí envíe su certificado o sino la conexión se deberá caer; esto en el caso del Servidor Apache está bien documentado.

Entiendo que en Python 3.2 esto está resuelto en la misma API standard de Python (en su momento abrí un ticket similar para usar esto con urllib2, que incluye cosas importantes como el manejo de cookies, por ejemplo), y comentaron eso.

Según me dijeron en PyAr, es casi seguro que este ejemplo no funcione en Python 2.7, así que en un futuro no muy lejano espero poder adaptar este código a dicha versión y seguramente lo estaré subiendo en esta página.

Saludos

Categories: codear, programación, python, ubuntu-ar Tags:

Virtualizando sólo una partición de una máquina física

viernes, 14 de enero de 2011 10 comentarios

Hace poquito un amigo me contó que estuvo leyendo el post anterior de Consolidación y «Shrinking» de discos físicos para pasarlos a una máquina virtual, pero tenía un pequeño obstáculo relacionado con el espacio en disco necesario, que más o menos era así:

Quería consolidar un disco real de 80 GB que tiene XP instalado en su C:, pero en total el disco tiene 4 particiones (primarias). Sólo me interesaba el disco C:, con lo que ahorraba espacio en el proceso ya que la partición del C: sólo ocupa 25 GB.

Entonces hice la copia con «dd if=/dev/sdb1 of=imagen.raw». Como uso VirtualBox, con un comando lo convertí de .raw a .vdi. Pero no logré bootear.

Hice varias pruebas, siempre con VirtualBox y no lo logré. Supongo que es porque no se copió el MBR. En cambio, cuando copié el disco completo, booteó sin problemas.

La pregunta es: ¿Cómo debería haber hecho para trabajar solo con esa partición y de esa forma evitar trabajar con los 80GB?

Bueno, el problema era que, efectivamente, al hacer el dd sobre /dev/sdb1 sólo se copian los bytes dentro de la partición y no el MBR+Bootloader (la vieja «pista 0» del disco). Para resolver el problema habría que copiar los bytes de la pista 0 más los bytes de la partición en cuestión, siguiendo estos pasos:

Ejecutar el comando parted sobre /dev/sdb (en mi caso, voy a usar /dev/sda como ejemplo):

marcelo@jupiter:~$ sudo parted /dev/sda u s print
Modelo: ATA WDC WD3200BEVT-0 (scsi)
Disco /dev/sda: 625142448s
Tamaño de sector (lógico/físico): 512B/512B
Tabla de particiones. msdos
 
Numero  Inicio     Fin         Tamaño      Tipo      Sistema de ficheros  Banderas
 1      63s        32001479s   32001417s   primary   ext4                 arranque
 2      32001541s  94494329s   62492789s   extended
 5      32001543s  94494329s   62492787s   logical   ext4
 3      94494330s  98494514s   4000185s    primary   linux-swap(v1)
 4      98494515s  625137344s  526642830s  primary   ext4

El parámetro «print» le dice a parted que me imprima la tabla de particiones, y «u s» que imprima los tamaños en sectores (que en los discos <=1.0TB son siempre de 512 bytes, sino mismo parted lo dice en la salida, ver este post para más detalles).

De esta manera se tienen todos los sectores a copiar de /dev/sda directamente; en mi caso, 63 sectores de la pista 0, que contiene al MBR, más los de la primera partición, 32001417, total: 32001480 sectores.

Luego el dd que sólo copia los bytes que nos interesan (Pista 0 + Partición «C:») es fácil:

sudo dd if=/dev/sda of=imagen.raw bs=512 count=32001480

Y listo. Eso sí, luego hay que particionar la imagen con Parted, Fdisk, GParted o el software que se quiera utilizar a tal efecto. Es necesario hacerlo porque el MBR copiado va a reportar las 4 particiones que se tenían previamente en el disco y ahora sólo se va a disponer de una sola.

Asumo que este procedimiento también se puede aplicar para copiar una partición que no sea la primera, usando las opciones «skip» y «append» del comando dd; por ejemplo, si quisiera hacer un disco de sólo mi partición 5, tendría que:

  1. Copiar la pista 0 en un archivo con algo así como «dd if=/dev/sda of=imagen.raw bs=512 count=63».
  2. Ejecutar otro dd con la partición a copiar, salteando («skipeando») N sectores con la opción «skip» y especificando la opción «append» para agregar al archivo anterior de salida: «dd if=/dev/sda of=imagen.raw bs=512 count=62492787 skip=32001543 append».

Lógicamente esto último no lo probé, acepto comentarios de si funcionó o no 😉

Espero que a alguien le sirva…

¡Saludos!

Categories: codear, linux, sysadmin, ubuntu-ar Tags:

Comparativas de Virtualización KVM

miércoles, 5 de enero de 2011 1 comentario

Ultimamente por diferentes cuestiones personales estoy bastante desconectado de la lectura de noticias, blogs y demás. Sin embargo, me pareció útil dejar por acá dos comparativas sobre KVM de Phoronix.com, que si bien en algunos lados me encontré que se quejan de la «calidad» de su suite de benchmarks para software libre/abierto, por el otro, ¡hey! ¡al menos se preocupan en hacerlo! 🙂

Linux KVM vs. VirtualBox 4.0 Virtualization Benchmarks
Este es un test de performance entre KVM y Virtualbox. En resumen, y con los parámetros por defecto en cuanto a I/O, VBox gana, pero parece que es debido a que no hace los fsync del guest en el host y termina utilizando su caché; muy probablemente este comportamiento es configurable (¿ver acá?), pero así y todo ¡es bueno saberlo!. De todas maneras, de alguna manera es peligroso para un entorno de servidores ya que hay riesgo de pérdida de datos, pero por ejemplo, para mi notebook (target primario adonde Virtualbox siempre estuvo orientado) está bien.

Por el otro lado, cuando hay que usar la CPU, KVM «le pasa el trapo» a VBox. Hay un test de I/O de red (TCP) que a KVM le dio mal, tan mal, que seguro es debido a que los salames testers no habilitaron VirtIO en los guests KVM.

Multi-Core Scaling In A KVM Virtualized Environment
Este test trata de dilucidar si es mito o no que el Hyperthreading (las VCPUs) de los microprocesadores Intel Xeon basados en Nehalem hacen más lentas o más rápidas las VMs que corren sobre KVM. Esto es algo que pregunté personalmente en el IRC de KVM (#kvm en Freenode, dicho sea de paso), y me sugirieron lo mismo que dió en los tests: hay veces en donde las VMs aprovechan todas las CPUs virtuales (VCPUs) y otras en que no, con lo cual hay que probar en cada caso en particular y dejar la configuración que nos dé mejores resultados.

Interesante de leer y experimentar.

Saludos

Categories: codear, linux, sysadmin, ubuntu-ar Tags:

Navegador simple con wxPython + Webkit/GTK

sábado, 9 de octubre de 2010 7 comentarios

Hace algunos posts (¡casi un año ya!) escribí sobre una manera fácil y rápida de tener un componente «navegador web» en Python sobre Linux/BSD, gracias a PyGTK y WebkitGTK, llamado lógicamente, pyWebkitGTK. En pocas líneas de código uno puede disponer de un navegador potente y completo en un panel de su aplicación basada en PyGTK, ideal para integrar aún más la cada omnipresente Web.

Las vueltas de la vida y las ganas de experimentar y aprender te llevan a probar otros frameworks/librerías, como lo es wxPython; tanto es así que de vez en cuando tengo el placer de dar alguna charla al respecto [1], y una de las debilidades que le usualmente le encontraba es la falta de un componente «browser web» nativo y soportado en todas las plataformas (wxPython sólo incluye IE embebible como ActiveX en Windows).

En búsqueda de alternativas existe wxWebKit, pero al proyecto le faltan terminar algunas cosas para tener lista su versión «1.0», y si bien wxWebConnect funciona, no da soporte para wxPython, sólo wxWidgets desde C++. Eso nos deja con que en Linux/BSD no tenemos componente que nos dé esta posibildad, pero… si wxPython en estas plataformas utiliza GTK por debajo, ¿no podríamos usar pyWebkitGTK como componente para embeberlo en nuestra aplicación Python?

La respuesta por suerte es afirmativa, y en una rápida búsqueda en la Wiki de wxPython encontré un ejemplo de cómo hacerlo. Si bien podría copiar y pegar la receta, me gustaría «aggiornarla» un poquito, al menos traduciendo y explicando un poco más los comentarios.

Primero vamos a mostrar cómo se vería el módulo que incluye un widget HtmlPanel, wxwebkitgtk.py:

#!/usr/bin/env python
# coding:utf-8
 
"""
    wxWebkitGTK - Componente wxPython que embebe un navegador
                   utiliza la biblioteca Webkit GTK desde Python (PyWebkitGTK).
 
    Marcelo Fidel Fernández - http://www.marcelofernandez.info
    Basado en: http://wiki.wxpython.org/wxGTKWebKit
"""
import os
import wx
import gobject
gobject.threads_init()
import gtk, gtk.gdk
import webkit
 
class HtmlPanel(wx.Panel):
 
    def __init__(self, *args, **kwargs):
        wx.Panel.__init__(self, *args, **kwargs)
        # Aquí es donde se hace la "magia" de embeber webkit en wxGTK.
        whdl = self.GetHandle()
        window = gtk.gdk.window_lookup(whdl)
        # Debemos mantener la referencia a "pizza", sino obtenemos un segfault.
        self.pizza = window.get_user_data()
        # Obtengo el padre de la clase GtkPizza, un gtk.ScrolledWindow
        self.scrolled_window = self.pizza.parent
        # Saco el objeto GtkPizza para poner un WebView en su lugar
        self.scrolled_window.remove(self.pizza)
        self.webview = webkit.WebView()
        self.scrolled_window.add(self.webview)
        self.scrolled_window.show_all()

La «magia» consiste en que, sabiendo que pyWebkitGTK necesita un componente ScrolledWindow GTK como padre para funcionar correctamente, se utiliza la biblioteca PyGTK para buscar el ScrolledWindow GTK donde está embebido el wx.Panel de la clase (su «abuelo»), y reemplazar el hijo GTKPizza (un componente inventado por wxWidgets para funcionar) por el WebView de Webkit.

Aquí hay un ejemplo de cómo se puede utilizar este panel como widget de wxPython completo e independiente, copiando la funcionalidad básica del post de PyWebkitGTK, el archivo wxwebkitgtk_demo.py:

#!/usr/bin/env python
# coding: utf-8
 
"""
    wxSimpleBrowser - Navegador muy muy simple de internet, sólo de ejemplo,
                      que utiliza la biblioteca Webkit GTK desde wxPython.
 
    Marcelo Fidel Fernández - http://www.marcelofernandez.info
    Licencia: BSD. Disponible en: http://www.freebsd.org/copyright/license.html
"""
 
import sys
import wx
from wxwebkitgtk import HtmlPanel
 
DEFAULT_URL = 'http://www.python.org'
 
class wxSimpleBrowser(wx.Frame):
 
    def __init__(self):
        wx.Frame.__init__(self, None)
        self.TxtUrl = wx.TextCtrl(self, wx.ID_ANY, style=wx.TE_PROCESS_ENTER)
        self.TxtUrl.Bind(wx.EVT_TEXT_ENTER, self.OnTxtURL)
        self.Box = wx.BoxSizer(wx.VERTICAL)
        self.Box.Add(self.TxtUrl, proportion=0, flag=wx.EXPAND)
        self.SetSizer(self.Box)
        self.SetSize((800,600))
        self.Show()
        # Necesitamos tener mostrado el componente padre del Panel para que funcione,
        # por eso mostramos primero el Frame y después creamos el HtmlPanel
        self.HtmlPanel = HtmlPanel(self)
        self.Box.Add(self.HtmlPanel, proportion=1, flag=wx.EXPAND)
        self.SendSizeEvent() # Para acomodar el panel al tamaño del frame
 
    def OnTxtURL(self, event):
        self.Open(self.TxtUrl.GetValue())
 
    def Open(self, url):
        # Podemos acceder a todos los métods del objeto WebView
        # http://webkitgtk.org/reference/webkitgtk-webkitwebview.html
        self.HtmlPanel.webview.load_uri(url)
        self.TxtUrl.SetValue(url)
        self.SetTitle('wxSimpleBrowser - %s' % url)
 
if __name__ == '__main__':
    if len(sys.argv) &gt; 1:
        url = sys.argv[1]
    else:
        url = DEFAULT_URL
    app = wx.App()
    browser = wxSimpleBrowser()
    browser.Open(url)
    app.MainLoop()

Creo que para la enorme funcionalidad que nos brinda el proceso de ponerlo en práctica es bastante simple, y aunque depende de PyGTK, ésta biblioteca hoy está disponible «de fábrica» en cualquier distribución moderna de GNU/Linux.

De aquí en más es ser muy sencillo dejar al lector el armado de un widget para wxPython que en Windows muestre el componente navegador de IE y en Linux un navegador Webkit.

[1] ¡La semana que viene voy a estar en la PyCon Argentina 2010 dando una charla de Introducción a wxPython! 😀

¡Saludos!

Categories: codear, linux, programación, python, ubuntu-ar Tags: