Pular para o conteúdo principal

Acesso Restrito a Buckets no Storin (Somente Escrita e Somente Leitura)

aviso

⚠️ Todas as configurações deste manual são exemplos. Adapte nomes de buckets, perfis e User IDs conforme o seu ambiente.

📌 Visão Geral​

Este guia mostra como compartilhar um bucket do Storin com acessos restritos, por exemplo:

  • uma credencial que só envia arquivos (write-only), útil para aplicações que fazem upload de backups ou logs;
  • uma credencial que só lê e lista arquivos (read-only), útil para auditoria, consulta ou processamento.

O controle é feito por Bucket Policy.

Outras ferramentas

Os exemplos deste guia usam a AWS CLI, mas o mesmo procedimento pode ser feito via API S3, MinIO Client (mc) ou qualquer outra ferramenta compatível com S3. A Bucket Policy (JSON) é a mesma; muda apenas o comando usado para aplicá-la.


🧠 Como o Storin aplica as permissões​

No Storin, as permissões não são aplicadas pela Access Key ou Secret Key individualmente. Elas são aplicadas pelo User ID (identidade S3) ao qual a credencial pertence.

Na prática:

  • Cada projeto do painel possui uma identidade S3, com um User ID próprio.
  • Todas as Access Keys geradas dentro do mesmo projeto usam o mesmo User ID e, portanto, têm exatamente as mesmas permissões.
  • As chaves servem apenas para autenticar a identidade. Quem define o que pode ou não ser feito é o User ID referenciado na policy.
informação

Para ter perfis de acesso diferentes (dono, somente escrita, somente leitura), cada perfil precisa de um User ID diferente, ou seja, um projeto diferente.

Gerar uma nova Access Key/Secret Key no mesmo projeto não cria uma nova identidade.

Exemplo de estrutura​

ProjetoUser IDUso
Projeto principalUSER_OWNERProprietário do bucket
Projeto WriterUSER_WRITERSomente escrita
Projeto ReaderUSER_READERSomente leitura

A Bucket Policy é configurada no bucket do Projeto principal, referenciando USER_WRITER e USER_READER.


🧰 Pré-requisitos​

  • Um bucket já criado no projeto principal (o dono do bucket).
  • Uma ferramenta compatível com S3. Neste guia usamos a AWS CLI; caso ainda não tenha configurado, siga o guia Configurando a AWS CLI com o Storin.
  • jq instalado (opcional, usado para validar o JSON da policy antes de aplicar).

🆔 Parte 1 – Criando as identidades (User IDs)​

Repita os passos abaixo uma vez para cada perfil restrito (um projeto para o Writer e outro para o Reader).

Passo 1 – Criar um novo projeto​

No painel, crie um novo projeto. Ele pode estar na mesma conta ou em uma conta diferente da que contém o bucket.

Criando um novo projeto

Passo 2 – Inicializar a identidade S3​

A identidade S3 do projeto é gerada no primeiro uso do Object Storage. Para inicializá-la, crie um bucket temporário nesse projeto e, em seguida, apague-o.

Criando bucket temporário

dica

O bucket temporário serve apenas para gerar a identidade. Ele pode ser excluído logo depois, sem impacto no User ID.

Passo 3 – Copiar o User ID​

Acesse a aba Acessos do projeto e copie o User ID exibido.

Aba Acessos com o User ID

Passo 4 – Gerar a Access Key e Secret Key​

Ainda na aba Acessos, gere a Access Key e a Secret Key desse projeto e guarde-as em local seguro. Elas serão usadas pela aplicação ou pessoa que terá o acesso restrito.

Gerando Access Key e Secret Key

perigo

A Secret Key é exibida apenas no momento da criação. Guarde-a imediatamente em um local seguro, como um cofre de senhas.

Ao final desta parte, você terá:

PerfilUser IDCredenciais
Writer<WRITER_ID>Access Key + Secret Key
Reader<READER_ID>Access Key + Secret Key

⚙️ Parte 2 – Configurando a AWS CLI​

