Configurar el acceso basado en recursos

En esta página se describe cómo gestionar el acceso a recursos específicos mediante enlaces de roles condicionales en tus políticas de permisos. Si usas atributos de recursos en una expresión de condición, puedes controlar si una entidad puede usar un permiso para acceder a un recurso en función del nombre, el tipo y el servicio del recurso. Google Cloud

Antes de empezar

  • Lee la información general sobre las condiciones de gestión de identidades y accesos (IAM) para conocer los conceptos básicos de los enlaces de roles condicionales de IAM.
  • Consulte los atributos de recursos que se pueden usar en una expresión de condición.
  • El atributo de nombre de recurso puede controlar el acceso a los siguientes Google Cloud servicios:
    • Apigee
    • Application Integration
    • Hub de APIs de Apigee
    • Servicio de copia de seguridad y DR
    • BigQuery
    • API Reservation de BigQuery
    • Bigtable
    • Autorización binaria
    • Cloud Deploy
    • Cloud Key Management Service
    • Cloud Logging
    • Cloud SQL
    • Cloud Storage
    • Compute Engine
    • Dataform
    • Google Kubernetes Engine
    • Firestore
    • Integration Connectors
    • Google Cloud Managed Service para Apache Kafka
    • Gestor de parámetros
    • Pub/Sub Lite
    • Secret Manager
    • Spanner

Roles obligatorios

Para obtener los permisos que necesitas para gestionar las vinculaciones de roles condicionales, pide a tu administrador que te conceda los siguientes roles de gestión de identidades y accesos:

Para obtener más información sobre cómo conceder roles, consulta el artículo Gestionar el acceso a proyectos, carpetas y organizaciones.

Estos roles predefinidos contienen los permisos necesarios para gestionar las vinculaciones de roles condicionales. Para ver los permisos exactos que se necesitan, despliega la sección Permisos necesarios:

Permisos obligatorios

Para gestionar las vinculaciones de roles condicionales, se necesitan los siguientes permisos:

  • Para gestionar el acceso a los proyectos, sigue estos pasos:
    • resourcemanager.projects.getIamPolicy en el proyecto
    • resourcemanager.projects.setIamPolicy en el proyecto
  • Para gestionar el acceso a las carpetas, sigue estos pasos:
    • resourcemanager.folders.getIamPolicy en la carpeta
    • resourcemanager.folders.setIamPolicy en la carpeta
  • Para gestionar el acceso a las organizaciones, sigue estos pasos:
    • resourcemanager.organizations.getIamPolicy en la organización
    • resourcemanager.organizations.setIamPolicy en la organización

También puedes obtener estos permisos con roles personalizados u otros roles predefinidos.

Conceder acceso a un grupo de recursos en función de los prefijos de los nombres de los recursos

Se puede usar una vinculación de rol condicional para conceder acceso a principales a recursos cuyos nombres coincidan con un prefijo, como las instancias de máquina virtual (VM) de Compute Engine cuyos nombres empiecen por una cadena determinada. El prefijo del nombre del recurso se suele usar para agrupar recursos destinados a un fin concreto o que tienen determinadas propiedades.

Por ejemplo, supongamos que ejecutas cargas de trabajo en determinadas instancias de VM que pueden operar con datos sanitarios sensibles. Otras cargas de trabajo no sensibles deben ejecutarse en el mismo proyecto y quieres asegurarte de que tus desarrolladores tengan acceso limitado a las instancias de VM que operan con datos sensibles. Para ello, asigna el prefijo sensitiveAccess a las instancias de VM que contengan datos sensibles y el prefijo devAccess a las demás instancias de VM. Después, puedes usar enlaces de roles condicionales para asegurarte de que los desarrolladores puedan seguir trabajando con normalidad en las instancias de devAccess máquinas virtuales, pero sin concederles acceso a las instancias de sensitiveAccess máquinas virtuales.

Aunque puede usar el atributo de condición resource.name por sí solo para gestionar el acceso, es habitual usar también los atributos resource.type y resource.service. Si usa estos atributos adicionales, será menos probable que una condición afecte al acceso a diferentes tipos de recursos con nombres similares. En el ejemplo de esta sección se controla el acceso mediante los atributos resource.name y resource.type.

