security couchdb

security - Autorización CouchDB sobre una base por base de datos



(3)

He estado haciendo más investigaciones y pruebas, y quiero resumir dónde he llegado y qué es lo que aún no funciona para mí.

En primer lugar, disculpas por quienes leyeron esta pregunta: estaba buscando formas de establecer permisos para que las personas escriban, no lean, la base de datos. Resulta ser una gran diferencia: las técnicas para crear un "lector" son completamente diferentes de crear un "escritor" (ese término en realidad no existe, aunque me pregunto por qué).

En resumen: debe agregar un usuario a la base de datos _users, que es una lista de los usuarios que tienen acceso a cualquier base de datos en su instancia de CouchDB. Pude hacerlo al emitir un comando similar a:

curl -X PUT http://admin:password@localhost:5984/_users/org.couchdb.user:username -d ''{"type":"user", "hashed_password":"2bf184a2d152aad139dc4facd7710ee848c2af27", "name":"username", "roles":[]}''

Tenga en cuenta que, al parecer, debe indicar el nombre de usuario con el prefijo "org.couchdb.user". Usé un método de hash de Ruby para obtener el valor hashed_password:

require ''digest/sha1'' pass_hash = Digest::SHA1.hexdigest(password)

Esto consigue un usuario aparentemente válido en la base de datos. El siguiente paso es asignar a ese usuario como un "escritor" (¡ja, ahí está otra vez!) Para la nueva base de datos que creé. Entonces podría hacer algo como:

curl -X PUT http://admin:password@localhost:5984/newdatabase

y entonces

curl -X PUT http://admin:password@localhost:5984/newdatabase/_design/security -d @security.json

Ese archivo .json contiene una función de Javascript para la clave "validate_doc_update", y esa función se ve así:

function(new_doc, old_doc, userCtx) { if(userCtx.name != username) { throw({forbidden: "Please log in first."}); } }

Es rotonda, pero tiene sentido. Sin embargo, ahora me encuentro con un problema: al parecer, la variable userCtx no se llena hasta que el usuario se autentica. Este artículo sugiere que todo lo que tiene que hacer es pasar las credenciales a través de una solicitud HTTP a una base de datos de sesión especial, como por ejemplo:

curl -X POST http://username:password@localhost:5984/_session

Puedo hacer eso para mi usuario administrador, y la var de userCtx se completará. Pero para mi usuario recién creado, falla:

$ curl http://org.couchdb.user:username:password@localhost:5984/_session {"ok":true,"userCtx":{"name":null,"roles":[]},"info":{"authentication_db":"_users","authentication_handlers":["cookie","oauth","default"]}}

Tenga en cuenta que el hash userCtx es nulo. Me pregunto si esa cosa del espacio de nombres está causando el problema. Tiene un freakin ''dos ​​puntos en él, así que tal vez hay algo de confusión acerca de la contraseña? He intentado hacerlo sin el espacio de nombres, y no funciona en absoluto; al menos aquí mi solicitud parece estar llegando a la base de datos y obteniendo una respuesta.

Estoy atascado en este punto. Si alguien puede verificar mis suposiciones y progresar hasta ahora, espero que todos podamos descubrir cómo hacer que esto funcione.

¡Gracias!

Aaron

Estoy trabajando en una aplicación soportada por CouchDB. Esencialmente, quiero crear una base de datos para cada usuario individual de mi aplicación. Para lograr esto, el usuario administrador creará la base de datos, pero en adelante, el usuario tendrá que acceder a su base de datos (utilizando HTTP Auth over SSL). He estado pasando un buen rato pensando en esto.

El mejor recurso que he encontrado está en la wiki de CouchDB, en este enlace:

http://wiki.apache.org/couchdb/Security_Features_Overview#Authorization

Sugiere que puede configurar la autorización por base de datos creando un documento llamado "_security" al que agrega un hash de administradores y lectores. Cuando intento crear ese documento, el mensaje que recibo es "Miembro de documento especial no válido: _seguridad".

$ curl -X GET http://localhost:5984 {"couchdb":"Welcome","version":"1.0.1"}

¡Cualquier ayuda sería apreciada!

Aclamaciones,

Aaron


No debería haber ningún problema con ese enfoque.

Digamos que usted tiene una base de datos "de prueba", y ya tiene una cuenta de administrador:

curl -X PUT http://localhost:5984/test -u "admin:123"

Ahora puedes crear un documento de seguridad para él:

curl -X PUT http://localhost:5984/test/_security -u "admin:123" -d ''{"admins":{"names":[], "roles":[]}, "readers":{"names":["joe"],"roles":[]}}''

Solo el usuario "joe" podrá leer la base de datos. Para crear el usuario debe tener ya la contraseña hash sha1:

curl -X POST http://localhost:5984/_users -d ''{"_id":"org.couchdb.user:joe","type":"user","name":"joe","roles":[],"password_sha":"c348c1794df04a0473a11234389e74a236833822", "salt":"1"}'' -H "Content-Type: application/json"

Este usuario tiene la contraseña "123" con hash usando sha1 con sal "1" (sha1 ("123" + "1")), para que pueda leer la base de datos:

curl -X GET http://localhost:5984/test -u "joe:123"

Puede leer cualquier documento ahora en esa base de datos, y ningún otro usuario (excepto él y admin) puede.

ACTUALIZADO: seguridad del escritor

El método anterior emite el problema del lector, pero el permiso del lector aquí en realidad significa "leer / escribir documentos comunes", por lo que permite escribir documentos excepto los documentos de diseño. Los "admin" en la _security doc pueden escribir do design-docs en esta base de datos.

El otro enfoque, tomado de su propia respuesta, es el "validate_doc_update", puede tener un validate_doc_update como sigue en un archivo:

function(new_doc, old_doc, userCtx) { if(!userCtx || userCtx.name != "joe") { throw({forbidden: "Bad user"}); } }

Y empújalo en un diseño couchdb:

curl -X PUT http://localhost:5984/test/_design/security -d "{ /"validate_doc_update/": /"function(new_doc,doc,userCtx) { if(userCtx || userCtx.name != ''joe'') {throw({forbidden: ''Bad user''})}}/"}" --user ''admin:123''

Los "joe" pueden escribir en la base de datos utilizando la autenticación básica:

curl -X PUT http://localhost:5984/test/foobar -d ''{"foo":"bar"}'' -u ''joe:123''

Como también abordó, puede usar la api _session para obtener una cookie para la autenticación:

curl http://localhost:5984/_session -v -X POST -d ''name=joe&password=123'' -H "Content-Type: application/x-www-form-urlencodeddata"

Esto devolverá un encabezado como:

Set-Cookie: AuthSession=am9lOjRDRDE1NzQ1Oj_xIexerFtLI6EWrBN8IWYWoDRz; Version=1; Path=/; HttpOnly

Por lo tanto, puede incluir la cookie "AuthSession = am9lOjRDRDE1NzQ1Oj_xIexerFtLI6EWrBN8IWYWoDRz" en sus próximas solicitudes y se autenticarán.