O blog da AWS

Escrevendo políticas do IAM: Conceda Acesso a Pastas Específicas do Usuário em um Bucket do Amazon S3

Por Jim Scharf

 

Muitos de vocês perguntaram como criar uma política do  AWS Identity and Access Management (IAM) com permissões em nível de pasta para buckets do Amazon S3. O blogueiro convidado desta semana, Elliot Yamaguchi, redator técnico da equipe do IAM, explicará os fundamentos da redação desse tipo de política.

Para mostrar como criar uma política com permissões no nível da pasta, vou percorrer um cenário semelhante ao que muitas pessoas fizeram em compartilhamentos de arquivos existentes, em que cada usuário tem acesso apenas à sua própria pasta inicial. Com permissões no nível da pasta, você pode controlar de forma granular quem tem acesso a quais objetos em um bucket específico.

Mostrarei uma política que concede aos usuários do IAM acesso ao mesmo bucket do Amazon S3 para que eles possam usar o Console de Gerenciamento da AWS para armazenar suas informações. Todos os usuários poderão carregar ou baixar arquivos de suas próprias pastas, mas não poderão acessar a pasta de mais ninguém no bucket.

Depois de explicar a política, mostrarei como usar variáveis de política para que você possa usar uma única política para um grupo do IAM em vez de criar uma política individual para cada usuário do IAM.

No restante desta publicação, mostrarei e explicarei a política, que será associada a um usuário do IAM chamado  David. Além disso, eu já criei um bucket chamado my-company com a seguinte estrutura:

/home/Adele/
/home/Bob/
/home/David/
/restricted/
/root-file.txt

Uma breve lição sobre objetos do Amazon S3

Antes de mostrar e explicar a política, precisarei revisar como os objetos do Amazon S3 são nomeados. Essa breve descrição não é abrangente, mas ajudará você a entender como a política funciona. Se você já conhece objetos e prefixos do Amazon S3, avance para a política de David, abaixo.

O Amazon S3 armazena dados em uma estrutura plana: você cria um bucket e o bucket armazena objetos. O Amazon S3 não tem uma hierarquia de sub-buckets ou pastas; no entanto, ferramentas como o Console de Gerenciamento da AWS podem emular uma hierarquia de pastas para apresentar pastas em um bucket usando os nomes de objetos (também conhecidos como chaves). Para simplificar, você pode pensar no nome de um objeto como o caminho completo de um arquivo em um sistema de arquivos tradicional. Para dar um exemplo, para um objeto chamado home/common/shared.txt, o console mostrará o arquivo shared.txt na pasta common que está na pasta home. Os nomes dessas pastas (como home/ ou home/common/) /) são chamados de prefixos, e prefixos como esses são os que uso para especificar a pasta inicial de David em sua política.

A propósito, a barra (/) em um prefixo como home/ não é um caractere reservado; você pode nomear um objeto (usando a API do Amazon S3) com prefixos como  home:common:shared.txt ou home-common-shared.txt. No entanto, a convenção é usar uma barra como delimitador, e o console do Amazon S3 (mas não o próprio Amazon S3) trata a barra como um caractere especial para mostrar objetos em pastas.

Política do David

Começarei mostrando a política completa de David que associei a um usuário do IAM chamado David usando o console do IAM. Em seguida, vou detalhar a política e explicar como ela funciona.

{
 "Version":"2012-10-17",
 "Statement": [
   {
     "Sid": "AllowUserToSeeBucketListInTheConsole",
     "Action": ["s3:ListAllMyBuckets", "s3:GetBucketLocation"],
     "Effect": "Allow",
     "Resource": ["arn:aws:s3:::*"]
   },
  {
     "Sid": "AllowRootAndHomeListingOfCompanyBucket",
     "Action": ["s3:ListBucket"],
     "Effect": "Allow",
     "Resource": ["arn:aws:s3:::my-company"],
     "Condition":{"StringEquals":{"s3:prefix":["","home/", "home/David"],"s3:delimiter":["/"]}}
    },
   {
     "Sid": "AllowListingOfUserFolder",
     "Action": ["s3:ListBucket"],
     "Effect": "Allow",
     "Resource": ["arn:aws:s3:::my-company"],
     "Condition":{"StringLike":{"s3:prefix":["home/David/*"]}}
   },
   {
     "Sid": "AllowAllS3ActionsInUserFolder",
     "Effect": "Allow",
     "Action": ["s3:*"],
     "Resource": ["arn:aws:s3:::my-company/home/David/*"]
   }
 ]
}

Essa política concede a David acesso total ao console, mas apenas à pasta que pertence a ele (/home/David) Embora você possa simplesmente conceder a cada usuário acesso ao seu próprio bucket, lembre-se de que uma conta da AWS pode ter até 100 buckets por padrão. Ao criar pastas iniciais e conceder as permissões apropriadas, você pode ter centenas de usuários compartilhando um único bucket.

A política de David consiste em quatro blocos. Vamos dar uma olhada em cada um individualmente.

Bloco 1: conceder as permissões necessárias do console do Amazon S3

