Blog de Amazon Web Services (AWS)

Escribiendo políticas de IAM: Conceda Acceso a Carpetas Específicas de Usuario en un Bucket de Amazon S3

Por Jim Scharf

 

Muchos de ustedes se han preguntado cómo crear una política de AWS Identity and Access Management (IAM) con permisos a nivel de carpeta para buckets de Amazon S3. El bloguero invitado de esta semana, Elliot Yamaguchi, redactor técnico del equipo de IAM, explicará los aspectos básicos para escribir este tipo de políticas.

Para mostrarle cómo crear una política con permisos a nivel de carpeta, voy a guiarlo a través de un escenario similar al utilizado por muchas personas en recursos compartidos de archivos existentes, donde cada usuario solo tiene acceso a su propia carpeta personal. Con los permisos a nivel de carpeta, puede controlar de forma granular quién tiene acceso a qué objetos de un bucket específico.

Le mostraré una política que otorga a usuarios de IAM acceso al mismo bucket de Amazon S3 para que puedan usar la Consola de Administración de AWS para almacenar su información. Todos los usuarios podrán subir o descargar archivos de sus propias carpetas, pero no podrán acceder a la carpeta del bucket de ninguna otra persona.

Tras explicar la política, mostraré cómo utilizar las variables de política para que pueda utilizar una única política para un grupo de IAM en lugar de crear una política individual para cada usuario de IAM.

En el resto de esta publicación, mostraré y explicaré la política que se asociará a un usuario de IAM llamado David. Además, ya he creado un bucket llamado my-company con la siguiente estructura:

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

Breve lección sobre los objetos de Amazon S3

Antes de mostrar y explicar la política, tendré que repasar como los objetos de Amazon S3 son nombrados. Esta breve descripción no es exhaustiva, pero le ayudará a entender cómo funciona la política. Si ya está familiarizado con los objetos y prefijos de Amazon S3, continúe con la política de David, que aparece a continuación.

Amazon S3 almacena los datos en una estructura plana: usted crea un bucket y el bucket almacena objetos. Amazon S3 no tiene una jerarquía de sub-carpetas o carpetas; sin embargo, herramientas como la Consola de Administración de AWS pueden emular una jerarquía de carpetas para presentar las carpetas de un bucket usando los nombres de los objetos (también conocidos como claves). En pocas palabras, puede pensar en el nombre de un objeto como la ruta completa de un archivo en un sistema de archivos tradicional. Por ejemplo, para un objeto llamado home/common/shared.txt, la consola mostrará el archivo shared.txt en la carpeta common que se encuentra en la carpeta home. Los nombres de estas carpetas (como home/ o home/common/) se denominan prefijos, y prefijos como estos son los que utilizo para especificar la carpeta de inicio de David en su política.

Por cierto, la barra (/) de un prefijo como home/ no es un carácter reservado; puede asignar un nombre a un objeto (mediante la API de Amazon S3) con prefijos como home:common:shared.txt o home-common-shared.txt. Sin embargo, la convención es utilizar una barra como delimitador, y la consola de Amazon S3 (pero no Amazon S3 en sí) trata la barra como un carácter especial para mostrar objetos en carpetas.

Política de David