Para conceder acceso a los discos e instancias de Compute Engine de un proyecto en función de un prefijo de nombre, sigue estos pasos:

Consola

  1. En la consola, ve a la página IAM. Google Cloud

    Ve a la página Gestión de identidades y accesos.

  2. En la lista de principales, busca el principal que quieras y haz clic en el botón .

  3. En el panel Editar permisos, busca el rol al que quieras configurar una condición. A continuación, en Condición de IAM (opcional), haz clic en Añadir condición de IAM.

  4. En el panel Editar condición, introduce un título y una descripción opcional para la condición.

  5. Puedes añadir una expresión de condición con el Creador de condiciones o el Editor de condiciones. El creador de condiciones proporciona una interfaz interactiva para seleccionar el tipo de condición, el operador y otros detalles aplicables de la expresión. El editor de condiciones proporciona una interfaz basada en texto para introducir manualmente una expresión con la sintaxis de CEL.

    Creador de condiciones:

    1. Elimina los campos de condición que haya en el creador de condiciones. El único campo del creador de condiciones debe ser el botón Añadir.
    2. Crea una expresión de condición agrupada que dé como resultado true si el recurso es un disco que empieza por el prefijo especificado:
      1. Haz clic en el desplegable Añadir y, a continuación, en Condiciones agrupadas.
      2. En el menú desplegable Tipo de condición, selecciona Recurso > Tipo.
      3. En el menú desplegable Operador, selecciona es.
      4. En el menú desplegable Resource Type (Tipo de recurso), selecciona compute.googleapis.com/Disk.
      5. Haz clic en el primer botón Añadir situado justo debajo de la condición que acabas de introducir para añadir otra cláusula a la expresión.
      6. En el menú desplegable Tipo de condición, selecciona Recurso > Nombre.
      7. En el menú desplegable Operador, selecciona Empieza por.
      8. En el campo Valor, introduce el nombre del recurso, incluido el prefijo que quieras, en el formato adecuado. Por ejemplo, usa projects/PROJECT_ID/region/ZONE_ID/disks/PREFIX para identificar los discos del proyecto PROJECT_ID y de la zona ZONE_ID cuyos nombres empiecen por PREFIX.
      9. A la izquierda de cada tipo de condición, haga clic en Y para asegurarse de que ambas cláusulas deben ser verdaderas.
    3. Crea una expresión de condición agrupada que se evalúa como true si el recurso es una instancia que empieza por el prefijo especificado:
      1. Haz clic en el botón Añadir situado fuera del grupo de condiciones y, a continuación, en Condiciones agrupadas.
      2. En el menú desplegable Tipo de condición, selecciona Recurso > Tipo.
      3. En el menú desplegable Operador, selecciona es.
      4. En el menú desplegable Tipo de recurso, selecciona compute.googleapis.com/Instance.
      5. En el mismo grupo de condiciones, haz clic en Añadir.
      6. En el menú desplegable Tipo de condición, selecciona Recurso > Nombre.
      7. En el menú desplegable Operador, selecciona Empieza por.
      8. En el campo Valor, introduce el nombre del recurso, con el prefijo que quieras, en el formato adecuado. Por ejemplo, usa projects/PROJECT_ID/zones/ZONE_ID/instances/PREFIX para identificar las instancias del proyecto PROJECT_ID y la zona ZONE_ID cuyos nombres empiezan por PREFIX.
      9. Asegúrate de que el operador lógico que conecta las condiciones del grupo esté definido como Y.
    4. Crea una expresión de condición agrupada que dé como resultado true si el recurso no es un disco ni una instancia:
      1. Haz clic en el botón Añadir situado fuera de los grupos de condiciones actuales y, a continuación, en Condiciones agrupadas.
      2. En el menú desplegable Tipo de condición, selecciona Recurso > Tipo.
      3. En el menú desplegable Operador, selecciona no es.
      4. En el menú desplegable Resource Type (Tipo de recurso), selecciona compute.googleapis.com/Disk.
      5. En el mismo grupo de condiciones, haz clic en Añadir.
      6. En el menú desplegable Tipo de condición, selecciona Recurso > Tipo.
      7. En el menú desplegable Operador, selecciona no es.
      8. En el menú desplegable Tipo de recurso, selecciona compute.googleapis.com/Instance.
      9. Asegúrate de que el operador lógico que conecta las condiciones del grupo esté definido como Y.
    5. Asegúrate de que el operador lógico que conecta todos los grupos de expresiones de condición sea O.

      Cuando haya terminado, el creador de condiciones debería tener un aspecto similar al siguiente:

    6. Haz clic en Guardar para aplicar la condición.

    7. Cuando se cierre el panel Editar condición, haz clic de nuevo en Guardar en el panel Editar permisos para actualizar tu política de permitir.

    Editor de condiciones:

    1. Haz clic en la pestaña Editor de condiciones e introduce la siguiente expresión:

      (resource.type == "compute.googleapis.com/Disk" &&
      resource.name.startsWith("projects/PROJECT_ID/zones/ZONE_ID/disks/PREFIX")) ||
      (resource.type == "compute.googleapis.com/Instance" &&
      resource.name.startsWith("projects/PROJECT_ID/zones/ZONE_ID/instances/PREFIX")) ||
      (resource.type != "compute.googleapis.com/Disk" &&
      resource.type != "compute.googleapis.com/Instance")
    2. Después de introducir la expresión, puede corregir la sintaxis de CEL haciendo clic en Ejecutar corrector, situado en la parte superior derecha del cuadro de texto.

    3. Haz clic en Guardar para aplicar la condición.

    4. Cuando se cierre el panel Editar condición, vuelve a hacer clic en Guardar en el panel Editar permisos para actualizar tu política de permitir.

