> ## Documentation Index
> Fetch the complete documentation index at: https://docs.basaltic.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Escribir políticas

> El formato del documento de política, cada operador de condición y ejemplos de trabajo para comenzar.

Una política es un documento JSON de declaraciones. Cada declaración dice si un **effect** se aplica a un conjunto de **acciones** en un conjunto de **recursos**, opcionalmente controlado por **condiciones**.

```json theme={null}
{
  "version": "2024-01-01",
  "statements": [
    {
      "sid": "ReadInstances",
      "effect": "allow",
      "actions": ["compute:ListInstances", "compute:GetInstance"],
      "resources": ["crn:compute:*:my-account:instance/*"]
    }
  ]
}
```

`version` es siempre `2024-01-01`. Cualquier otra cosa es rechazada.

<a id="choose-the-policy-scope" />

## Elegir el alcance de la política

Las directivas de cuenta pertenecen a una cuenta y se adjuntan a sus roles y cuentas de servicio. Conceden acciones de servicio de cuenta. Las políticas de organización pertenecen a Workspace y otorgan `workspace:*`, `billing:*`, `quota:*` y `audit:*`. Adjúntalos a usuarios o grupos, o delégalos explícitamente a un rol de cuenta o cuenta de servicio.

El formato del documento se comparte, pero los dominios de permisos son separados. Las exclusiones de `actions: ["*"]` y de acciones se aplican solo dentro del dominio de la política. Una directiva de administrador de cuenta no puede conceder acceso de organización. Una directiva de organización no puede conceder acceso a recursos de cuenta ordinarios.

El editor visual de la consola ofrece servicios apropiados para el ámbito seleccionado. La edición de JSON utiliza las mismas reglas; escribir una acción desde el otro ámbito no la hace efectiva.

<a id="statements" />

## Declaraciones

<ResponseField name="sid" type="string, optional">
  Una etiqueta para su propio uso. No tiene efecto sobre la evaluación.
</ResponseField>

<ResponseField name="effect" type="allow | deny" required>
  Minúsculas. Un `deny` explícito supera a cualquier `allow` en el dominio de la política que se está evaluando.
</ResponseField>

<ResponseField name="actions / not_actions" type="array" required>
  Exactamente uno de la pareja. Si se establecen ambos o ninguno, se rechaza al guardar el documento.
</ResponseField>

<ResponseField name="resources / not_resources" type="array" required>
  Exactamente uno del par, misma regla.
</ResponseField>

<ResponseField name="conditions" type="array, optional">
  Todos ellos deben mantenerse para que la declaración se aplique.
</ResponseField>

<a id="actions" />

### Medidas

Las acciones son `service:Action`, y `*` es el único comodín.

```json theme={null}
"actions": ["compute:GetInstance"]        // one action
"actions": ["compute:*"]                  // every compute action
"actions": ["compute:List*", "compute:Get*"]  // reads, by convention
"actions": ["*"]                          // everything
```

<a id="resources" />

### Recursos

