Immer wieder brauche ich aus einer Anwendung in Google Cloud heraus Zugriff auf AWS-Ressourcen wie S3, SQS und Co. Da Access- und Secret-Keys zu Recht als schlechte Praxis gelten, habe ich kurzerhand Janus gebaut – ein kleines Tool, mit dem Sie aus einer Google Cloud Compute Engine-Instanz heraus per Service Account eine AWS Role übernehmen können.
Warum Janus? In der römischen Mythologie war Janus, der zweigesichtige Gott, für Tore und Türen zuständig. Eine schöne Analogie für unseren Fall ;-)
Was genau ist Janus also? Ein kleines Stück Code, das Sie auf Ihrer eigenen Google Cloud Compute Engine-Instanz laufen lassen, um eine AWS Role zu übernehmen – ohne dafür AWS IAM Keys zu nutzen.
Warum Janus?
Angenommen, Sie wollen aus einer Instanz oder einem Container in Google Cloud eine private Datei aus einem S3-Bucket laden. Dazu müssen Sie sich gegenüber AWS IAM authentifizieren.
Dafür gibt es mehrere Möglichkeiten. Am sichersten ist es, einer Instanz eine IAM Role zuzuweisen – das funktioniert allerdings nur mit EC2-Instanzen, also Instanzen auf AWS-Infrastruktur.
Bei einer Google Cloud-Instanz sind die Optionen begrenzt. Die meisten greifen daher zu AWS IAM Access Keys – häufig mit weiter gefassten Berechtigungen als nötig – und legen sie hartcodiert ab.
Das ist ein erhebliches Sicherheitsrisiko: Gerät der Key in falsche Hände, steht jedem die Tür zu Ihrem AWS-Konto offen. Die Folgen reichen von Datenlecks bis zu finanziellen Schäden. Das vergleichsweise "harmloseste" Szenario, das mir untergekommen ist: Angreifer fahren auf Ihre Kosten Krypto-Mining-Server hoch oder verschlüsseln Daten und Backups im Konto und fordern Lösegeld für die Wiederherstellung.
Wie lässt sich also eine sichere Verbindung von GCP zu AWS-Ressourcen aufbauen, ohne Keys hartzucodieren?
Janus umgeht diese Einschränkungen, indem es Ihnen erlaubt, auf einer GCP Compute Engine-Maschine über eine Google Web Identity eine Role zu übernehmen – ganz ähnlich wie mit einer IAM Role auf EC2. Janus fordert dabei einen temporären Key bei AWS an, der eine Stunde gültig ist.
Janus einrichten
Als Beispiel zeige ich, wie man Read-only-Zugriff auf einen AWS S3-Bucket einrichtet, den ich später in meiner Google Compute-Instanz nutzen werde.
- Melden Sie sich in der GCP Console an und wählen Sie im linken Navigationsmenü IAM & Admin. Klicken Sie dann auf Service Accounts und anschließend auf +CREATE SERVICE ACCOUNT.

2. Geben Sie dem Service Account einen Namen und eine aussagekräftige Beschreibung (immer Best Practice). Klicken Sie dann auf CREATE.

3. Klicken Sie anschließend auf das Feld Role und wählen Sie Service Account → Service Account Token Creator.
Schneller geht es, wenn Sie Token in das Suchfeld Type to filter eingeben.

4. Es erscheint die Seite "Grant users access to this service account (optional)". Klicken Sie dort auf DONE.
5. Klicken Sie auf den Namen des Service Accounts und kopieren Sie die Unique ID.

6. Melden Sie sich in Ihrem AWS-Konto an und navigieren Sie zur IAM Console → Roles → Create role.

7. Wählen Sie als trusted entity die Option Web identity → Google als Identity provider und fügen Sie die Unique ID des GCP Service Accounts in das Feld Audience ein. Klicken Sie dann auf Next: Permissions.

8. Vergeben Sie nun die Berechtigung für die Role. Für dieses Beispiel verwenden wir AmazonS3ReadOnlyAccess. Klicken Sie auf Next: Tags.