gcloud

Las políticas de permiso se definen mediante el patrón lectura, modificación y escritura.

Ejecuta el comando gcloud projects get-iam-policy para obtener la política de permisos actual del proyecto. En el siguiente ejemplo, la versión JSON de la política de permiso se descarga en una ruta del disco.

Comando:

gcloud projects get-iam-policy project-id --format=json > filepath

Se descarga el formato JSON de la política de permiso:

{
  "bindings": [
    {
      "members": [
        "user:my-user@example.com"
      ],
      "role": "roles/owner"
    },
    {
      "members": [
        "group:my-group@example.com"
      ],
      "role": "roles/compute.instanceAdmin"
    }
  ],
  "etag": "BwWKmjvelug=",
  "version": 1
}

Para configurar la política de permiso con una condición de prefijo de nombre de recurso, añade la siguiente expresión de condición destacada. La CLI de gcloud actualiza la versión automáticamente:

{
  "bindings": [
    {
      "members": [
        "user:my-user@example.com"
      ],
      "role": "roles/owner"
    },
    {
      "members": [
        "group:my-group@example.com"
      ],
      "role": "roles/compute.instanceAdmin",
      "condition": {
          "title": "PREFIX_only",
          "description": "Only gives access to VMs with the PREFIX prefix",
          "expression":
            "(resource.type == 'compute.googleapis.com/Disk' &&
            resource.name.startsWith('projects/PROJECT_ID/zones/ZONE_ID/disks/PREFIX')) ||
            (resource.type == 'compute.googleapis.com/Instance' &&
            resource.name.startsWith('projects/PROJECT_ID/zones/ZONE_ID/instances/PREFIX')) ||
            (resource.type != 'compute.googleapis.com/Instance' &&
            resource.type != 'compute.googleapis.com/Disk')"
      }
    }
  ],
  "etag": "BwWKmjvelug=",
  "version": 3
}

A continuación, define la nueva política de permiso ejecutando el comando gcloud projects set-iam-policy:

gcloud projects set-iam-policy project-id filepath

