Achtung: Diese Seite enthält Partner- und Werbe-Links. Daher ist diese Seite im Gesamten als Werbeanzeige zu verstehen!
In diesem Artikel erkläre ich, wie Symfony so konfiguriert werden kann, dass von Nutzern hochgeladene, allgemein öffentliche Dateien mit Hilfe der MiddlewareGaufrette respektive dem KnpGaufretteBundle automatisch in ein S3-Bucket auf Amazon AWS hochgeladen werden können und der Zugriff über einen sauber getrennten Nutzer funktioniert.
Falls noch kein S3-Bucket erstellt wurde, muss dieses natürlich initial erledigt werden - ein gültiger Amazon AWS-Account vorausgesetzt. In meinem Beispiel erstelle ich den Bucket in der Region "EU (Frankfurt)", was später in der Symfony-Konfiguration als eu-central-1
relevant wird. Eine Lister aller Regionen und der Regions-Code kann hier gefunden werden.
Ansonsten kann der Bucket prinzipiell "nach Lust und Laune" erstellt werden, in meinem Beispiel tue ich das ohne Versionierung, Logging oder einer Verschlüsselung. Außerdem füge ich initial keine Berechtigungen hinzu - im dritten Schritt dieses Artikels werde ich darauf zurückkommen.
Für das tatsächliche Hochladen von Daten in den S3-Bucket benötigt Symfony Zugangsdaten in Form des sogenannten "Access Key" und dem dazugehörigen "Access Key Secret". Es empfiehlt sich sehr, diese Zugangsdaten mit eingeschränkten Rechten für den gewollten Anwendungsfall zu generieren, da ein potenzieller Angreifer, der in den Besitz dieser Daten kommt, sonst uneingeschränkte Kontorlle über den AWS-Account hätte.
Um einen entsprechenden Nutzer zu erstellen, muss oben im Menü auf "My Security Credentials" und anschließend auf "Users" geklickt werden. Hier können beliebige Nutzer über den "Add user"-Button erstellt werden. In meinem Beispiel nenne ich den Nutzer s3-staging
und wähle die Checkbox "Programmatic access" an um zu definieren, dass dieser Account keinen echten Menschen repräsentiert.
Im darauf folgenden Screen füge ich den neuen Nutzer weder einer Gruppe hinzu noch verbinde ich ihn direkt mit Berechtigungen innerhalb von AWS. Die im "Review"-Screen angezeigte Warnung, dass der Nutzer über keinerlei Berechtigungen verfüge, kann getrost ignoriert werden. Ist der Nutzer erstellt, kann er entsprechend auch in der Übersicht eingesehen und angeklickt werden. Für den nächsten Schritt benötigen wir die "User ARN " - in meinem Fall arn:aws:iam::119851430366:user/s3-staging
. Im Tab "Security credentials" muss außerdem der Access Key und das zugehörige Secret gespeichert werden.
Der S3-Bucket sowie ein entsprechender Nutzer mit noch fehlenden Zugriffsrechten ist jetzt erstellt. Über eine sogenannte "Bucket Policy" wird dem Nutzer nun das fehlende Recht zum Hochladen und Auslesen aller Dateien gegeben. Hierzu muss der in Schritt 1 erstellte S3-Bucket nochmals bearbeitet werden. Im Tab "Permissions" muss dafür folgende - natürlich angepasste - Policy hinzugefügt werden. Konkret sind der Name des S3-Buckets( werbung-vorbei-staging
) sowie der ARN des Nutzers ( arn:aws:iam::119851430366:user/s3-staging
) durch die tatsächlichen Werte zu ersetzen.
{
"Version": "2012-10-17",
"Id": "Policy1489062408719",
"Statement": [
{
"Sid": "AllowGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::werbung-vorbei-staging/*"
},
{
"Sid": "AllowListBucket",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::119851430366:user/s3-staging"
},
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::werbung-vorbei-staging"
},
{
"Sid": "AllowPutObject",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::119851430366:user/s3-staging"
},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::werbung-vorbei-staging/*"
},
{
"Sid": "AllowDeleteObject",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::119851430366:user/s3-staging"
},
"Action": "s3:DeleteObject",
"Resource": "arn:aws:s3:::werbung-vorbei-staging/*"
}
]
}
Achtung: Die hier aufgeführte Policy erlaubt den lesenden Zugriff auf alle in den S3-Bucket hochgeladenen Dateien und ist daher nur zu empfehlen, wenn keine sensiblen oder personenbezogenen Daten gespeichert werden.
Ich nutze meist das VichUploaderBundle zum Hochladen von Dateien. Dieses Bundlen spielt wunderbar mit dem KnpGaufretteBundle zusammen, das letztlich Gaufrette für das Hochladen der Dateien verwendet. Nachfolgend beschreibe ich die Konfiguration der genannten Bundles, angefangen mit der parameters.yml
, die ich um einige Einträge zur Verwaltung des S3-Bucket erweitert habe:
parameters.yml
parameters:
aws_s3_key: ***
aws_s3_secret: ***
aws_s3_region: eu-central-1
aws_s3_signature: v4
aws_s3_bucket: werbung-vorbei-staging
aws_s3_bucket_url: 'https://s3.eu-central-1.amazonaws.com/werbung-vorbei-staging/media/'
Im Anschluss kann die knp_gaufrette.yml
wie folgt konfiguriert werden:
knp_gaufrette.yml
knp_gaufrette:
stream_wrapper:
filesystems: [ media_fs ]
adapters:
media_local:
local:
directory: '%kernel.root_dir%/../public/uploads/images'
media_s3:
aws_s3:
service_id: 'app.aws_s3.client'
bucket_name: '%aws_s3_bucket%'
options:
directory: 'media'
files_local:
local:
directory: '%kernel.root_dir%/../public/uploads/files'
files_s3:
aws_s3:
service_id: 'app.aws_s3.client'
bucket_name: '%aws_s3_bucket%'
options:
directory: 'files'
filesystems:
files_fs:
adapter: 'files_%knp_adapter%'
media_fs:
adapter: 'media_%knp_adapter%'
Sowie auch die vich_uploader.yml
:
vich_uploader.yml
vich_uploader:
db_driver: orm
storage: gaufrette
mappings:
uploaded_image:
uri_prefix: /uploads/images
upload_destination: media_fs
namer: vich_uploader.namer_uniqid
inject_on_load: false
delete_on_update: true
delete_on_remove: true
Und letztlich die aws.yml
:
aws.yml
services:
app.aws_s3.client:
class: Aws\S3\S3Client
factory: [Aws\S3\S3Client, factory]
arguments:
-
region: '%aws_s3_region%'
signature: '%aws_s3_signature%'
version: '2006-03-01'
credentials:
key: '%aws_s3_key%'
secret: '%aws_s3_secret%'
Nun sollte, wenn eine Entität mit einer Datei wie in der Dokumentation zum VichUploaderBundle beschrieben gespeichert wird, automatisch eine Kopie der entsprechenden Datei auf dem erstellten S3-Bucket erscheinen: