S3 — un recurso compartido es un bucket
serve "s3" { addr = "0.0.0.0:9000" }O por HTTPS, desde la v0.9.0, con tls = true y un
bloque tls:
serve "s3" {
addr = "0.0.0.0:9000"
tls = true
}El quinto protocolo, y el que hace que una imagen sea accesible desde cualquier cosa
que hable almacenamiento de objetos: una herramienta de copias de seguridad, una
canalización de datos, rclone, el fetch() de un navegador. No se monta nada.
GET / the shares this person may use, as buckets
GET /photos?list-type=2 the files in that share, as keys
GET /photos/holiday.jpg the file itself, Range and allUn recurso compartido es un bucket
Servido sobre el mismo árbol por usuario que usa SFTP: un sistema de archivos cuyo nivel superior son los recursos compartidos que esa persona puede usar. Así, un recurso compartido que alice no puede usar no es un bucket que alice pueda ver, y las reglas de acceso se aplican en un solo lugar en vez de copiarse a un segundo protocolo.
Un directorio dentro de un recurso compartido es un prefijo, no un objeto
Que es lo que los clientes S3 ya creen: muestran como carpetas los prefijos
que terminan en el delimitador. Un GET de un directorio responde
NoSuchKey, porque responder 200 haría creer a un cliente que puede
descargar los bytes de una carpeta.
Una clave de acceso es un usuario; la clave secreta es su contraseña
export AWS_ACCESS_KEY_ID=alice
export AWS_SECRET_ACCESS_KEY=$(cat alice.pw)
aws --endpoint-url http://attic.example.org:9000 s3 lsSigV4 prueba la posesión del secreto calculando un HMAC a partir de él: la contraseña nunca cruza la red, exactamente como con NTLMv2.
Por eso el directorio debe GUARDAR la contraseña, y no solo comprobarla
Un origen que solo puede verificar una contraseña —un bind LDAP, una columna bcrypt— puede responder a WebDAV y no puede responder a S3.
Y tampoco sirve un hash NT: es el MD4 con el que SMB puede trabajar, y a
partir de él no se puede calcular un HMAC. Una identidad que solo guarda
un hash NT sirve SMB y no S3: vecinos cercanos, pero no la misma
respuesta. check imprime la columna.
⛔ No existe ningún accesor Password() en todo el programa: a la contraseña solo
se llega mediante Identity.Derive, que recibe una derivación y devuelve su
resultado. Para S3 la derivación es la identidad, porque el cálculo de claves de
SigV4 vive en go-filesystems/s3; el secreto va a esa comprobación de firma, para ese
único usuario, y a ningún otro sitio.
Lo que se sirve
ListBuckets, HeadBucket, ListObjectsV2 con prefijo, delimitador, max-keys y
continuación, HeadObject, y GetObject con Range. SigV4 en sus dos formas, en
cabecera y prefirmada.
La API de objetos en sí es
go-filesystems/s3.
Lo que se rechaza, y por qué
Las escrituras responden 403
PUT, POST y DELETE se rechazan con AccessDenied (“this export is
read-only”). fileshare mantiene el servidor S3 en solo lectura porque un
recurso compartido que una persona solo puede leer tiene que rechazar en el
mismo punto en que lo hace SFTP, y eso aún no está conectado;
go-filesystems/s3 v0.3.0, sobre la que se construye esta versión, rechaza de
todos modos cualquier escritura. Rechazar es mejor que un objeto escrito a
medias.
Aquí no se acepta un token bearer
OIDC funciona por WebDAV y en ningún otro sitio. S3 autentica con una firma SigV4 —un HMAC sobre la petición—, sin ningún campo en el que quepa un token bearer.
La vía habitual es STS AssumeRoleWithWebIdentity, que canjea un token OIDC
por credenciales temporales con las que luego firma el cliente. Es un
mecanismo distinto, y no está implementado.
La subida multiparte, el versionado, las ACL, las políticas, las reglas de ciclo de
vida, la replicación y el etiquetado no están implementados. Configurar cualquiera de
ellos, e iniciar una subida multiparte, es una escritura, y responde AccessDenied
como cualquier otra. Un GET que pide uno de ellos (?versioning, ?acl,
?tagging…) no se distingue: la consulta se ignora y se devuelve el listado del
bucket o el objeto. NotImplemented responde a un listado distinto de
list-type=2, a cualquier método salvo GET sobre /, y a un método que ninguna
operación de aquí utiliza.
Dos límites que conviene conocer antes de apuntarlo a algo grande
GetObject lee el objeto entero en memoria. La interfaz del controlador ofrece
ReadFile y nada más —ni función de apertura, ni lector—, así que no hay lectura en
streaming que usar. Un límite, 256 MiB, responde EntityTooLarge en lugar de tumbar
el proceso.
LastModified es la época Unix. filesystem.Stat lleva Mode, Size e
Inode, y ninguna fecha de modificación. El campo no es opcional en el esquema de
S3, así que hay que enviar algo; la época es obviamente una fecha que no es real,
mientras que time.Now() parecería un archivo que acaba de cambiar y haría que
cualquier herramienta de sincronización lo copiara todo, en cada ejecución.
Creada el por tannevaled
Modificada el por tannevaled