> ## 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.

# Escrever políticas

> O formato do documento de política, cada operador de condição e exemplos de trabalho para começar.

Uma política é um documento JSON de instruções. Cada instrução diz se um **efeito** se aplica a um conjunto de **ações** em um conjunto de **recursos**, opcionalmente limitado por **condições**.

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

`version` é sempre `2024-01-01`. Qualquer outra coisa é rejeitada.

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

## Escolha o escopo da política

As políticas de conta pertencem a uma conta e são anexadas às suas funções e contas de serviço. Eles concedem ações de serviço de conta. As políticas da organização pertencem ao espaço de trabalho e concedem `workspace:*`, `billing:*`, `quota:*` e `audit:*`. Anexe-os a usuários ou grupos ou delege-os explicitamente a uma função de conta ou conta de serviço.

O formato do documento é compartilhado, mas os domínios de permissão são separados. `actions: ["*"]` e exclusões de ação se aplicam somente dentro do domínio da política. Uma política de administrador de conta não pode conceder acesso à organização. Uma política de organização não pode conceder acesso a recursos de conta ordinários.

O editor visual do console oferece serviços apropriados ao escopo selecionado. A edição de JSON usa as mesmas regras; escrever uma ação do outro escopo não a torna eficaz.

<a id="statements" />

## Declarações

<ResponseField name="sid" type="string, optional">
  Uma etiqueta para seu próprio uso. Não tem efeito sobre a avaliação.
</ResponseField>

<ResponseField name="effect" type="allow | deny" required>
  Em minúsculas. Um `deny` explícito vence qualquer `allow` no domínio da política sendo avaliado.
</ResponseField>

<ResponseField name="actions / not_actions" type="array" required>
  Exatamente um do par. A definição de ambos ou nenhum deles é rejeitada quando o documento é salvo.
</ResponseField>

<ResponseField name="resources / not_resources" type="array" required>
  Exatamente um do par, mesma regra.
</ResponseField>

<ResponseField name="conditions" type="array, optional">
  Todos eles devem ser mantidos para que a declaração se aplique.
</ResponseField>

<a id="actions" />

### Acções

As ações são `service:Action`, e `*` é o único curinga.

```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

Os recursos são [CRNs](/pt/iam#resource-names), com `*` como único curinga. O layout de dois pontos e barra é comparado literalmente, então a forma tem que estar certa:

```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>
  Alguns recursos são nomeados em vez de UUID-chave, o que torna uma convenção de nomeação diretamente passível de política: `crn:certificate::my-account:certificate/prod-*`.
</Tip>

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

### Nomeação por exclusão

`not_actions` e `not_resources` cobrem tudo **exceto** o que eles listam.