Empezaré mostrando la política completa de David que asocié a un usuario de IAM llamado David mediante la consola de IAM. A continuación, detallaré la política y explicaré cómo 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/*"]
   }
 ]
}

Esta política le da a David acceso completo a la consola, pero solo a la carpeta que le pertenece (/home/david). Si bien puede simplemente conceder a cada usuario acceso a su propio bucket, recuerde que una cuenta de AWS puede tener hasta 100 buckets por defecto. Al crear carpetas personales y conceder los permisos adecuados, puede hacer que cientos de usuarios compartan un solo bucket.

La política de David consiste en cuatro bloques. Echemos un vistazo a cada uno de ellos de forma individual.

Bloque 1: Conceder los permisos necesarios desde la consola de Amazon S3

Antes de empezar a identificar las carpetas específicas a las que puede tener acceso David, debo concederle dos permisos necesarios para acceder a la consola de Amazon S3: ListAllMyBuckets y GetBucketLocation.

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

La acción ListAllMyBuckets otorga a David permiso para enumerar todos los buckets de la cuenta de AWS, lo cual es necesario para listar los buckets en la consola de Amazon S3. (actualmente, no es posible filtrar selectivamente ciertos buckets, por lo que los usuarios deben tener permitido listar todos los buckets desde la consola). La consola también realiza una llamada GetBucketLocation cuando los usuarios acceden por primera vez a la consola de Amazon S3, por lo que David también necesita permiso para realizar esa acción. Sin estas dos acciones, David recibirá un error de acceso denegado en la consola.

Bloque 2: Permitir el listado de objetos en las carpetas raíz y principal

Aunque David solo debería tener acceso a su carpeta personal, necesita permisos adicionales para poder navegar hasta su carpeta en la consola de Amazon S3. David necesita permiso para listar los objetos a nivel raíz del bucket de mycompany y en la carpeta home/. La siguiente política otorga estos permisos a David:

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

Sin el permiso de ListBucket, David no podrá acceder a la carpeta porque no tendrá permisos para ver el contenido de las carpetas raíz y principal. Cuando David intente usar la consola para ver el contenido del bucket my-company, la consola devolverá un error de acceso denegado. Si bien esta política le da permiso a David para enumerar todos los objetos de las carpetas raíz y principal, no podrá ver el contenido de ningún archivo o carpeta, excepto el suyo propio (especifico esos permisos en el bloque siguiente).

Este bloque incluye condiciones que permiten limitar cuando una solicitud a AWS es válida.  En este caso, David puede listar objetos del bucket my-company cuando solicita objetos sin prefijo (objetos en el nivel raíz) y objetos con el prefijo home/ (objetos de la carpeta de inicio). Si David intenta navegar a otras carpetas, como restricted/, se le negará el acceso. Además, David necesita permisos para listar el prefijo home/David a fin de poder utilizar la función de búsqueda de la consola en lugar de desplazarse hacia abajo por la lista de carpetas de los usuarios.

Para establecer estos permisos de carpeta raíz y de inicio, usé dos condiciones: s3:prefix y s3:delimiter. La condición s3:prefix especifica las carpetas para las que David tiene permisos de ListBucket. Por ejemplo, David puede listar todos los siguientes archivos y carpetas en el bucket my-company:

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

Sin embargo, David no puede listar archivos o subcarpetas de las carpetas restricted/, home/Adele, o home/Bob folders.

Si bien la condición s3:delimiter no es obligatoria para acceder a la consola, sigue siendo una buena práctica incluirla en caso de que David realize solicitudes mediante la API o la interfaz de línea de comandos (CLI). Como se indicó anteriormente, el delimitador es un carácter, como una barra (/), que identifica la carpeta en la que se encuentra un objeto. El delimitador es útil cuando desea enumerar objetos como si estuvieran en un sistema de archivos. Por ejemplo, supongamos que el bucket my-company almacenaba miles de objetos. Si David incluye el delimitador en sus solicitudes, puede limitar el número de objetos devueltos únicamente a los nombres de los archivos y subcarpetas de la carpeta especificada. Sin el delimitador, además de todos los archivos de la carpeta que especificó, David obtendría todos los archivos de cualquier subcarpeta, todos los archivos de cualquier sub-subcarpeta, etc.

Bloque 3: Permitir el listado de objetos en la carpeta de David

Además de las carpetas raíz y de inicio, David necesita acceso a todos los objetos de la carpeta home/David/ y a las subcarpetas que pueda crear. Esta es una política que permite que:

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

En esta condición, utilizo una expresión StringLike en combinación con el asterisco (*) para representar cualquier objeto de la carpeta de David, donde el asterisco actúa como un comodín. De esta forma, David puede enumerar todos los archivos y carpetas de su carpeta (home/David/).No incluí esta condición en el bloque anterior (AllowRootAndHomeListingOfCompanyBucket) porque el bloque anterior usaba la expresión StringEquals que interpretaba literalmente el asterisco (*) como un asterisco, no como un comodín.

En la siguiente sección, que será el bloque AllowAllS3ActionsInUserFolder, verás que el elemento Resource especifica  my-company/home/David/*, que es similar a la condición especificada en esta sección. Podría pensar que puede utilizar el elemento Resource de la misma manera para especificar la carpeta de David en este bloque. Sin embargo, la acción ListBucket es una operación a nivel de bucket, lo que significa que el elemento Resource de la acción ListBucket se aplica únicamente a los nombres de bucket y no tiene en cuenta ningún nombre de carpeta. Por lo tanto, para limitar las acciones a nivel de objeto (archivos y carpetas), debe utilizar condiciones.

Bloque 4: Permitir todas las acciones de Amazon S3 en la carpeta de David

Por último, especifico las acciones de David (como los permisos de lectura, escritura y borrado) y las limito únicamente a su carpeta personal, como se muestra en la siguiente política:

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

Para el elemento Action, especifiqué s3:*, lo que significa que David puede realizar todas las acciones desde Amazon S3. En el elemento Resource, especifiqué la carpeta de David con un asterisco (*) (un comodín) para que David pueda realizar acciones en la carpeta y dentro de ella. Por ejemplo, David puede cambiar la clase de almacenamiento de su carpeta, habilitar el cifrado o hacer que la carpeta sea pública (realizar acciones en la propia carpeta). David también puede cargar archivos, eliminarlos y crear subcarpetas en su carpeta (realizar acciones en la carpeta).

Una forma más sencilla de gestionar políticas con variables de política

En la política a nivel de carpetas de David, especifiqué la carpeta de inicio de David. Si quisieras una política similar para usuarios como Bob y Adele, tendrías que crear políticas separadas que especifiquen sus carpetas de inicio. En lugar de crear políticas individuales para cada usuario, puede utilizar variables de política y crear una política única que se aplique a varios usuarios (una política de grupo). Las variables de política actúan como marcadores de posición. Cuando realiza una solicitud a AWS, el marcador de posición se sustituye por un valor de la solicitud cuando la política es evaluada.

Por ejemplo, puedo usar la política anterior y reemplazar el nombre de usuario de David por una variable que use el nombre de usuario del solicitante (aws:username), como se muestra en la siguiente política. Tenga en cuenta también que indiqué el número de versión de ambas políticas; si bien la versión es opcional para la política anterior, es obligatoria siempre que utilice variables 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}/*"]
    }
  ]
}

Cada vez que un usuario hace una solicitud a AWS, la variable se sustituye por el nombre de usuario “amigable” de la persona que hizo la solicitud. Así, cuando David hace una solicitud, ${aws:username} resuelve a David; cuando Adele hace la solicitud, ${aws:username} resuelve a Adele, etc.

Estos son algunos recursos adicionales para obtener más información sobre las carpetas de Amazon S3 y las políticas de IAM:

– Jim

 

Este artículo fue traducido del Blog de AWS en Inglés.


Sobre el autor

Jim Scharf

 

 

 

 

Revisores

Giovanni Ferraz es Partner Technical Account Manager y miembro de la comunidad de seguridad de AWS. Trabajando directamente con Partners Enterprise Support, ayudando a adoptar mejores prácticas, optimización de costes, seguridad y la reducción de riesgos en la nube de AWS.

 

 

 

 

Pedro Rosinholi es Arquitecto de Soluciones en AWS con más de 11 años de experiencia en soluciones tecnológicas. Ayuda a las empresas nativas digitales a desarrollar sus negocios en la nube de forma segura, escalable y resiliente. En su tiempo libre toca música usando discos de vinilo.

 

 

 

 

Adrian Diaz se desempeña actualmente como Technical Account Manager, apoyando a clientes de Enterprise Support en su viaje a la nube de AWS. Cuenta con más de 15 años de experiencia en TI, habiéndose desempeñado como administrador de sistemas e ingeniero de infraestructura, en donde ha participado de proyectos de networking, telefonía IP, virtualización, migración de centro de cómputos, entre otros