La nueva vinculación de rol condicional otorga permisos al grupo de la siguiente manera:

  • Los miembros de la vinculación de roles solo pueden usar los permisos de disco e instancia para acceder a los discos y las instancias cuyos nombres empiecen por el prefijo especificado.
  • Los miembros de la vinculación de roles pueden usar todos los demás permisos del rol Administrador de instancias (roles/compute.instanceAdmin) para acceder a todos los recursos, excepto a los discos y las instancias.

REST

Usa el patrón lectura, modificación y escritura para permitir el acceso a recursos específicos.

Primero, lee la política de permisos del proyecto:

El método projects.getIamPolicy de la API Resource Manager obtiene la política de permisos de un proyecto.

Antes de usar los datos de la solicitud, haz las siguientes sustituciones:

  • PROJECT_ID: tu ID de proyecto. Google Cloud Los IDs de proyecto son cadenas alfanuméricas, como my-project.
  • POLICY_VERSION: la versión de la política que se va a devolver. En las solicitudes se debe especificar la versión de la política más reciente, que es la versión 3. Consulta Especificar una versión de la política al obtener una política para obtener más información.

Método HTTP y URL:

POST https://cloudresourcemanager.googleapis.com/v1/projects/PROJECT_ID:getIamPolicy

Cuerpo JSON de la solicitud:

{
  "options": {
    "requestedPolicyVersion": POLICY_VERSION
  }
}

Para enviar tu solicitud, despliega una de estas opciones:

Deberías recibir una respuesta JSON similar a la siguiente:

{
  "version": 1,
  "etag": "BwWKmjvelug=",
  "bindings": [
    {
      "role": "roles/owner",
      "members": [
        "user:my-user@example.com
      ]
    },
    {
      "members": [
        "group:my-group@example.com"
      ],
      "role": "roles/compute.instanceAdmin"
    }
  ]
}

A continuación, modifica la política de permiso para que permita el acceso a recursos específicos. Asegúrate de cambiar el campo version por el valor 3:

{
  "version": 3,
  "etag": "BwWKmjvelug=",
  "bindings": [
    {
      "role": "roles/owner",
      "members": [
        "user:my-user@example.com"
      ]
    },
    {
      "role": "roles/compute.instanceAdmin",
      "members": [
        "group:my-group@example.com"
      ],
      "condition": {
          "title": "PREFIX_only",
          "description": "Only gives access to VMs with the PREFIX prefix",
          "expression":
            "(resource.type == 'compute.googleapis.com/Disk' &&
            resource.name.startsWith('projects/PROJECT_ID/zones/ZONE_ID/disks/PREFIX')) ||
            (resource.type == 'compute.googleapis.com/Instance' &&
            resource.name.startsWith('projects/PROJECT_ID/zones/ZONE_ID/instances/PREFIX')) ||
            (resource.type != 'compute.googleapis.com/Instance' &&
            resource.type != 'compute.googleapis.com/Disk')"
      }
    }
  ]
}

Por último, escribe la política de permiso actualizada:

El método projects.setIamPolicy de la API Resource Manager define la política de permitidos de la solicitud como la nueva política de permitidos del proyecto.

Antes de usar los datos de la solicitud, haz las siguientes sustituciones:

  • PROJECT_ID: tu ID de proyecto. Google Cloud Los IDs de proyecto son cadenas alfanuméricas, como my-project.

Método HTTP y URL:

POST https://cloudresourcemanager.googleapis.com/v1/projects/PROJECT_ID:setIamPolicy

Cuerpo JSON de la solicitud:

{
  "policy": {
    "version": 3,
    "etag": "BwWKmjvelug=",
    "bindings": [
      {
        "role": "roles/owner",
        "members": [
          "user:my-user@example.com"
        ]
      },
      {
        "role": "roles/compute.instanceAdmin",
        "members": [
          "group:my-group@example.com"
        ],
        "condition": {
          "title": "Dev_access_only",
          "description": "Only access to devAccess* VMs",
          "expression":
            "(resource.type == 'compute.googleapis.com/Disk' &&
            resource.name.startsWith('projects/PROJECT_ID/zones/ZONE_ID/disks/PREFIX')) ||
            (resource.type == 'compute.googleapis.com/Instance' &&
            resource.name.startsWith('projects/PROJECT_ID/zones/ZONE_ID/instances/PREFIX')) ||
            (resource.type != 'compute.googleapis.com/Instance' &&
            resource.type != 'compute.googleapis.com/Disk')"
        }
      }
    ]
  }
}

