Productividad Personal

Fórmula para la productividad personal.
Vía @elalkimista

TotalPlay llegó a Guadalajara

¡Finalmente "TotalPlay" llegó a Guadalajara!


ACTUALIZACIÓN: Antes de que se vayan y lean el resto de la nota, les pido que chequen una entrada posterior sobre Total play.

Es una gran noticia considerando que esto implica más competencia para las empresas que ya se encuentran proporcionando servicios "triple play" actualmente (¿verdad Megacable?) en la ciudad.

Ojalá que nosotros (los clientes) nos veamos beneficiados con un decremento en el precio de los servicios y el incremento en la calidad, actualmente Axtel me ha funcionado muy bien a comparación de los servicios brindados por Megacable/Telmex, no he tenido la necesidad de contratar con Telecable, pero he escuchado historias de terror similares a las de Megacable.

Hasta el momento ésto es lo que se puede encontrar en la página de TotalPlay, los paquetes:


La cobertura por el momento se reduce a tres zonas, que se detallan a continuación en:



Veremos en un futuro que comentarán los clientes, mientras tanto yo sí estoy considerando contrartarlos y cancelar los servicios de Megacable, que hasta el momento al igual que Telmex, no hacen mucho por mejorar sus velocidades/paquetes.

yubikey: Configuración y uso de infraestructura OTP

Introducción:

Las llaves de hardware o tokens, se utilizan para implementar niveles de autenticación de dos factores. Algo que sabes, el password como el primer factor, y algo que tienes que sería una llave Yubikey configurada con tu usuario.

El nivel de seguridad es igual de alto que el token RSA, a final de cuentas, al única diferencia práctica es que el token, te da un numero que hay que copiar, único y diferente sincronizado con la cuenta por medio de "algún algoritmo mágico" y la llave Yubikey, en vez de mostrarlo en pantalla, lo "escribe", por que al final la llave Yubikey es detectado como teclado y por eso es compatible con cualquier plataforma que reciba usb, windows, linux, mac... 

Que es lo que escribe el Yubikey, depende de una serie de parametros, una llave aes y eso es precisamente lo que vamos trataré de documentar aquí.

Yubikey 

Las llaves yubikey, son llaves que general One Time Password u OTP por sus siglas en ingles, cada vez que uno activa la llave, esta genera un número de identificación diferente. Es exactamente igual a cuando se usa un "token" bancario. Se hace algo para generar un resultado, lo normal es picar un boton para que nos de una secuencia de números que más vale que copiemos. Yubico ofrece el mecanismo para implementar toda la cadena de autenticación que es como sigue:



Se tiene un cliente que hace uso de un server de autenticación que consulta algunas cosas de el almacén de las llaves, obviamente toda la infraestructura debe de estar coordinada. 

KSM o Key Storage Manager. 

Pero lo primero que se tienen es una base de datos llamada la keystorage, para lo que en términos de seguridad es nuestro KSM o Key Storage Manager. 
El KSM, como todo lo de seguridad suena muy "acá", pero en realidad, no es más que una base de datos y una tabla para fines prácticos. Para fines teóricos de seguridad y de implementación, el KSM es la párte más importante y débil de nuestra infraestructura de llaves, es en donde vamos a almacenar las llaves AES que se almacenan en los equipos yubikey, lo cual nos permite desencriptar la información que contiene la yubikey. 
El KSM debería de ser una base de datos hiper-vigilada, hiper-autditada, por el lo que acabamos de comentar, pero seamos honestos, nadie lo hará, pero para mitigar esto, mi recomendación sería que la pusieran en un servidor con su propia base de datos y sin acceso más que a ciertas direcciones ip y usuarios, ademas de su hardening normal. 

La estructura de la KSM es:

Como se puede observar, es bastante sencilla.

Segun la documentación para generar llaves AES, como nunca debes de guardar "sin encriptar la informacion" lo pasa por el pipe y la firma con un dato, pero para fines de que saber que diantres esta  haciendo, nos podemos saltar esa parte.

Cuando ejecutamos el comando pasando el numero de la llave o el ragno de las llaves que queremos generar la salida es:

 perl ykksm-gen-keys.pl  1 

# serialnr,identity,internaluid,aeskey,lockpw,created,accessed[,progflags]
1,cccccccccccb,3f7a64615f3c,5ce3fb71c78292397678a556b1c0be02,4bbbe24a0335,2013-03-03T19:27:32,

