Securizar S3 bucket website endpoint

Hace algunas semanas me llegó este mensaje por parte de AWS

We are writing to notify you that you have configured your S3 bucket(s) to be publicly accessible, and this may be a larger audience than you intended. By default, S3 buckets allow only the account owner to access the contents of a bucket; however, customers can configure S3 buckets to permit public access. Public buckets are accessible by anyone on the Internet, and content in them may be indexed by search engines. We recommend enabling the S3 Block Public Access feature on buckets if public access is not required. S3 bucket permissions should never allow “Principal”:”*” unless you intend to grant public access to your data. Additionally, S3 bucket ACLs should be appropriately scoped to prevent unintended access to “Authenticated Users” (anyone with an AWS account) or “Everyone” (anyone with Internet access) unless your use case requires it. For AWS’s definition of “Public Access,” please see The Meaning of “Public” [1].

Más aburrido que ver “Los lunes al sol” doblado al iraní. Lo sé.

Vamos a resumir un poco los puntos importantes del mensaje:

  • Te notificamos de que tienes un S3 bucket que consideramos que es público y quizá es un error.
  • Por defecto, los buckets solo permiten al dueño de la cuenta el acceso a ese bucket. Sin embargo, los clientes podéis cambiar este comportamiento.
  • Los buckets públicos son accesibles por todo el mundo y incluso pueden ser indexados por motores de búsqueda.
  • Te recomendamos habillitar los S3 Block Public Access en los buckets si el acceso público no es requerido.
  • Nunca pongas “Principal: *” en una bucket policy a menos que consientas acceso público a tus datos.
  • Adicionalmente, las ACLS deben tener un alcance apropiado para evitar accesos no autorizados a “Authenticated Users” (cualquiera con una cuenta de AWS) o “Everyone” (cuaquiera con Internet)

Qué es para AWS un bucket público?

Pues no hace falta extenderse, está todo aquí, en este link.

Será evaluado como público dependiendo de las configuarciones de

  • ACL
  • Bucket Policy
  • Access Points

S3 Bucket marcado como público

Aquí podemos ver como este bucket (which should remain nameless!) tiene este simpático icono que nos avisa de que esto es público. Bueno, en mi caso la verdad es que no hacía falta que fuera público y ya lo he corregido.

LO DEL CONTEXTO

La idea de este bucket era que está detrás de un CloudFront. Y efectivamente carecía de la bucket policy correcta, además de más cosas.

Además, este bucket funcionaba como website endpoint. Lo cual es necesario para el siguiente punto:

Proteger el S3 website endpoint bucket para que solo acceda via CloudFront

Hay dos formas de proteger un bucket para que solo sea accesible desde CloudFront y no se pueda acceder directamente.

Y digo dos porque S3 puede funcionar como

  • S3 website endoint
  • S3 REST Api endpoint

La clave aquí es que si queremos proteger el S3 website endpoint no podemos utilizar el “Origin Access Identity” (OAI). Simplemente no funcionará.

Entonces la solución pasará por añadir un custom header en el Origin de nuestra distribución CloudFront.

Lo siguiente será editar la bucket policy de nuestro bucket, con algo como esto:

 {
        "Version": "2012-10-17",
        "Id": "http referer policy example",
        "Statement": [
            {
                "Effect": "Allow",
                "Principal": "*",
                "Action": "s3:GetObject",
                "Resource": "arn:aws:s3:::my-bucket.es/*",
                "Condition": {
                    "StringLike": {
                        "aws:Referer": [
                            "http://www.example.com/*" # aquí va el custom header de CFN
                        ]
                    }
                }
            },
            {
                "Sid": "2",
                "Effect": "Deny",
                "Principal": "*",
                "Action": "s3:GetObject",
                "Resource": "arn:aws:s3:::my-bucket.es/*",
                "Condition": {
                    "StringNotLike": {
                        "aws:Referer": [
                            "http://www.example.com/*" # aquí va el custom header de CFN
                        ]
                    }
                }
            }
        ]
    }

Seguidamente, habililltaremos todo el “S3 Block Public Access”. Y si tenemos alguna ACL que permite acceso a “Everyone” también lo deshabilitaremos.

Una ACL ferpecta
None shall pass

Y con esto, el aviso desaparecerá. Y en la consola de S3 veremos que ya no sale el icono en rojo sino otro comentario, relacionado con la política que hemos añadido a nuestro bucket.

Y con esto ya nos podemos olvidar del molesto aviso de S3.

Links

Leave a Reply

Your email address will not be published. Required fields are marked *