Para enviar tu solicitud, despliega una de estas opciones:

La respuesta contiene la política de permiso actualizada.


Extraer valores de nombres de recursos

En los ejemplos anteriores se muestran comparaciones booleanas entre el nombre del recurso o el principio del nombre del recurso y otro valor. Sin embargo, en algunos casos, es posible que tengas que comparar un valor con una parte específica del nombre del recurso que no esté al principio del nombre.

Puedes usar la función extract() y especificar una plantilla de extracción para extraer la parte pertinente del nombre del recurso como una cadena. Si es necesario, puedes convertir la cadena extraída a otro tipo, como una marca de tiempo. Después de extraer un valor del nombre del recurso, puede compararlo con otros valores.

En los siguientes ejemplos se muestran expresiones de condición que usan la función extract(). Para obtener información sobre la función extract(), consulta la referencia del atributo de condiciones de gestión de identidades y accesos.

Ejemplo: Coincidir con los pedidos de los últimos 30 días

Supongamos que almacenas información de pedidos en varios segmentos de Cloud Storage y que los objetos de cada segmento están organizados por fecha. Un nombre de objeto típico podría ser similar a este ejemplo:

projects/_/buckets/acme-orders-aaa/objects/data_lake/orders/order_date=2019-11-03/aef87g87ae0876

Quieres permitir que una cuenta principal acceda a cualquier pedido de los últimos 30 días. La siguiente condición coincide con los objetos de Cloud Storage de estos pedidos. Usa las funciones duration() y date() para restar 30 días (2.592.000 segundos) a la hora de la solicitud y, a continuación, compara esa marca de tiempo con la fecha del pedido:

resource.type == 'storage.googleapis.com/Object' &&
  request.time - duration('2592000s') < date(resource.name.extract('/order_date={date_str}/'))

Para obtener información sobre las funciones date() y duration(), consulta la referencia de atributos de fecha y hora.

Ejemplo: coincidencia con VMs de Compute Engine en cualquier ubicación

Supongamos que quieres asignar un rol a nivel de proyecto a una entidad principal para cualquier máquina virtual de Compute Engine cuyo nombre empiece por dev-, independientemente de la ubicación de la máquina virtual. También quiere que la entidad de seguridad pueda usar ese rol en todos los demás tipos de recursos.

El nombre de recurso de una VM tiene un formato similar a projects/PROJECT_ID/zones/ZONE_ID/instances/INSTANCE_ID. La siguiente condición se evalúa como true en las VMs con un nombre de instancia que empieza por la cadena dev- y en todos los tipos de recursos que no sean VMs:

resource.type != 'compute.googleapis.com/Instance' ||
  resource.name.extract('/instances/{name}').startsWith('dev-')

El texto entre llaves identifica la parte del nombre del recurso que se extrae para la comparación. En este ejemplo, la plantilla de extracción extrae los caracteres que haya después de la primera aparición de la cadena /instances/.

Consideraciones importantes sobre el uso de las condiciones basadas en recursos

Al añadir una condición basada en recursos, es importante tener en cuenta cómo afectará la condición a los permisos de la entidad de seguridad.

Roles personalizados

Veamos un ejemplo con roles personalizados. Un administrador quiere crear un rol personalizado que conceda acceso para crear instancias de VM, pero solo permite al usuario crear instancias de VM en un proyecto con un nombre de recurso que empiece por el prefijo staging, usando los discos con el mismo prefijo de nombre.

Para conseguir este objetivo, asegúrate de que el rol concedido contenga los permisos necesarios para crear una instancia de VM, lo que significa que debe tener permisos en los tipos de recursos de disco y de instancia. A continuación, asegúrate de que la expresión de condición compruebe el nombre del recurso de ambos discos e instancias. Además de estos dos tipos, no se conceden otros permisos en el rol.