Como podemos ver, casi se mapea 1-1  la información a la tabla, donde corresponde:



Campo Tabla Campo Comando Switch Valor
serialnr serialnr Copia de la yubikey 1
publicname identity -ofixed= cccccccccccb
created created n/a 2013-03-03T19:27:32
internalname internaluid -ouid= 3f7a64615f3c
aeskey aeskey -a 5ce3fb71c78292397678a556b1c0be02
lockcode lockpw -c 4bbbe24a0335
creator n/a n/a n/a
active n/a n/a n/a
hardware n/a n/a n/a

Ahora una explicación de los campos:

  1. serialnr creo que no necesita explicación, es el numero de serie.
  2. publicname es la parte no encriptada que se configura en la llave OTP para su envio.
  3. created la fecha de creacion de la llave.
  4. internalname es el valor que se usa en el uid de la llave OTP y viaja encriptada.
  5. aeskey es la llave aes utilizada para la encriptacion por parte del otp.
  6. lockcode es el password colocado en la llave para proteger la configuración.
  7. creator quien crea la llave
  8. active si la llave esta activa
  9. hardware ni idea, supongo que si es un OTP de hardware o puede ser de software.

Ahora, volviendo a la documentación, se tiene un "archivo encriptado" donde vienen la serie de estas llaves AES generadas, hay que notar que mucha de la información, pues, no tiene mucha relación con nada, continuando con la misma documentación ahora se importa este archivo a la base de datos con el comando ykksm-import.pl

Si nos fijamos, lo  único que hace realmente el comando es tomar esta información, desencriptarla con la llave que usamos para encriptarla y si no le pasamos el parametro --creator, pues entoces pone de llave de encriptacion en el creador, active y hardware estan como default 1.

Así que para fines prácticos, nos podemos obviar este proceso y subirlos a mano o con algún otro método que definamos y modificar la estructura de la base de datos, para por ejemplo que el dato de creator pueda contener algo más significativo que 8 caracters. Estas herramientas vienen en el paquete http://code.google.com/p/yubikey-ksm/ que es solamente la parte de almacenamiento del servidor de autenticación.

Yo supongo que ya tienes el servidor de autenticación configurado y el cliente, y lo que realmente falta es saber que datos ponerle a la llave, por lo menos eso es lo que a mi me falta.

Ahora, de estos datos, se usa la herramienta

ykpersonalize -ouid=3f7a64615f3c -a5ce3fb71c78292397678a556b1c0be02 -ofixed=cccccccccccb -c4bbbe24a0335

y el otp esta listo par ser usado. Esta información debe de estar guardada en la base de datos keystorage de KSM.

Con esto, la información entre el KSM, su tabla keystorage  y la OTP estan sincronizadas, solo falta actualizar el dato en el AuthServer, que es en donde vive la base de datos ykval.