Antes de começar a identificar as pastas específicas às quais David pode ter acesso, preciso conceder a ele duas permissões necessárias para o acesso ao console do Amazon S3:  ListAllMyBuckets e GetBucketLocation.

   {
      "Sid": "AllowUserToSeeBucketListInTheConsole",
      "Action": ["s3:GetBucketLocation", "s3:ListAllMyBuckets"],
      "Effect": "Allow",
      "Resource": ["arn:aws:s3:::*"]
   }

A ação ListAllMyBuckets concede a permissão para o David listar todos os buckets na conta da AWS, o que é necessário para navegar até buckets no console do Amazon S3. Abro aqui um parêntese: atualmente, não é possível filtrar seletivamente determinados buckets, portanto, os usuários devem ter permissão para listar todos os buckets de acesso ao console. O console também faz uma chamada  GetBucketLocation quando os usuários navegam inicialmente para o console do Amazon S3, e é por isso que David também exige permissão para essa ação. Sem essas duas ações, David receberá um erro de acesso negado no console.

Bloco 2: permitir a listagem de objetos nas pastas raiz e inicial

Embora David deva ter acesso apenas à sua pasta pessoal, ele precisa de permissões adicionais para poder navegar até sua pasta no console do Amazon S3. David precisa de permissão para listar objetos no nível raiz do bucket my-company na pasta home/. A política a seguir concede essas permissões a David:

   {
      "Sid": "AllowRootAndHomeListingOfCompanyBucket",
      "Action": ["s3:ListBucket"],
      "Effect": "Allow",
      "Resource": ["arn:aws:s3:::my-company"],
      "Condition":{"StringEquals":{"s3:prefix":["","home/", "home/David"],"s3:delimiter":["/"]}}
   }

Sem a permissão  ListBucket David não pode navegar até a pasta porque ele não terá permissões para visualizar o conteúdo das pastas raiz e inicial. Quando David tenta usar o console para visualizar o conteúdo do bucket my-company, to console retornará um erro de acesso negado. Embora essa política conceda permissão a David para listar todos os objetos nas pastas raiz e inicial, ele não poderá visualizar o conteúdo de nenhum arquivo ou pasta, exceto o próprio (especifico essas permissões no próximo bloco).

Esse bloco inclui condições, que permitem limitar quando uma solicitação à AWS é válida. Nesse caso, David pode listar objetos no bucket  my-company somente quando solicita objetos sem um prefixo (objetos no nível raiz) e objetos com o prefixo  home/ (objetos na pasta inicial). Se David tentar navegar para outras pastas, como  restricted/, ele terá seu acesso negado. Além disso, David precisa de permissões para listar o prefixo home/David para poder usar a funcionalidade de pesquisa do console em vez de rolar para baixo na lista de pastas dos usuários.

Para definir essas permissões de raiz e pasta inicial, usei duas condições: s3:prefix e s3:delimiter. A condição  s3:prefix especifica as pastas para as quais David tem permissões ListBucket. Por exemplo, David pode listar todos os seguintes arquivos e pastas no bucket my-company:

/root-file.txt
/restricted/
/home/Adele/
/home/Bob/
/home/David/

Mas David não pode listar arquivos ou subpastas nas pastas restricted/, home/Adele, ou home/Bob folders.

Embora a condição  s3:delimiter não seja necessária para acesso ao console, ainda é uma boa prática incluí-la caso David faça solicitações usando a API ou a interface de linha de comando (CLI). Conforme observado anteriormente, o delimitador é um caractere, como uma barra (/), tque identifica a pasta em que um objeto está. O delimitador é útil quando você deseja listar objetos como se estivessem em um sistema de arquivos. Por exemplo, vamos supor que o bucket  my-company armazenou milhares de objetos. Se David incluir o delimitador em suas solicitações, ele poderá limitar o número de objetos retornados apenas aos nomes de arquivos e subpastas na pasta especificada. Sem o delimitador, além de todos os arquivos na pasta que ele especificou, David obteria todos os arquivos em qualquer subpasta, todos os arquivos em qualquer sub-subpasta etc.

Bloco 3: permitir a listagem de objetos na pasta de David

Além das pastas raiz e inicial, David requer acesso a todos os objetos na pasta home/David/ e a todas as subpastas que ele possa criar. Aqui está uma política que permite isso:

    {
      "Sid": "AllowListingOfUserFolder",
      "Action": ["s3:ListBucket"],
      "Effect": "Allow",
      "Resource": ["arn:aws:s3:::my-company"],
      "Condition":{"StringLike":{"s3:prefix":["home/David/*"]}}
    }

Na condição, eu uso uma expressão  StringLike em combinação com o asterisco (*) para representar qualquer objeto na pasta de David, onde o asterisco age como um curinga. Dessa forma, David pode listar todos os arquivos e pastas na pasta dele (home/David/).Não incluí essa condição no bloco anterior (AllowRootAndHomeListingOfCompanyBucket) porque o bloco anterior usava a expressão StringEquals que literalmente interpretaria o asterisco (*) ) como um asterisco, não como um curinga.