Los recursos son [CRNs](/es/iam#resource-names), con `*` como único comodín. El diseño de los dos puntos y la barra se compara literalmente, por lo que la forma tiene que ser correcta:

```json theme={null}
"resources": ["crn:compute:sa-saopaulo-1:my-account:instance/*"]
"resources": ["crn:compute:*:my-account:instance/*"]        // any region
"resources": ["crn:dns::my-account:zone/example.com"]       // global: empty region
"resources": ["crn:workspace:::user/*"]                           // org-scoped: both empty
"resources": ["*"]                                          // anything
```

<Tip>
  Algunos recursos son nombrados en lugar de UUID-clave, lo que hace que una convención de nombres sea directamente política-capacitada: `crn:certificate::my-account:certificate/prod-*`.
</Tip>

<a id="naming-by-exclusion" />

### Nombramiento por exclusión

`not_actions` y `not_resources` cubren todo **excepto** lo que enumeran.

<CodeGroup>
  ```json Deny — carve a hole (safe) theme={null}
  {
    "sid": "NothingOutsideMyAccount",
    "effect": "deny",
    "actions": ["*"],
    "not_resources": ["crn:compute:*:my-account:*"]
  }
  ```

  ```json Allow — grants the future (careful) theme={null}
  {
    "sid": "EverythingButIAM",
    "effect": "allow",
    "not_actions": ["iam:*"],
    "resources": ["*"]
  }
  ```
</CodeGroup>

<Warning>
  `not_actions` con `effect: allow` concede todas las acciones que los patrones no nombran — **incluyendo acciones que aún no existen**, añadidas por servicios enviados después de que la política fue escrita. Emparejar exclusión con `deny` hace un agujero en un amplio allow y no tiene tal sorpresa. Prefiero eso.
</Warning>

<a id="conditions" />

## Condiciones

Una condición compara una **clave de contexto** con **valores** usando un **operador**. Cada condición en una declaración debe mantenerse para que se aplique.

```json theme={null}
{
  "effect": "allow",
  "actions": ["compute:*"],
  "resources": ["*"],
  "conditions": [
    { "operator": "ip_address", "key": "basalt:SourceIp", "values": ["203.0.113.0/24"] }
  ]
}
```

<a id="operators" />

### Operadores

| Operador de línea | Se mantiene cuando |
| - | - |
| `equals` / `not_equals` | El valor coincide / no coincide con ningún valor listado |
| `starts_with` / `ends_with` / `contains` | Comparación de subcadenas |
| `in` / `not_in` | Miembros de la lista |
| `greater_than` / `less_than` | Comparación numérica |
| `greater_than_or_equals` / `less_than_or_equals` | Comparación numérica, inclusive |
| `exists` / `not_exists` | La clave está presente / ausente |
| `ip_address` / `not_ip_address` | La dirección cae dentro / fuera de los CIDRs listados |

<a id="what-happens-when-the-key-is-missing" />

### Qué sucede cuando falta la llave

Esta es la parte que decide si una barandilla funciona, por lo que vale la pena ser preciso.

<Warning>
  Una condición cuya clave de contexto esté **ausente de la solicitud** fallará, *excepto* para los operadores negados, que se mantienen.

  `not_equals`, `not_in`, `not_ip_address` y `not_exists` son satisfechos por una petición que no lleva la clave en absoluto. Cada otro operador afirma algo positivo sobre un valor que no está allí, por lo que falla cerrado.
</Warning>

La razón es que un deny necesita disparar en la petición contra la que está protegiendo. "Denial unless the request comes from these addresses" tiene que capturar una solicitud sin dirección — tratar la clave faltante como *no match* haría que la barandilla fallara al abrirse exactamente cuando importa.

<a id="multi-valued-keys" />

### Claves de valores múltiples

Algunas claves de contexto son **conjuntos** en lugar de valores individuales — `basalt:TagKeys` es el conjunto de claves de etiqueta que lleva una solicitud. Para comparar con uno, añada un `set_operator`:

<CodeGroup>
  ```json for_all_values theme={null}
  {
    "sid": "OnlyApprovedTagKeys",
    "effect": "deny",
    "actions": ["*"],
    "resources": ["*"],
    "conditions": [{
      "operator": "not_in",
      "set_operator": "for_all_values",
      "key": "basalt:TagKeys",
      "values": ["env", "owner", "cost-center"]
    }]
  }
  ```

  ```json for_any_value theme={null}
  {
    "sid": "MustCarryEnvTag",
    "effect": "allow",
    "actions": ["compute:CreateInstance"],
    "resources": ["*"],
    "conditions": [{
      "operator": "equals",
      "set_operator": "for_any_value",
      "key": "basalt:TagKeys",
      "values": ["env"]
    }]
  }
  ```
</CodeGroup>

* **`for_all_values`** se mantiene cuando *cada* miembro del conjunto de peticiones satisface al operador. Un conjunto ausente o vacío se mantiene **vacíamente** — una petición que no lleva etiquetas no está cercada por una restricción de clave de etiqueta.
* **`for_any_value`** se mantiene cuando *al menos* uno de los miembros lo hace. Un conjunto ausente o vacío **no** se mantiene.

<a id="context-keys" />

### Teclas de contexto

| Clave | Carries |
| - | - |
| `basalt:SourceIp` | La dirección de la que proviene la solicitud. Suministrado en cada solicitud. |
| `basalt:RequestTag/<key>` | El valor de una etiqueta **que se establece** por esta solicitud. |
| `basalt:ResourceTag/<key>` | El valor de una etiqueta **ya presente** en el recurso. |
| `basalt:TagKeys` | El conjunto de claves de etiqueta que lleva la solicitud. Multivalor. |

Los dos prefijos de etiqueta responden a preguntas diferentes. `ResourceTag` cerca el acceso a cosas ya etiquetadas de cierta manera; `RequestTag` cerca lo que un llamador puede etiquetar algo *como*.

<a id="worked-examples" />

## Ejemplos de trabajo

<AccordionGroup>
  <Accordion title="Solo lectura en un servicio" icon="eye">
    ```json theme={null}
    {
      "version": "2024-01-01",
      "statements": [{
        "sid": "ReadOnlyCompute",
        "effect": "allow",
        "actions": ["compute:List*", "compute:Get*", "compute:Describe*"],
        "resources": ["*"]
      }]
    }
    ```
  </Accordion>

  <Accordion title="Confina un equipo a un entorno por etiqueta" icon="tag">
    Solo alcanza los recursos ya etiquetados `env=staging`:

    ```json theme={null}
    {
      "version": "2024-01-01",
      "statements": [{
        "sid": "StagingOnly",
        "effect": "allow",
        "actions": ["compute:*", "storage:*"],
        "resources": ["*"],
        "conditions": [
          { "operator": "equals", "key": "basalt:ResourceTag/env", "values": ["staging"] }
        ]
      }]
    }
    ```

    <Note>
      Esto no otorga nada en un recurso **no etiquetado**: `equals` en una clave faltante falla. Eso es lo que normalmente quieres: un recurso sin etiquetar no está silenciosamente en el ámbito.
    </Note>
  </Accordion>

  <Accordion title="Forzar que los nuevos recursos se etiqueten correctamente" icon="pencil">
    Un llamador puede crear instancias solo mientras las etiqueta `env=staging`:

    ```json theme={null}
    {
      "version": "2024-01-01",
      "statements": [{
        "sid": "CreateOnlyAsStaging",
        "effect": "allow",
        "actions": ["compute:CreateInstance"],
        "resources": ["*"],
        "conditions": [
          { "operator": "equals", "key": "basalt:RequestTag/env", "values": ["staging"] }
        ]
      }]
    }
    ```
  </Accordion>

  <Accordion title="Cerce una red de oficina, y sea sincero" icon="network">
    ```json theme={null}
    {
      "version": "2024-01-01",
      "statements": [{
        "sid": "DenyOffNetwork",
        "effect": "deny",
        "actions": ["*"],
        "resources": ["*"],
        "conditions": [
          { "operator": "not_ip_address", "key": "basalt:SourceIp", "values": ["203.0.113.0/24"] }
        ]
      }]
    }
    ```

    Escrito como un **deny** con el operador **negated**, por lo que también se dispara en una solicitud que no lleva ninguna dirección de origen. El inverso — permit when `ip_address` matches — deja la valla apagada siempre que la clave esté ausente.
  </Accordion>

  <Accordion title="Una barandilla que sobrevive a las amplias subvenciones" icon="shield">
    ```json theme={null}
    {
      "version": "2024-01-01",
      "statements": [{
        "sid": "NeverTouchProdCerts",
        "effect": "deny",
        "actions": ["certificate:DeleteCertificate", "certificate:RevokeCertificate"],
        "resources": ["crn:certificate::my-account:certificate/prod-*"]
      }]
    }
    ```

    Adjúntalo en cualquier lugar del conjunto del director. Un deny explícito no es anulado por un Administrator allow.
  </Accordion>

  <Accordion title="Permitir que un agente de plano de datos lea la clave de un certificado" icon="key">
    ```json theme={null}
    {
      "version": "2024-01-01",
      "statements": [{
        "sid": "MaterialForEdge",
        "effect": "allow",
        "actions": ["certificate:GetCertificateMaterial"],
        "resources": ["crn:certificate::my-account:certificate/edge-*"]
      }]
    }
    ```

    `GetCertificateMaterial` es una acción separada de la lectura de un certificado, precisamente por lo que esto puede ser concedido estrechamente. Véase [certificates](/es/certificates/material).
  </Accordion>
</AccordionGroup>

<a id="managed-and-inline-policies" />

## Políticas administradas e integradas

<Columns cols={2}>
  <Card title="Política gestionada" icon="library">
    Un objeto independiente con su propio CRN. Las directivas de cuenta se adjuntan a roles y cuentas de servicio; las directivas de organización también se adjuntan a usuarios y grupos. Edite una vez y todos los archivos adjuntos usarán el documento actualizado.
  </Card>

  <Card title="Política en línea" icon="paperclip">
    Escrito directamente sobre un principal, nombrado en lugar de identificado, y borrado con él. Para una subvención única que nunca debe ser reutilizada o accidentalmente adjuntada en otro lugar.
  </Card>
</Columns>

Se crea una política administrada por cuenta en `iam.basaltic.sh`. Las políticas de la organización usan la misma ruta de colección en `workspace.basaltic.sh`:

<Tabs>
  <Tab title="Console">
    Abra **Identity & access** → **Policies** y elija **Create Policy** para una política de cuenta. Utilice **Organization** → **Organization policies** para una directiva de organización. **Policy Document** admite edición visual y JSON. Adjunte la política guardada desde la página de identidad correspondiente.
  </Tab>

  <Tab title="API">
    ```bash theme={null}
    POST /v1/policies
    { "name": "S3ReadOnly", "document": { "version": "2024-01-01", "statements": [...] } }
    ```
  </Tab>

  <Tab title="CLI">
    ```bash theme={null}
    basaltic iam policy create --name S3ReadOnly --document @policy.json
    ```

    `--document` toma el JSON inline o `@file`; `--from-file` envía el cuerpo completo de la solicitud en su lugar.
  </Tab>

  <Tab title="Go">
    ```go theme={null}
    p, err := iam.New(cfg).CreatePolicy(ctx, &iam.PolicyCreateRequest{
        Name:     "S3ReadOnly",
        Document: doc,
    })
    ```
  </Tab>
</Tabs>

Las pólizas en línea viven bajo el principal. Este ejemplo de usuario utiliza Workspace y un documento de directiva de organización:

<Tabs>
  <Tab title="Console">
    Cada usuario, grupo, cuenta de servicio y rol tiene una tarjeta **Inline Policies** con **Add Inline Policy**, un **Name** y un editor JSON de **Policy Document**. El nombre identifica la política, por lo que se fija una vez guardada y al editarla solo cambia el documento.
  </Tab>

  <Tab title="API">
    ```bash theme={null}
    PUT    /v1/users/{user_id}/inline-policies/{policy_name}
    GET    /v1/users/{user_id}/inline-policies
    DELETE /v1/users/{user_id}/inline-policies/{policy_name}
    ```
  </Tab>

  <Tab title="CLI">
    ```bash theme={null}
    basaltic workspace user set-inline-policy <user-id> <policy-name> \
      --document @policy.json
    basaltic workspace user list-inline-policies <user-id>
    basaltic workspace user delete-inline-policy <user-id> <policy-name>
    ```

    La cuenta `iam service-account` y `iam role`, y la organización `workspace group`, llevan operaciones de directiva en línea equivalentes.
  </Tab>

  <Tab title="Go">
    ```go theme={null}
    c := workspace.New(cfg)
    err := c.PutUserInlinePolicy(ctx, userID, "deny-billing-change", &workspace.PutInlinePolicyRequest{
        Document: doc,
    })
    list, err := c.ListUserInlinePolicies(ctx, userID)
    err = c.DeleteUserInlinePolicy(ctx, userID, "deny-billing-change")
    ```
  </Tab>
</Tabs>

Las rutas de usuario y grupo usan documentos de directivas de espacio de trabajo y organización. Las rutas de cuentas de servicio y roles usan documentos de directivas de cuentas y IAM.

Algunas políticas administradas son políticas **sistema**, marcadas como `is_system`. La plataforma los mantiene, se comparten entre las organizaciones y no se pueden editar, ya sea que los adjuntes o no. La consola los etiqueta como **System** en lugar de **Custom** y los abre como **View Policy**, sin guardar.

<a id="validation" />

## Validación

Un documento es rechazado al guardar, no ignorado silenciosamente, cuando:

* `version` falta o no es `2024-01-01`
* `statements` está vacío
* `effect` no es `allow` o `deny`
* Una sentencia establece tanto `actions` como `not_actions`, o ninguna de ellas
* Una sentencia establece tanto `resources` como `not_resources`, o ninguno de los dos
* Una condición no tiene `key`, o un `operator` o `set_operator` no reconocido

<Note>
  Un operador no reconocido en un documento **almacenado** — uno guardado antes de que un operador fuera renombrado, por ejemplo — nunca coincide. En una sentencia allow se salta; en una deny se trata como una deny dura cuando la acción y el recurso coinciden, por lo que una barandilla rota falla cerrada en lugar de abierta.
</Note>

<a id="next" />

## Siguiente

<CardGroup cols={2}>
  <Card title="Límites de permisos" icon="shield" href="/es/iam/permission-boundaries">
    Limitar lo que estas políticas pueden conceder.
  </Card>

  <Card title="Roles y credenciales" icon="key-round" href="/es/iam/roles">
    Las directivas de sesión reducen el ámbito de las credenciales de la misma manera.
  </Card>
</CardGroup>

<a id="resource-references" />

## Referencias de recursos

Los nombres de directiva, rol y grupo son inmutables. Los campos de relación como `policy`, `role`, `group` y `groups[]` aceptan un UUID, un nombre o un CRN. La sintaxis selecciona la búsqueda; un recurso que falta nunca desencadena una segunda búsqueda usando otra interpretación.

Las directivas de cuenta usan `crn:iam::<account-handle>:policy/<name>`. Las políticas de cuenta del sistema usan `crn:iam:::policy/<Name>`. Un nombre nulo prefiere una directiva en la cuenta seleccionada, luego una directiva del sistema. Un CRN de sistema totalmente cualificado selecciona ese espacio de nombres incluso cuando una directiva personalizada tiene el mismo nombre.

Las directivas de organización usan `crn:workspace:::policy/<name>`; las directivas de organización del sistema usan `crn:workspace:::system-policy/<Name>`. Una búsqueda de directiva de organización no busca directivas de cuenta, ni viceversa.

Los roles usan `crn:iam::<account-handle>:role/<name>`. Los grupos usan `crn:workspace:::group/<name>`. Las solicitudes de adjuntos de directivas de organización delegadas usan el UUID de la directiva en `policy_id`; consulte [Permisos de espacio de trabajo](/es/workspace/permissions).

Las listas con filtros `name` y `crn` se aplican antes de la paginación. Un valor vacío sigue siendo un filtro. Un CRN extranjero o no coincidente devuelve una página vacía. Vea [resource references](/es/reference-resolution) para los filtros de cada lista.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.