thomaskekeisen.de

Aus dem Leben eines Bildschirmarbyters

Achtung: Diese Seite enthält Partner- und Werbe-Links. Daher ist diese Seite im Gesamten als Werbeanzeige zu verstehen!

Sichere Buckets ohne großen Aufwand

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.

Schritt 1: Bucket erstellen

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.

S3-Bucket erstellen Screenshot 1
S3-Bucket erstellen Screenshot 2
S3-Bucket erstellen Screenshot 3
S3-Bucket erstellen Screenshot 4

Schritt 2: IAM-Nutzer erstellen

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.

IAM-Nutzer anlegen erstellen Screenshot 1
IAM-Nutzer anlegen erstellen Screenshot 2
IAM-Nutzer anlegen erstellen Screenshot 3
IAM-Nutzer anlegen erstellen Screenshot 4
IAM-Nutzer anlegen erstellen Screenshot 5
IAM-Nutzer anlegen erstellen Screenshot 6

Schritt 3: Bucket-Policy anpassen

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.

Screenshot: Bucket-Policy erstellen

Schritt 4: Symfony konfigurieren

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%'
            
        
Symfony konfigurieren Screenshot 1
Symfony konfigurieren Screenshot 2
Symfony konfigurieren Screenshot 3
Symfony konfigurieren Screenshot 4

Et voila

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:

Screenshot: Eine Datei wurde im S3-Bucket gespeichert

Teilen

Kommentare