9. Der Tags-Schritt ist optional und wird hier übersprungen. Klicken Sie auf Next: Review.
10. Vergeben Sie einen Namen und eine ausführliche Beschreibung für die Role und klicken Sie auf Create role.

11. Die Role ist nun einsatzbereit. Klicken Sie auf Role ARN und kopieren Sie ihn für einen späteren Schritt.

12. Wechseln Sie zurück in die GCP Console und legen Sie eine neue Compute Engine-VM-Instanz an.

Scrollen Sie etwas nach unten zum Abschnitt Identity and API access und ersetzen Sie den Compute Engine default service account durch den in Schritt 5 erstellten Service Account.

13. AWS und GCP sind nun eingerichtet, sodass wir aus GCP heraus eine AWS Role übernehmen können. Jetzt fehlt nur noch ein Tool oder etwas Code, der den Vorgang mit der Web Identity von Google ausführt. Genau dafür gibt es Janus.
Janus liefert temporäre AWS-Credentials an alle unterstützten AWS SDKs sowie an die AWS CLI.
Um Janus einzurichten, führen Sie einfach die folgenden Befehle als Root-User aus:
$ apt install python3-pip awscli
$ pip3 install boto3 requests
$ wget https://raw.githubusercontent.com/doitintl/janus/master/janus.py -O /usr/local/bin/janus
$ chmod 555 /usr/local/bin/janus
Um Janus mit der gewünschten IAM Role auszuführen, geben Sie den in Schritt 10 kopierten AWS Role ARN an.
/usr/local/bin/janus arn:aws:iam::123456789012:role/s3-ro-from-gcp
14. Legen Sie ein neues Profil in Ihrer Datei /.aws/credentials an ( steht als Kürzel für das Home-Verzeichnis des Users). Das AWS SDK nutzt die in dieser Datei hinterlegten Profile, um die Authentifizierung gegenüber AWS abzuschließen.
Existiert die Datei noch nicht, legen Sie sie an:
$ mkdir ~/.aws
$ touch ~/.aws/credentials
Bearbeiten Sie die Datei credentials und fügen Sie ein Profil hinzu (der Standardprofilname lautet default). Sie können mehrere Profile anlegen – für dieses Beispiel erstellen wir ein neues Default-Profil:
credential_process = /usr/local/bin/janus arn:aws:iam::123456789012:role/s3-ro-from-gcp
15. Fertig! Sie können AWS jetzt aus Ihrer GCP-Instanz heraus nutzen.
Als Beispiel kopiere ich mit der AWS CLI eine Datei namens hello.txt aus meinem AWS S3-Bucket:

Wie funktioniert das Ganze?
- Jedes Mal, wenn das AWS SDK oder die AWS CLI auf AWS zugreifen muss, sucht es das Default-Profil unter:
/.aws/credentials auf Mac, Linux und Unix ( steht als Kürzel für das Home-Verzeichnis)
oder
C:\Users\USERNAME\.aws\credentials unter Windows.
- Anschließend wird Janus mit dem Namen der zu übernehmenden AWS Role ausgeführt.
- Janus fordert ein JWT-Token vom Compute Engine-Metadata-Server an und übernimmt damit die AWS Role.
- AWS prüft, ob das JWT-Token zu den Einstellungen der AWS Role passt, und gibt einen temporären Access Key zurück:

- Mit diesem temporären Access Key können wir nun auf AWS zugreifen und APIs im Namen der AWS Role aufrufen.
Wie lässt sich nachvollziehen, welche Instanz auf mein AWS-Konto zugreift?
Für das Tracking übernimmt Janus die Role mit einem eigenen Session-Namen im Format project-id.instance-name.
Sofern in Ihrem Konto AWS CloudTrail aktiviert ist, können Sie alle AssumeRoleWithWebIdentity-Events filtern und jeden API-Aufruf nachvollziehen.

Das Event enthält:
- die Source-IP der GCP-Maschine,
- username – die Unique ID des GCP Service Accounts,
- den "Session Name" der Session-Role – Project ID und Instanzname,
- den Namen der übernommenen Role.
Über den Access Key lassen sich anschließend alle Aktionen nachverfolgen, die die Instanz ausgeführt hat.