<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` com `effect: allow` concede todas as ações que os padrões não nomeiam — **incluindo ações que ainda não existem**, adicionadas por serviços enviados após a política ter sido escrita. Emparelhar exclusão com `deny` cria um buraco em um amplo allow e não tem tal surpresa. Prefiro isso.
</Warning>

<a id="conditions" />

## Condições

Uma condição compara uma **chave de contexto** com **valores** usando um **operador**. Cada condição em uma declaração deve ser mantida para que ela 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 rede | Mantém quando |
| - | - |
| `equals` / `not_equals` | O valor corresponde / não corresponde a nenhum valor listado |
| `starts_with` / `ends_with` / `contains` | Comparação de substring |
| `in` / `not_in` | Associação na lista |
| `greater_than` / `less_than` | Comparação numérica |
| `greater_than_or_equals` / `less_than_or_equals` | Comparação numérica, inclusive |
| `exists` / `not_exists` | A chave está presente / ausente |
| `ip_address` / `not_ip_address` | O endereço está dentro / fora dos CIDRs listados |

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

### O que acontece quando a chave está faltando

Esta é a parte que decide se um corrimão funciona, por isso vale a pena ser preciso.

<Warning>
  Uma condição cuja chave de contexto está **ausente da solicitação** falha — *exceto* para os operadores negados, que mantêm.

  `not_equals`, `not_in`, `not_ip_address` e `not_exists` são satisfeitos por uma requisição que não carrega a chave em tudo. Todo outro operador afirma algo positivo sobre um valor que não está lá, então ele falha fechado.
</Warning>

A razão é que um deny precisa disparar na requisição que ele está protegendo. "Negar a menos que a solicitação venha desses endereços" tem que pegar uma solicitação sem endereço - tratar a chave faltante como *sem correspondência* faria com que o guardrail falhasse em abrir exatamente quando importa.

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

### Chaves de múltiplos valores

Algumas chaves de contexto são **conjuntos** em vez de valores únicos — `basalt:TagKeys` é o conjunto de chaves de tag que uma requisição carrega. Para comparar com um, adicione um `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`** é válido quando *cada* membro do conjunto de solicitações satisfaz o operador. Um conjunto ausente ou vazio é mantido **vacuously** — uma requisição que não possui tags não é cercada por uma restrição de tag-chave.
* **`for_any_value`** é válido quando *pelo menos um* membro é válido. Um conjunto ausente ou vazio **não** se mantém.

<a id="context-keys" />

### Chaves de contexto

| Chave | Carries |
| - | - |
| `basalt:SourceIp` | O endereço de onde veio a solicitação. Fornecido em cada pedido. |
| `basalt:RequestTag/<key>` | O valor de uma tag **que está sendo definida** por esta solicitação. |
| `basalt:ResourceTag/<key>` | O valor de uma tag **já presente** no recurso. |
| `basalt:TagKeys` | O conjunto de chaves de tag que a solicitação carrega. Multi-valor. |

Os dois prefixos de tag respondem a perguntas diferentes. `ResourceTag` cerca o acesso a coisas já rotuladas de uma certa maneira; `RequestTag` cerca o que um chamador tem permissão para rotular algo *como*.

<a id="worked-examples" />

## Exemplos de trabalhos

<AccordionGroup>
  <Accordion title="Somente leitura em um serviço" 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="Limitar uma equipe a um ambiente por tag" icon="tag">
    Alcança apenas recursos já marcados como `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>
      Isso não concede nada em um recurso **sem tag**: `equals` em uma chave ausente falha. Isso é geralmente o que você quer — um recurso sem rótulo não está silenciosamente no escopo.
    </Note>
  </Accordion>

  <Accordion title="Forçar novos recursos a serem rotulados corretamente" icon="pencil">
    Um chamador pode criar instâncias apenas enquanto as marca `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 uma rede de escritório e faça isso de verdade" 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 um **deny** com o operador **negated**, então ele também dispara em uma requisição que não carrega nenhum endereço de origem. O inverso — allow when `ip_address` matches — deixa a cerca desligada sempre que a chave estiver ausente.
  </Accordion>

  <Accordion title="Um corrimão que sobrevive a grandes subsídios" 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-*"]
      }]
    }
    ```

    Anexe-o em qualquer lugar no conjunto do principal. Uma negação explícita não é substituída por uma permissão de administrador.
  </Accordion>

  <Accordion title="Permitir que um agente de plano de dados leia a chave de um 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` é uma ação separada da leitura de um certificado, precisamente para que isso possa ser concedido de forma restrita. Veja [certificates](/pt/certificates/material).
  </Accordion>
</AccordionGroup>

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

## Políticas gerenciadas e inline

<Columns cols={2}>
  <Card title="Política de gestão" icon="library">
    Um objeto autônomo com seu próprio CRN. As políticas de conta são anexadas a funções e contas de serviço; as políticas de organização também são anexadas a usuários e grupos. Edite uma vez e todos os anexos usam o documento atualizado.
  </Card>

  <Card title="Política em linha" icon="paperclip">
    Escrita diretamente em um principal, nomeado em vez de identificado, e apagada com ele. Para uma subvenção única que nunca deve ser reutilizada ou acidentalmente anexada em outro lugar.
  </Card>
</Columns>

Uma política gerenciada de conta é criada em `iam.basaltic.sh`. As políticas da organização usam o mesmo caminho de coleta em `workspace.basaltic.sh`:

