En Couchbase 4.5, los datos estaban protegidos cubo por cubo. Cada bucket tenía una contraseña, y para acceder a un bucket a través de una consulta N1QL, el usuario tenía que incluir la contraseña del bucket en la consulta. Los buckets sin contraseña eran posibles, pero no se recomendaban para uso en producción.

Este esquema ofrecía una protección básica, pero era de grano muy grueso: un usuario podía hacer todo con un cubo, o nada en absoluto. Además, para acceder a varios buckets era necesario introducir una contraseña para cada uno de ellos, lo que resultaba incómodo, sobre todo si las contraseñas cambiaban.

Para permitir a nuestros usuarios evitar estos problemas, hemos introducido el control de acceso basado en roles (RBAC) en Couchbase Server 5.0. El acceso a los datos se controla ahora a través de roles detallados en los buckets, y a cada usuario se le pueden asignar roles que se ajusten a lo que realmente debería estar haciendo en la base de datos.

En este artículo te guiaré a través de las principales funcionalidades ofrecidas por RBAC en Couchbase Server 5.0. Los ejercicios prácticos te permitirán probar las nuevas características por ti mismo.

Configurar

Para los ejercicios prácticos, necesitarás instalar Couchbase Server 5.0, Enterprise Edition. Durante la instalación, configúralo para tener un administrador llamado "Administrator" con contraseña "password". Esto no es una práctica recomendada en un entorno de producción, por supuesto.