Na próxima seção, que será o bloco AllowAllS3ActionsInUserFolder, você verá que o elemento  Resource especifica  my-company/home/David/*, que é semelhante à condição especificada nesta seção. Você pode pensar que pode usar o elemento  Resource eda mesma forma para especificar a pasta de David neste bloco. No entanto, a açãoListBucket ListBucket é uma operação no nível do bucket, o que significa que o elemento  Resource para a ação ListBucket se aplica somente a nomes de bucket e não leva em consideração nenhum nome de pasta. Portanto, para limitar as ações no nível do objeto (arquivos e pastas), você deve usar condições.

Bloco 4: permitir todas as ações do Amazon S3 na pasta de David

Por fim, especifico as ações de David (como permissões de leitura, gravação e exclusão) e as limito apenas à pasta inicial dele, conforme mostrado na política a seguir:

    {
      "Sid": "AllowAllS3ActionsInUserFolder",
      "Effect": "Allow",
      "Action": ["s3:*"],
      "Resource": ["arn:aws:s3:::my-company/home/David/*"]
    }

Para o elemento  Action especifiquei s3:*, que significa que David tem permissão para realizar todas as ações do Amazon S3. No elemento  Resource especifiquei a pasta de David com um asterisco (*) um curinga) para que David possa executar ações na pasta e dentro da pasta. Por exemplo, David tem permissão para alterar a classe de armazenamento da pasta dele, habilitar a criptografia ou tornar a pasta pública (executar ações na própria pasta). David também tem permissão para fazer upload de arquivos, excluir arquivos e criar subpastas na pasta dele (executar ações na pasta).

Uma maneira mais fácil de gerenciar políticas com variáveis de política

Na política de nível de pasta de David, especifiquei a pasta inicial de David. Se você quisesse uma política semelhante para usuários como Bob e Adele, teria que criar políticas separadas que especificassem suas pastas iniciais. Em vez de criar políticas individuais para cada usuário, você pode usar variáveis de política e criar uma única política que se aplique a vários usuários (uma política de grupo). As variáveis de política atuam como espaços reservados. Quando você faz uma solicitação à AWS, o espaço reservado é substituído por um valor da solicitação quando a política é avaliada.

Por exemplo, posso usar a política anterior e substituir o nome de usuário de David por uma variável que usa o nome de usuário do solicitante  (aws:username), conforme mostrado na política a seguir. Observe também que eu declarei o número da versão para ambas as políticas; embora a versão seja opcional para a política anterior, ela é necessária sempre que você usa variáveis de política.

{
  "Version":"2012-10-17",
  "Statement": [
    {
      "Sid": "AllowGroupToSeeBucketListInTheConsole",
      "Action": ["s3:ListAllMyBuckets", "s3:GetBucketLocation"],
      "Effect": "Allow",
      "Resource": ["arn:aws:s3:::*"]
    },
    {
      "Sid": "AllowRootAndHomeListingOfCompanyBucket",
      "Action": ["s3:ListBucket"],
      "Effect": "Allow",
      "Resource": ["arn:aws:s3:::my-company"],
      "Condition":{"StringEquals":{"s3:prefix":["","home/"],"s3:delimiter":["/"]}}
    },
    {
      "Sid": "AllowListingOfUserFolder",
      "Action": ["s3:ListBucket"],
      "Effect": "Allow",
      "Resource": ["arn:aws:s3:::my-company"],
      "Condition":{"StringLike":{"s3:prefix":
                  [
                       "home/${aws:username}/*",
                       "home/${aws:username}"
                  ]
               }
        }
    },
    {
       "Sid": "AllowAllS3ActionsInUserFolder",
       "Action":["s3:*"],
       "Effect":"Allow",
       "Resource": ["arn:aws:s3:::my-company/home/${aws:username}/*"]
    }
  ]
}

Sempre que um usuário faz uma solicitação à AWS, a variável é substituída pelo nome de usuário “amigável” de quem fez a solicitação. Então, quando David faz uma solicitação, ${aws:username} resolve para  David; quando Adele faz a solicitação, ${aws:username} resolve para  Adele, etc.

Aqui estão alguns recursos adicionais para aprender sobre as pastas do Amazon S3 e sobre as políticas do IAM:

– Jim

 

Este artigo foi traduzido do Blog da AWS em Inglês.


Sobre o autor

Jim Scharf

 

 

 

 

Revisores

Giovanni Ferraz é Partner Technical Account Manager e membro da Comunidade de Segurança na AWS, atuando diretamente com Partners Enterprise Support, ajudando em melhores práticas, otimização de custos, segurança e redução de riscos na nuvem AWS.

 

 

 

 

Pedro Rosinholi é Arquiteto de Soluções na AWS com mais de 11 anos de experiência em soluções de Tecnologia. Ajuda empresas nativas digitais na construção de seus negócios na nuvem de maneira segura, escalável e resiliente. No tempo livre coloca uns discos de vinil para tocar.