<Tabs>
  <Tab title="Console">
    Abra **Identity & access** → **Policies** e escolha **Create Policy** para uma política de conta. Use **Organization** → **Organization policies** para uma política da organização. **Policy Document** suporta edição visual e JSON. Anexe a política salva da página de identidade apropriada.
  </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` recebe o JSON inline ou `@file`; `--from-file` envia o corpo inteiro da requisição.
  </Tab>

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

Políticas em linha vivem sob o principal. Este exemplo de usuário usa o Workspace e um documento de política da organização:

<Tabs>
  <Tab title="Console">
    Cada usuário, grupo, conta de serviço e função tem um cartão **Inline Policies** com **Add Inline Policy** — um editor JSON de **Name** e **Policy Document**. O nome identifica a política, por isso é fixado uma vez salva e a edição altera apenas o 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>
    ```

    Conta `iam service-account` e `iam role`, e organização `workspace group`, carregam operações equivalentes de política inline.
  </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>

As rotas de usuário e grupo usam documentos de política de organização e espaço de trabalho. As rotas de conta e função de serviço usam documentos de política de conta e IAM.

Algumas políticas gerenciadas são políticas **system**, marcadas como `is_system`. Eles são mantidos pela plataforma, compartilhados entre as organizações e não podem ser editados, seja anexados ou não. O console os identifica como **System** em vez de **Custom** e os abre como **View Policy**, sem salvar.

<a id="validation" />

## Validação

Um documento é rejeitado ao salvar, não ignorado silenciosamente, quando:

* `version` está ausente ou não é `2024-01-01`
* `statements` está vazio
* `effect` não é `allow` ou `deny`
* uma declaração define tanto `actions` e `not_actions`, ou nenhuma
* uma instrução define tanto `resources` e `not_resources`, ou nenhum
* uma condição não tem `key`, ou um `operator` ou `set_operator` não reconhecido

<Note>
  Um operador não reconhecido em um documento **armazenado** — um salvo antes de um operador ser renomeado, por exemplo — nunca corresponde. Em uma instrução allow, ela é ignorada; em uma deny, ela é tratada como uma hard deny quando a ação e o recurso coincidem, então um guardrail quebrado falha fechado em vez de aberto.
</Note>

<a id="next" />

## Próximo

<CardGroup cols={2}>
  <Card title="Limites de permissão" icon="shield" href="/pt/iam/permission-boundaries">
    Limitar o que essas políticas podem conceder.
  </Card>

  <Card title="Funções e credenciais" icon="key-round" href="/pt/iam/roles">
    As políticas de sessão restringem as credenciais da mesma forma.
  </Card>
</CardGroup>

<a id="resource-references" />

## Referências de recursos

Os nomes de política, função e grupo são imutáveis. Campos de relacionamento como `policy`, `role`, `group` e `groups[]` aceitam um UUID, um nome ou um CRN. A sintaxe seleciona a pesquisa; um recurso ausente nunca aciona uma segunda pesquisa usando outra interpretação.

As políticas de conta usam `crn:iam::<account-handle>:policy/<name>`. As políticas de conta do sistema usam `crn:iam:::policy/<Name>`. Um nome nu prefere uma política na conta selecionada, em seguida, uma política do sistema. Um CRN de sistema totalmente qualificado seleciona esse namespace mesmo quando uma política personalizada tem o mesmo nome.

Políticas de organização usam `crn:workspace:::policy/<name>`; políticas de organização de sistema usam `crn:workspace:::system-policy/<Name>`. Uma pesquisa de política da organização não pesquisa políticas de conta, ou vice-versa.

Funções usam `crn:iam::<account-handle>:role/<name>`. Os grupos usam `crn:workspace:::group/<name>`. As solicitações de anexo de política de organização delegada usam o UUID da política em `policy_id`; consulte [Permissões de espaço de trabalho](/pt/workspace/permissions).

Listas com filtros `name` e `crn` aplicam-se ambos antes da paginação. Um valor vazio ainda é um filtro. Um CRN estrangeiro ou não correspondido retorna uma página vazia. Veja [resource references](/pt/reference-resolution) para os filtros de cada lista.


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