Accede a la consola de administración (en http://localhost:8091) y ve a la pantalla Buckets. Allí crea dos buckets, "testbucket1" y "testbucket2", cada uno con una cuota de memoria de 100 MB para evitar quedarte sin memoria.

A continuación, vaya a la pantalla Consulta y cree índices primarios en los dos buckets que acaba de crear. Los índices primarios le permiten ejecutar consultas en los buckets.

Puede ir a la pantalla Índices para comprobar que los índices se han creado realmente. Ambos se llamarán "#primary".

Funciones principales

Hay cuatro roles principales que controlan quién puede ejecutar qué consultas N1QL. Los roles query_select, query_insert, query_update y query_delete permiten ejecutar consultas N1QL del tipo correspondiente. También hay tres roles más especializados (query_manage_index, query_system_catalog, y query_external_access) que serán cubiertos en la siguiente sección, Roles Adicionales Importantes.

Pero hay más. Estos roles están parametrizados por el cubo al que se aplican. Un usuario no puede tener simplemente el rol query_select; necesitamos saber en qué cubo está el rol, como query_select[testbucket1], que permite al usuario ejecutar una consulta SELECT contra testbucket1. También es posible tener este rol en todos los cubos, indicado por query_select[*].

Para probarlo tú mismo, entra en la consola de Couchbase y en la pantalla de Seguridad crea un nuevo usuario user1 con contraseña "password" y rol query_select[testbucket1].

La función se encuentra en "Funciones de consulta" en el menú de creación de usuarios.

A continuación, haga lo mismo para "usuario2", pero dele a ese usuario query_select[testbucket2].

Ahora vamos a intentar ejecutar una consulta contra estos buckets usando los roles. Usaré la herramienta de shell CBQ que viene con Couchbase.

Que nos dan esta respuesta:

Fíjate que el error nos dice muy claramente qué rol nos falta. Intentémoslo de nuevo con el usuario1, que tiene el rol correcto:

Funcionó:

Intente usted mismo la consulta con el usuario2, que tiene el rol correcto pero en el cubo equivocado. La solicitud fallará.

Intentemos ahora una consulta más compleja que afecte a dos buckets. Comience ejecutando esta consulta:

El sistema nos dice que necesita el rol query_insert[testbucket2]:

Crea un nuevo usuario "user3" con el rol requerido, e inténtalo de nuevo:

Seguimos recibiendo un error, pero es un error diferente al de antes. La consulta que estamos intentando ejecutar tiene dos partes; selecciona de testbucket1 e inserta en testbucket2. Hemos proporcionado suficientes credenciales para la inserción pero no para la selección. Ve a la consola, añade query_select[testbucket2] a user3 e inténtalo de nuevo. Esta vez la consulta funciona.

Intentemos una cosa más. Añade una cláusula RETURNING a la consulta e intenta ejecutarla:

Esto falla:

Lo que ocurre aquí es que la cláusula RETURNING está siendo tratada como un SELECT sobre el bucket en el que hemos insertado (testbucket2), ocurriendo justo después de la inserción. El usuario no tiene el rol query_select[testbucket2] y por lo tanto está siendo rechazado.

Añade el rol query_select[testbucket2] a user3 y vuelve a ejecutar la consulta. Ahora funcionará.

Funciones adicionales importantes

Hay tres funciones más que debes conocer cuando trabajes con N1QL.

query_manage_index
En primer lugar, vamos a intentar crear un índice:

Eso nos da un error:

El rol Query Manage Index en un bucket es necesario para crear, borrar o construir índices en ese bucket.

Crea un nuevo usuario "user4" con el rol query_manage_index[testbucket1]. Prueba el creación de índices de nuevo. Ahora la consulta funcionará.

catálogo_sistema_consulta
En versiones anteriores de Couchbase, las tablas del sistema eran totalmente accesibles para cualquiera. Ahora están más restringidas de varias maneras que se describirán más adelante en este documento, pero hay un rol útil, query_system_catalog, que permite el acceso a las tablas del sistema. Esto es particularmente útil para el personal que necesita ser capaz de depurar problemas con las consultas o el sistema, pero no se les debe dar privilegios de administrador completo.

Si consultamos system:keyspaces como administrador, veremos los dos buckets que hemos creado en el sistema:

Pero si ejecutamos la misma consulta sin credenciales, los resultados se filtran:

Cree un nuevo usuario "user5" con el rol query_system_catalog, y vuelva a ejecutar la consulta. Verás los mismos resultados que cuando ejecutamos la consulta como Administrador.

Consulta_acceso_externo

La nueva función CURL() permite consultar servicios REST desde N1QL. Para usar la función, necesitamos hacer alguna configuración, y ejecutar la consulta usando el nuevo rol query_external_access.

Probemos primero la consulta:

La consulta se rechaza porque no se facilitan los permisos adecuados:

Crea un usuario "user6" con el rol query_external_access y vuelve a ejecutar la consulta utilizando ese usuario. Esta vez la consulta se niega a ejecutarse porque no hemos habilitado CURL(); por motivos de seguridad está deshabilitado por defecto.

Cree un archivo "curl_whitelist.json" con el siguiente contenido:

Colóquelo en el directorio couchbase. En un Mac, la ubicación exacta es "/Applications/Couchbase Server.app/Contents/Resources/couchbase-core/var/lib/couchbase/n1qlcerts/curl_whitelist.json". En otros sistemas, la ubicación es ligeramente diferente. Pruebe de nuevo la consulta, que debería ejecutarse correctamente, descargando los datos de la siguiente manera:

La lista completa de funciones de N1QL es la siguiente:

Papel Permisos Sintaxis GRANT
Seleccionar consulta Declaraciones SELECT GRANT select ON testbucket TO myuser
Insertar consulta Declaraciones INSERT GRANT insert ON testbucket TO myuser
Actualización de consultas Declaraciones UPDATE GRANT update ON testbucket TO myuser
Consulta Borrar Declaraciones DELETE GRANT delete ON testbucket to myuser
Consultar el catálogo del sistema Acceso a los espacios de claves del sistema GRANT query_system_catalog TO myuser
Consulta Gestionar índice Operaciones de indexación GRANT query_manage_index ON testbucket TO myuser
Consulta de acceso externo Función CURL() GRANT query_external_access TO myuser

explicar y preparar

Por supuesto, podemos hacer otras cosas con las consultas además de ejecutarlas. Podemos usar EXPLAIN para entender cómo el motor de consultas calcula una consulta. Y podemos utilizar PREPARE para configurar una consulta para su ejecución repetida.

En Couchbase 5.0, los permisos para EXPLAIN y PREPARE son simples. Son los mismos que los permisos requeridos para la sentencia subyacente. Eso es todo.

Para comprobarlo, intentemos EXPLICAR una sentencia SELECT sencilla, la misma que utilizamos en la sección anterior "Funciones principales":

En respuesta recibimos un mensaje de error que nos pide un rol específico:

Proporcionemos un usuario con ese rol:

Éxito, tal y como vimos para la propia declaración en "Funciones principales".

Ahora vamos a intentar PREPARAR la segunda declaración de "Roles primarios":

Recibimos el mismo mensaje de error que recibimos originalmente para la propia sentencia:

Y si añadimos un usuario con credenciales para el SELECT y el INSERT, el PREPARE tiene éxito:

CONCEDER y REVOCAR

En 5.0, N1QL incluye sentencias para dar roles a los usuarios (GRANT) y para quitarlos (REVOKE). Estas sentencias requieren permiso de Administrador para ejecutarse.

Antes de probar estas declaraciones, revisemos qué usuarios están configurados y qué roles tienen. Esto es lo que deberías ver en la pantalla de Seguridad de la consola de Couchbase.

Podemos otorgar un nuevo rol cluster_admin al usuario1 de la siguiente manera:

Esto tendrá éxito, y poco después la consola de Couchbase se actualizará para reflejar la nueva asignación de roles.

También podemos asignar roles parametrizados, así:

Podemos deshacer la concesión inicial mediante un REVOKE:

Todos estos parámetros pueden recibir listas de argumentos:

Por último, el prefijo query_ es opcional para query_insert, query_update, query_delete y query_select, lo que hace que parte de la sintaxis resulte más familiar:

Comparación con Oracle

El control de acceso basado en roles en Couchbase 5.0 ha sido diseñado para ser familiar a los profesionales que han utilizado el control de acceso en otros sistemas de bases de datos actuales. A estas alturas, ya deberías haber reconocido conceptos familiares como que los permisos de inserción/selección/actualización/eliminación son aplicables a los buckets, que son algo así como tablas. También debería resultarte familiar la noción de usuarios administradores con amplios permisos. El control de acceso basado en roles en Couchbase 5.0 ha sido diseñado para ser familiar a los profesionales que han utilizado el control de acceso en otros sistemas de bases de datos actuales. A estas alturas, ya deberías haber reconocido conceptos familiares como que los permisos de inserción/selección/actualización/eliminación son aplicables a los buckets, que son algo así como tablas. También debería resultarle familiar la noción de usuarios administradores con amplios permisos.

Por ejemplo, esta consulta GRANT funcionará tanto en Couchbase como en Oracle:

Una diferencia conceptual entre Couchbase y otros sistemas como Oracle es que nosotros tenemos un modelo binario de privilegios: usuarios y roles. Ellos típicamente tienen un modelo trinario, con usuarios, roles y privilegios. En consecuencia, dar permisos a los usuarios en Oracle es conceder privilegios sobre objetos a los usuarios. En Couchbase, se trata de otorgar roles parametrizados a los usuarios.

Los roles son estáticos en 5.0. No existen sentencias equivalentes a CREATE/DROP/ALTER ROLE.

Los permisos de Couchbase son sobre el sistema en su conjunto o sobre los buckets. No tenemos noción de permisos sobre tablas, columnas o colecciones.

En Couchbase GRANT y REVOKE solo son posibles por usuarios Admin. No existe tal cosa como una OPCIÓN ADMIN o una OPCIÓN GRANT. Cambiar permisos requiere que seas un Administrador.

Finalmente, no tenemos equivalente de SET ROLE. SET ROLE es un comando a nivel de sesión, lo que no tiene sentido en Couchbase porque no tenemos sesiones, sólo peticiones RESTful individuales.

Nuevos espacios clave del sistema

Couchbase 5.0 introduce tres nuevos espacios de claves del sistema relacionados con los usuarios. El primero de ellos es system:user_info. Este keypace lista los usuarios configurados en el sistema, incluyendo sus roles. Intentemos una consulta:

Eso nos da siete entradas como esta, una por cada usuario que hayamos configurado, más el Administrador configurado:

El espacio clave system:applicable_roles es similar, pero divide cada rol de usuario en una entrada independiente, lo que produce una visión más relacional de los datos:

Por último, el espacio de claves system:my_user_info muestra la parte de system:my_user_info correspondiente al usuario cuyas credenciales se introducen con la consulta.

Acceso a los espacios de claves del sistema

Siguiendo una filosofía general de funcionamiento seguro, los espacios de claves del sistema (buckets) están protegidos en la versión 5.0. El grado de restricción varía en función de los datos presentes en cada espacio de claves.

Tres espacios de claves no tienen nada que pueda ser valioso para un atacante:

  • sistema:almacenes de datos
  • sistema:espacios de nombres
  • sistema:dual

Por consiguiente, estos espacios de claves no están protegidos. No se necesitan credenciales para acceder a ellos.

En el otro extremo de la seguridad están system:user_info y system:applicable_roles, que contienen la lista de usuarios y sus roles. Sólo pueden acceder a ellas los usuarios Admin y Read Only Admin. La tabla system:my_user_info es similar, pero sólo muestra la información relevante para el usuario cuyas credenciales se presentan con la consulta. Ya hemos explorado estas tablas anteriormente.

Los siguientes cuatro espacios de claves del sistema contienen una variedad de información de tiempo de ejecución y configuración.

  • Sistema:preparados
  • Sistema:solicitudes_realizadas
  • Sistema:solicitudes_activas
  • Sistema:nodos

Como la información que contienen no es tan sensible como la de los usuarios, son más accesibles. La mayoría de los administradores, incluso los de menor importancia, pueden acceder a ellos: Admin, Read Only Admin, Cluster Admin, Query System Catalog, Replication Admin, Bucket Admin(cualquier bucket), o Views Admin(cualquier bucket).

Intentemos ver system:prepareds como user5, el usuario que creamos con permiso Query System Catalog, arriba.

Esto nos muestra una declaración preparada que creamos anteriormente.

El espacio clave system:keyspaces muestra la lista de buckets configurados en el sistema. Esta información es algo sensible, ya que proporciona a un atacante información sobre para qué se utiliza un sistema. En consecuencia, los usuarios con roles de alto nivel (Admin, Read Only Admin, Cluster Admin) ven todo lo que hay en este espacio de claves. Los usuarios con el rol Catálogo del Sistema de Consulta también ven todo, ya que este rol está destinado a depurar problemas de consulta. Para otros usuarios, la vista está filtrada; el usuario sólo ve aquellos espacios clave para los que tiene permiso query_select.

Por ejemplo, una consulta en system:keyspaces sin credenciales tendrá éxito pero no mostrará ninguna entrada:

Añada las credenciales para el usuario5, que tiene el rol Consulta del Catálogo del Sistema, y se mostrarán todas las entradas:

Utiliza las credenciales para el usuario1, que sólo tiene query_select[testbucket1], y verás sólo la entrada para testbucket1.

El espacio de claves system:indexes se gestiona de forma muy similar a system:keyspaces: los roles de alto nivel permiten el acceso completo, mientras que el rol query_select permite el acceso filtrado. La diferencia real es que el rol query_manage_index permite acceso filtrado, como query_select.

Protección de las API administrativas

El motor de consultas N1QL tiene APIs RESTful correspondientes a tres de los espacios clave del sistema: system:prepareds, system:completed_requests, y system:active_requests. Estos solían ser abiertos en Couchbase 4.6, pero ahora son seguros. Requieren las mismas credenciales que los espacios clave.

Si lo intentamos de nuevo con el usuario5, que tiene el rol requerido, funciona.

Acceso a los cubos migrados sin contraseña

Al migrar de 4.6 a 5.0, es útil conservar los patrones de permisos existentes, para permitir que las aplicaciones heredadas sigan funcionando como antes. En este caso es un poco complicado, porque en 4.6 el acceso se controlaba mediante contraseñas en los propios buckets, mientras que en 5.0 el control de acceso se basa en usuarios con varios roles.

Para preservar los patrones de acceso heredados, durante el proceso de actualización creamos usuarios con nombres y contraseñas que coinciden con el bucket original. Esto permite que las aplicaciones existentes sigan haciendo lo que hacían, incluso en el caso de acceso sin contraseña alguna.

Ver esto en acción va a requerir algo de trabajo. Ponte cómodo.

Empieza instalando Couchbase 4.6. A continuación, crea dos buckets, "openbucket" sin contraseña y "closedbucket" con contraseña "password".

Vaya a la pestaña Consulta y añada índices primarios para ambos buckets a fin de permitir la ejecución de consultas N1QL.Vaya a la pestaña Consulta y añada índices primarios para ambos buckets a fin de permitir la ejecución de consultas N1QL.

Compruebe que openbucket puede consultarse sin contraseña:

Pero la consulta a closedbucket sin contraseña falla:

Pero closedbucket se puede consultar con una contraseña:

Este es el patrón de acceso que queremos preservar cuando actualicemos a 5.0. Ahora apaga Couchbase, y actualiza a 5.0, preservando los datos subyacentes que acabamos de crear. Luego ve a la pantalla de Seguridad de la consola de Couchbase. Allí verás dos nuevos usuarios creados por el proceso de actualización.

El usuario "closedbucket" tiene el mismo nombre que el bucket "closedbucket" y la contraseña que se asignó al bucket en la versión 4.6. Nos permite preservar el acceso heredado a closedbucket. El usuario "openbucket" hace lo mismo, pero para openbucket.

Comprobemos que el patrón de acceso anterior sigue funcionando.

Openbucket sigue siendo accesible sin contraseña.

El acceso a Closedbucket falla sin contraseña.

Pero el acceso a closedbucket tiene éxito con una contraseña.

¡Hurra! Las cosas funcionan como antes. Ve a prepararte un capricho.

Resumen

  • El control de acceso en Couchbase 4.6 usaba contraseñas para los buckets. En 5.0 se utilizan roles asignados a los usuarios.
  • Los roles principales utilizados para controlar el acceso de un usuario a N1QL son query_select/query_insert/query_update/query_delete. Todos ellos están parametrizados por bucket.
  • Otras funciones importantes más especializadas son query_manage_index, query_system_catalog y query_external_access.
  • Explicar o preparar una consulta requiere las mismas funciones que ejecutarla.
    Hay nuevas sentencias que permiten CONCEDER y REVOCAR roles.
  • El sistema de roles debería resultar familiar a los usuarios familiarizados con otras bases de datos importantes. La principal diferencia es que Couchbase no tiene noción de permisos fuera de los roles.
  • Hay nuevos espacios clave del sistema para consultar los usuarios y las funciones que tienen asignadas.
    Los espacios de claves del sistema se controlan por motivos de seguridad. El comportamiento varía de un espacio de claves a otro en función de la sensibilidad de los datos que contiene.
  • Los patrones de acceso existentes, incluso para los buckets sin contraseña, deberían seguir funcionando tras la migración de 4.6 a 5.0.

Autor

Publicado por Johan Larson

Johan Larson es Ingeniero de Software Senior en Couchbase. La responsabilidad del trabajo de Johan es construir un lenguaje de consulta basado en SQL para datos JSON en un sistema NoSQL distribuido.

Dejar una respuesta