Configure um perfil para cada identidade (dono, writer e reader).

Arquivo ~/.aws/config​

[profile storin-owner]
region = sp1
output = json
request_checksum_calculation = when_required
response_checksum_validation = when_required
endpoint_url = https://sp1-s3.saveincloud.io

[profile storin-writer]
region = sp1
output = json
request_checksum_calculation = when_required
response_checksum_validation = when_required
endpoint_url = https://sp1-s3.saveincloud.io

[profile storin-reader]
region = sp1
output = json
request_checksum_calculation = when_required
response_checksum_validation = when_required
endpoint_url = https://sp1-s3.saveincloud.io

Arquivo ~/.aws/credentials​

[storin-owner]
aws_access_key_id = <ACCESS_KEY_OWNER>
aws_secret_access_key = <SECRET_KEY_OWNER>

[storin-writer]
aws_access_key_id = <ACCESS_KEY_WRITER>
aws_secret_access_key = <SECRET_KEY_WRITER>

[storin-reader]
aws_access_key_id = <ACCESS_KEY_READER>
aws_secret_access_key = <SECRET_KEY_READER>
aviso

As linhas request_checksum_calculation e response_checksum_validation são obrigatórias na AWS CLI 2.25 ou superior. Sem elas, todo upload falha com ValidationError.

informação

Ajuste o endpoint_url conforme a região do seu bucket (por exemplo, https://sp1-s3.saveincloud.io ou https://bsb1-s3.saveincloud.io).


📝 Parte 3 – Criando e aplicando a Bucket Policy​

Passo 1 – Criar o arquivo da policy​

Crie um arquivo chamado policy.json com o conteúdo abaixo:

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowWrite",
"Effect": "Allow",
"Principal": { "CanonicalUser": "<WRITER_ID>" },
"Action": [
"s3:PutObject",
"s3:AbortMultipartUpload",
"s3:ListMultipartUploadParts"
],
"Resource": "arn:aws:s3:::<BUCKET>/*"
},
{
"Sid": "DenyReadForWriter",
"Effect": "Deny",
"Principal": { "CanonicalUser": "<WRITER_ID>" },
"Action": [
"s3:GetObject",
"s3:GetObjectVersion",
"s3:DeleteObject",
"s3:DeleteObjectVersion"
],
"Resource": "arn:aws:s3:::<BUCKET>/*"
},
{
"Sid": "AllowReadObjects",
"Effect": "Allow",
"Principal": { "CanonicalUser": "<READER_ID>" },
"Action": ["s3:GetObject", "s3:GetObjectVersion"],
"Resource": "arn:aws:s3:::<BUCKET>/*"
},
{
"Sid": "AllowListForReader",
"Effect": "Allow",
"Principal": { "CanonicalUser": "<READER_ID>" },
"Action": ["s3:ListBucket"],
"Resource": ["arn:aws:s3:::<BUCKET>", "arn:aws:s3:::<BUCKET>/*"]
}
]
}

Substitua:

VariávelValor
<WRITER_ID>User ID do projeto Writer
<READER_ID>User ID do projeto Reader
<BUCKET>Nome do bucket que será compartilhado

O que cada bloco faz​

SidPerfilEfeito
AllowWriteWriterPermite enviar objetos, inclusive uploads multipart
DenyReadForWriterWriterBloqueia leitura e exclusão, inclusive dos objetos que ele mesmo enviou
AllowReadObjectsReaderPermite baixar objetos e suas versões
AllowListForReaderReaderPermite listar o conteúdo do bucket

Passo 2 – Aplicar a policy​

A policy deve ser aplicada com a credencial do dono do bucket. Exemplo com AWS CLI:

jq . policy.json && aws --profile storin-owner s3api put-bucket-policy \
--bucket <BUCKET> \
--policy file://policy.json

O jq valida o JSON antes do envio. Se houver erro de sintaxe, o comando para antes de aplicar a policy.

Para conferir a policy aplicada:

aws --profile storin-owner s3api get-bucket-policy --bucket <BUCKET>

❗ Regras obrigatórias​