La siguiente expresión de condición dará lugar a un comportamiento inesperado. Se bloquean los permisos para operar en máquinas virtuales de Compute Engine:

resource.type == 'compute.googleapis.com/Disk' &&
 resource.name.startsWith('projects/PROJECT_ID/zones/ZONE_ID/disks/staging')

La siguiente expresión de condición incluye discos e instancias, y gestionará el acceso en función del nombre de recurso de estos dos tipos:

(resource.type == 'compute.googleapis.com/Disk' &&
  resource.name.startsWith('projects/PROJECT_ID/zones/ZONE_ID/disks/staging')) ||
 (resource.type == 'compute.googleapis.com/Instance' &&
  resource.name.startsWith('projects/PROJECT_ID/zones/ZONE_ID/instances/staging'))

La siguiente expresión de condición incluye discos e instancias, y gestionará el acceso en función del nombre de recurso de estos dos tipos. En el caso de cualquier otro tipo de recurso, la expresión condicional asigna el rol independientemente del nombre del recurso:

(resource.type == 'compute.googleapis.com/Disk' &&
  resource.name.startsWith('projects/PROJECT_ID/zones/ZONE_ID/disks/staging')) ||
 (resource.type == 'compute.googleapis.com/Instance' &&
  resource.name.startsWith('projects/PROJECT_ID/zones/ZONE_ID/instances/staging')) ||
 (resource.type != 'compute.googleapis.com/Disk' &&
  resource.type != 'compute.googleapis.com/Instance')

Permisos solo para padres

En la jerarquía de recursos de Google Cloud, algunos de los permisos de un rol que afectan a un recurso secundario solo se deben aplicar a nivel superior. Por ejemplo, para enumerar los proyectos de una organización, un usuario debe tener el permiso resourcemanager.projects.list en la organización cuyos proyectos quiera enumerar, no en los proyectos en sí. Estos tipos de permisos se denominan permisos solo para padres y solo se aplican a las operaciones de list.

Para conceder acceso correctamente a los permisos de *.*.list al usar condiciones, la expresión de condición debe definir los atributos resource.service y resource.type según el tipo de recurso principal de los recursos de destino que se van a enumerar.

Veamos algunos ejemplos. Si usamos el ejemplo de Compute Engine de la sección anterior, la siguiente expresión impide el acceso a los permisos compute.disks.list y compute.instances.list, ya que el recurso en el que se comprueban estos permisos tiene el valor cloudresourcemanager.googleapis.com/Project del atributo resource.type.

(resource.type == 'compute.googleapis.com/Disk' &&
  resource.name.startsWith('projects/PROJECT_ID/zones/ZONE_ID/disks/PREFIX')) ||
 (resource.type == 'compute.googleapis.com/Instance' &&
  resource.name.startsWith('projects/PROJECT_ID/zones/ZONE_ID/instances/PREFIX'))

Es habitual que estos permisos de list se concedan junto con otros permisos para realizar operaciones normales en el recurso. Para aumentar el ámbito de la concesión en este caso, puedes ampliar el ámbito solo para el tipo cloudresourcemanager.googleapis.com/Project o ampliarlo a todos los demás permisos que no sean de tipo instancia o disco.

(resource.type == 'compute.googleapis.com/Disk' &&
  resource.name.startsWith('projects/PROJECT_ID/zones/ZONE_ID/disks/PREFIX')) ||
 (resource.type == 'compute.googleapis.com/Instance' &&
  resource.name.startsWith('projects/PROJECT_ID/zones/ZONE_ID/instances/PREFIX')) ||
 resource.type == 'cloudresourcemanager.googleapis.com/Project'

o

(resource.type == 'compute.googleapis.com/Disk' &&
  resource.name.startsWith('projects/PROJECT_ID/zones/ZONE_ID/disks/PREFIX')) ||
 (resource.type == 'compute.googleapis.com/Instance' &&
  resource.name.startsWith('projects/PROJECT_ID/zones/ZONE_ID/instances/PREFIX')) ||
 (resource.type != 'compute.googleapis.com/Disk' &&
  resource.type != 'compute.googleapis.com/Instance')