En ykval tenemos la tabla `clients`
CREATE TABLE IF NOT EXISTS `clients` (
  `id` int(11) NOT NULL,
  `active` tinyint(1) DEFAULT '1',
  `created` int(11) NOT NULL,
  `secret` varchar(60) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
  `email` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `notes` varchar(100) COLLATE utf8_unicode_ci DEFAULT '',
  `otp` varchar(100) COLLATE utf8_unicode_ci DEFAULT '',
  PRIMARY KEY (`id`),
  UNIQUE KEY `id` (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

En esta tabla, el id lo tengo mapeado a el id del usuario en mi aplicacion, active, create a 1, secret es una cadena de tamaño fijo que se usa para firmar la información del lado del cliente, esta cadena debe de ser aleatoria con un tamaño de 26 caracteres hexadecimales y el sistema autentifica con el correo electrónico, el cual esa tal cual en texto plano.

Agregando estos datos ya estamos listos para usar la infraestructura.

Si tienes dudas, manda un mensaje... con gusto te podemos ayudar.

backbone.js + restful con epiphany + fuelUX datagrid + Bootstrap: Parte 3 model de backbone.js

Ahhhhhhh... esa fué mi expreción cuando entendí por que no me funcionaba.

Esta es una entrada corta, muy corta, por que veremos la parte que relaciona el CRUD del RESTful entre backbone.js y epiphany.

La idea de utilizar backbone era que se estaba mapeada a RESTful, entoces, teniamos el etendido que, operando con modelos:



BackboneEpiphanyCRUD
model.save() (sin id) getRoute()->post(); CREATE
model.fetch() getRoute()->get(); READ
model.save() getRoute()->put(); UPDATE
model.destroy() getRoute()->delete(); DELETE

Ahora, si nos fijamos, la parte Create y Update, solo hay una pequeña diferencia, si el modelo tiene o no tiene id. 

En la primera parte, se define un modelo "sencillo" que será utilizado en una colección:
var User = Backbone.Model.extend({
  idAttribute: "tabletaEntryid"
});
var Users = Backbone.Collection.extend({
  model:User,
  url:function (){
    return "/sync/users/fromid/"+this.maximoId+"/offset/"+this.pageSize;
  },
  pageIndex:0,
  pageSize:0,
  maximoId:0,

});


 Y la propiedad url, que uno supone es la "base" para el resftul, tanto en la colección como en la parte del modelo, sin embargo, la documentación de Backbone.js dice al respecto sobre el modelo:
urlmodel.url()
Returns the relative URL where the model's resource would be located on the server. If your models are located somewhere else, override this method with the correct logic. Generates URLs of the form: "[collection.url]/[id]" by default, but you may override by specifying an explicit urlRoot if the model's collection shouldn't be taken into account. You can also pass in the model's url as an option when instantiating it.
Delegates to Collection#url to generate the URL, so make sure that you have it defined, or a urlRoot property, if all models of this class share a common root URL. A model with an id of 101, stored in a Backbone.Collection with a url of "/documents/7/notes", would have this URL: "/documents/7/notes/101"
urlRootmodel.urlRoot or model.urlRoot()
Specify a urlRoot if you're using a model outside of a collection, to enable  the defaulturl function to generate URLs based on the model id. "[urlRoot]/id"
Normally, you won't need to define this. Note that urlRoot may also be a function.
Lo cual, me hizo suponer, por no leer y entender bien,  que la definición de un modelo era:
var Cliente=Backbone.Model.extend({
    url: '/sync/infocliente',
})

Con eso, defines el URL específico para la colección y los puts, delete van directo al url SIN formar la parte resftul de url/:id, la forma correcta de definirlo es:
var Cliente=Backbone.Model.extend({
    urlRoot: '/sync/infocliente',
})

La diferencia es, y la documentación lo marca, pero solo lo entendí en base a "hack and slash" que urlRoot se usa cuando definimos un modelo FUERA de una colección, mientras que url es para especificar el url único del modelo o se delega su construcción a la colección.

Ahora, como, dice la nota en la tabla, para que el modelo haga post para crear un elemento del modelo o un post es si tiene definida la propiedad id:
var c = new Cliente({id: 1, fecha='hoy'});

Define un modelo completo.
c.set({tipo:'Mal cliente'});
c.save()
genera un put a /sync/infocliente/1 se ejecuta
en cambio
var c= new Cliente({tipo:'Mal cliente'});
c.save(); 
genera un post a /sync/infocliente


Esto se mapea con el epiphayny de la siguiente forma:
getRoute()->get('/sync/infocliente/(\d+)', array("sync", "infoclient"));
getRoute()->put('/sync/infocliente/(\d+)', array("sync", "updatecliente"));
getRoute()->delete('/sync/infocliente/(\d+)', array("sync", "deletecliente"));
Todo esta sencillo, excepto que en el put, php no "pela" el request ni lo transforma en nada de variable, por lo tanto hay que leerlo y backbone manda un objeto json que hay que interpretar:
  /**
    Actualiza un dato del cliente vía put
  */
  function updateCliente($id=null)
  {
    if(is_null($id))
    return;
    $id=intval($id);
    if($id<1)
    return;
    $putdata = file_get_contents("php://input");
    $vars=json_decode($putdata);
    if($id!=$vars->id)
    return;
}
La lectura de la información del request put la leo y transformo en objeto json de la siguiente forma:
    $putdata = file_get_contents("php://input");
    $vars=json_decode($putdata);

Y luego de lo que me dí cuenta, es que model.save() manda todos los atributos del elemento, por lo tanto puedo validar que el id del modelo sea igual al id del request como se ven en:
    if($id!=$vars->id)
    return;

Bueno, con eso termino mi experimentación por el momento... 
// Cookie consent