Estas regras valem para qualquer ferramenta usada para aplicar a policy.

Principal deve usar CanonicalUser

O Principal precisa usar CanonicalUser com o User ID em hexadecimal. As formas abaixo não funcionam no Storin e podem retornar 403:

"Principal": { "AWS": "<id>" }
"Principal": { "AWS": "arn:aws:iam:::user/<id>" }
O bloco DenyReadForWriter é obrigatório

Quem faz o PUT de um objeto se torna dono desse objeto e consegue lê-lo por ACL. Sem o Deny explícito, o Writer consegue ler tudo o que ele mesmo enviou.

O dono do bucket não pode ser restringido

O proprietário do bucket sempre tem acesso total, pois a ownership tem prioridade sobre a policy. Por isso, a credencial restrita precisa pertencer a uma identidade diferente da do dono, ou seja, a outro projeto.


✅ Parte 4 – Validando as permissões​

Os testes abaixo usam a AWS CLI. Com outra ferramenta, execute as operações equivalentes (upload, download, listagem e exclusão) com cada credencial e compare com a tabela de resultado esperado.

Crie um arquivo de teste:

echo "teste" > /tmp/t.txt

Writer (somente escrita)​

# Deve PASSAR
aws --profile storin-writer s3api put-object --bucket <BUCKET> --key wr.txt --body /tmp/t.txt

# Devem retornar 403 (AccessDenied)
aws --profile storin-writer s3api get-object --bucket <BUCKET> --key wr.txt /tmp/x.txt
aws --profile storin-writer s3api list-objects-v2 --bucket <BUCKET>
aws --profile storin-writer s3api delete-object --bucket <BUCKET> --key wr.txt
dica

Teste o GET do Writer sobre um objeto criado por ele mesmo (como o wr.txt acima). Esse é o cenário que comprova que o DenyReadForWriter está funcionando.

Reader (somente leitura)​

# Devem PASSAR
aws --profile storin-reader s3api get-object --bucket <BUCKET> --key wr.txt /tmp/y.txt
aws --profile storin-reader s3api list-objects-v2 --bucket <BUCKET>

# Devem retornar 403 (AccessDenied)
aws --profile storin-reader s3api put-object --bucket <BUCKET> --key ot.txt --body /tmp/t.txt
aws --profile storin-reader s3api delete-object --bucket <BUCKET> --key wr.txt

Resultado esperado​

IdentidadePUTGETLISTDELETE
Owner✅✅✅✅
Writer✅❌❌❌
Reader❌✅✅❌

🛠️ Troubleshooting – Problemas Comuns​

❌ 403 AccessDenied ao aplicar ou usar a policy​

  • Verifique se o Principal está no formato "CanonicalUser": "<USER_ID>".
  • Confirme se o User ID copiado é do projeto correto (aba Acessos).
  • Confirme se a policy foi aplicada com a credencial do dono do bucket.

❌ ValidationError em todo upload (AWS CLI)​

Faltam as linhas de checksum no ~/.aws/config. Adicione ao perfil:

request_checksum_calculation = when_required
response_checksum_validation = when_required

❌ O Writer consegue ler os próprios arquivos​

O bloco DenyReadForWriter não está na policy ou está com o User ID errado. Revise a policy e aplique novamente.

❌ A credencial "restrita" tem acesso total​

A Access Key foi gerada no mesmo projeto do dono do bucket. Chaves do mesmo projeto compartilham o mesmo User ID. Crie um projeto separado para o perfil restrito, conforme a Parte 1.

❌ O Reader não consegue listar o bucket​

A ação s3:ListBucket precisa dos dois resources: arn:aws:s3:::<BUCKET> e arn:aws:s3:::<BUCKET>/*.

Sobre sobrescrita de objetos

O Writer pode enviar um objeto com uma chave já existente, substituindo o conteúdo anterior. Se isso for um risco no seu caso, use chaves únicas no upload (por exemplo, com data e hora no nome) ou habilite o versionamento no bucket.


📘 Documentação relacionada: Configurando a AWS CLI com o Storin