Estoy implementando una carga directa de archivos desde la máquina del cliente a Amazon S3 a través de la API REST usando solo JavaScript, sin ningún código del lado del servidor. Todo funciona bien, pero una cosa me preocupa ...
Cuando envío una solicitud a la API REST de Amazon S3, necesito firmar la solicitud y poner una firma en el Authentication
encabezado. Para crear una firma, debo usar mi clave secreta. Pero todo sucede en el lado del cliente, por lo que la clave secreta se puede revelar fácilmente desde la fuente de la página (incluso si ofusco / cifro mis fuentes).
¿Cómo puedo manejar esto? ¿Y es un problema en absoluto? ¿Tal vez pueda limitar el uso específico de la clave privada solo a las llamadas a la API REST desde un origen CORS específico y solo a los métodos PUT y POST o tal vez vincular la clave solo a S3 y un bucket específico? ¿Puede haber otros métodos de autenticación?
La solución "sin servidor" es ideal, pero puedo considerar involucrar algún procesamiento en el servidor, excluyendo cargar un archivo a mi servidor y luego enviarlo a S3.
Respuestas:
Creo que lo que quieres son cargas basadas en navegador usando POST.
Básicamente, necesita un código del lado del servidor, pero todo lo que hace es generar políticas firmadas. Una vez que el código del lado del cliente tiene la política firmada, puede cargar usando POST directamente a S3 sin que los datos pasen por su servidor.
Aquí están los enlaces de documentos oficiales:
Diagrama: http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingHTTPPOST.html
Código de ejemplo: http://docs.aws.amazon.com/AmazonS3/latest/dev/HTTPPOSTExamples.html
La política firmada iría en su html en una forma como esta:
Observe que la acción FORM está enviando el archivo directamente a S3 , no a través de su servidor.
Cada vez que uno de sus usuarios quiera cargar un archivo, debe crear el
POLICY
ySIGNATURE
en su servidor. Devuelve la página al navegador del usuario. El usuario puede cargar un archivo directamente a S3 sin pasar por su servidor.Cuando firma la política, normalmente hace que la política caduque después de unos minutos. Esto obliga a sus usuarios a hablar con su servidor antes de cargarlos. Esto le permite controlar y limitar las cargas si lo desea.
Los únicos datos que van o salen de su servidor son las URL firmadas. Sus claves secretas permanecen secretas en el servidor.
fuente
${filename}
al nombre de la clave, así que para el ejemplo anterior, enuser/eric/${filename}
lugar de solouser/eric
. Siuser/eric
es una carpeta ya existente, la carga fallará silenciosamente (incluso será redirigido a success_action_redirect) y el contenido cargado no estará allí. Acabo de pasar horas depurando esto pensando que era un problema de permiso.Puede hacer esto con AWS S3 Cognito, pruebe este enlace aquí:
http://docs.aws.amazon.com/AWSJavaScriptSDK/guide/browser-examples.html#Amazon_S3
Prueba también este código
Simplemente cambie Region, IdentityPoolId y su nombre de depósito
fuente
Estás diciendo que quieres una solución "sin servidor". Pero eso significa que no tiene la capacidad de poner ninguno de "su" código en el bucle. (NOTA: una vez que entregue su código a un cliente, ahora es "su" código). Bloquear CORS no va a ayudar: las personas pueden escribir fácilmente una herramienta no basada en web (o un proxy basado en web) que agrega el encabezado CORS correcto para abusar de su sistema.
El gran problema es que no puedes diferenciar entre los diferentes usuarios. No puede permitir que un usuario enumere / acceda a sus archivos, pero puede evitar que otros lo hagan. Si detecta abuso, no hay nada que pueda hacer al respecto, excepto cambiar la clave. (Que el atacante presumiblemente puede obtener de nuevo).
Su mejor opción es crear un "usuario de IAM" con una clave para su cliente de JavaScript. Solo dale acceso de escritura a un solo cubo. (pero idealmente, no habilite la operación ListBucket, eso lo hará más atractivo para los atacantes).
Si tuviera un servidor (incluso una microinstancia simple a $ 20 / mes), podría firmar las claves en su servidor mientras monitorea / previene el abuso en tiempo real. Sin un servidor, lo mejor que puede hacer es monitorear periódicamente el abuso después del hecho. Esto es lo que haría:
1) gire periódicamente las claves para ese usuario de IAM: todas las noches, genere una nueva clave para ese usuario de IAM y reemplace la clave más antigua. Como hay 2 claves, cada clave será válida por 2 días.
2) habilite el registro S3 y descargue los registros cada hora. Establezca alertas en "demasiadas cargas" y "demasiadas descargas". Deberá verificar tanto el tamaño total del archivo como la cantidad de archivos cargados. Y querrá controlar tanto los totales globales como también los totales por dirección IP (con un umbral más bajo).
Estas comprobaciones se pueden hacer "sin servidor" porque puede ejecutarlas en su escritorio. (es decir, S3 hace todo el trabajo, estos procesos solo están ahí para alertarlo sobre el abuso de su depósito S3 para que no reciba una factura gigante de AWS al final del mes).
fuente
Al agregar más información a la respuesta aceptada, puede consultar mi blog para ver una versión en ejecución del código, utilizando la versión 4 de AWS Signature.
Resumiremos aquí:
Tan pronto como el usuario seleccione un archivo para cargar, haga lo siguiente: 1. Llame al servidor web para iniciar un servicio para generar los parámetros necesarios
En este servicio, llame al servicio AWS IAM para obtener crédito temporal
Una vez que tenga la credibilidad, cree una política de depósito (cadena codificada en base 64). Luego, firme la política del depósito con la clave de acceso secreta temporal para generar la firma final
enviar los parámetros necesarios de vuelta a la interfaz de usuario
Una vez que se reciba esto, cree un objeto de formulario html, establezca los parámetros requeridos y PUBLICARLO
Para obtener información detallada, consulte https://wordpress1763.wordpress.com/2016/10/03/browser-based-upload-aws-signature-version-4/
fuente
Aquí es donde has entendido mal. La razón por la que se usan las firmas digitales es para que pueda verificar que algo es correcto sin revelar su clave secreta. En este caso, la firma digital se utiliza para evitar que el usuario modifique la política que configuró para la publicación del formulario.
Las firmas digitales como la de aquí se utilizan para la seguridad en toda la web. Si alguien (¿NSA?) Realmente pudiera romperlos, tendrían objetivos mucho más grandes que su cubo S3 :)
fuente
He dado un código simple para cargar archivos desde el navegador Javascript a AWS S3 y enumerar todos los archivos en el cubo S3.
Pasos:
Para saber cómo crear Create IdentityPoolId http://docs.aws.amazon.com/cognito/latest/developerguide/identity-pools.html
Pase a la página de la consola S3 y abra la configuración de los cors desde las propiedades del depósito y escriba el siguiente código XML en eso.
Cree un archivo HTML que contenga el siguiente código, cambie las credenciales, abra el archivo en el navegador y disfrute.
fuente
Si no tiene ningún código del lado del servidor, su seguridad depende de la seguridad del acceso a su código JavaScript en el lado del cliente (es decir, todos los que tienen el código pueden cargar algo).
Por lo tanto, recomendaría, simplemente crear un bucket especial S3 que sea de escritura pública (pero no legible), para que no necesite ningún componente firmado en el lado del cliente.
El nombre del depósito (un GUID, por ejemplo) será su única defensa contra cargas maliciosas (pero un atacante potencial no podría usar su depósito para transferir datos, ya que solo se escribe a él)
fuente
Así es como se genera un documento de política utilizando el nodo y sin servidor
El objeto de configuración utilizado se almacena en SSM Parameter Store y tiene este aspecto
fuente
Si está dispuesto a utilizar un servicio de terceros, auth0.com admite esta integración. El servicio auth0 intercambia una autenticación de servicio SSO de terceros por un token de sesión temporal de AWS con permisos limitados.
Consulte: https://github.com/auth0-samples/auth0-s3-sample/
y la documentación de auth0.
fuente