Projekt: Ephemere Review-Umgebungen pro Merge Request. Gegenstand: Berechtigungen im AWS-Schulaccount (AWS Academy Learner Lab), US.1. Prüfdatum: 06.11.2026 Durchführende Stelle: Projektleitung
Fazit
Der Schulaccount reicht für die Umsetzung, ein Wechsel auf den privaten Account (Fallback) ist nicht nötig. Alle benötigten Dienste lassen sich anlegen, ansteuern und wieder entfernen. Es gibt aber vier Einschränkungen, die Architektur und Planung beeinflussen:
| # | Einschränkung | Auswirkung | Massnahme |
|---|---|---|---|
| E1 | Keine eigenen IAM-Rollen oder -Benutzer (iam:CreateRole, iam:CreateUser verweigert) | Lambda, EC2 und Scheduler können keine eigene Least-Privilege-Rolle erhalten. Es gibt keinen eigenen IAM-Benutzer für den Runner, der nur sqs:SendMessage darf. | Alle Dienste nutzen die vorhandene LabRole bzw. das LabInstanceProfile. Terraform liest diese per data-Quelle statt sie anzulegen. Falls die Zeit reicht, kann eine Least-Privilege-Policy im privaten Account nachgewiesen werden. |
| E2 | Zugangsdaten sind temporäre Learner-Lab-Sitzungsdaten (Rolle voclabs) | Die CI/CD-Variablen laufen mit jeder Sitzung ab und müssen von Hand erneuert werden. Der Runner hat dieselben weitreichenden Rechte wie die Projektleitung. | Vor Pipeline-Läufen die Variablen AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY und AWS_SESSION_TOKEN erneuern. Im Testprotokoll und in der Betriebsdokumentation festhalten. |
| E3 | Nur die Regionen us-east-1 und us-west-2 sind freigegeben | Keine Bereitstellung in der Schweiz oder der EU. | Alles läuft in us-east-1. |
| E4 | Die Zone us-east-1e bietet keine t3-Instanzen an | Ein Subnetz ohne feste Zone landet zufällig dort, run-instances schlägt dann mit Unsupported fehl. Im ersten Prüflauf ist genau das passiert. | Subnetze in Terraform immer mit fester availability_zone (z.B. us-east-1a) anlegen. |
Damit ist das Akzeptanzkriterium «Eine Lambda-Funktion mit eigener Rolle kann erstellt werden» nicht erfüllbar. Die Lambda läuft mit der LabRole, was für die Funktion genügt, aber das Sicherheitsziel «Least Privilege» im Schulaccount nicht durchgesetzt werden kann.
Vorgehen
Die Rechte wurden nicht aus den Policies abgelesen, sondern mit echten Aufrufen geprüft: Jede benötigte Ressource wird angelegt, benutzt und wieder gelöscht. So fallen auch Einschränkungen auf, die nicht in einer IAM-Policy stehen (z.B. E4). Das Skript ist wiederholbar und räumt auch bei einem Abbruch alles auf:
./source/permission-check/check_permissions.sh
Ein Lauf dauert rund 7 Minuten, den grössten Teil davon wartet das Skript auf die Registrierung der Instanz bei SSM und die Docker-Installation per Run Command.
Vorhandene Lab-Rolle
| Eigenschaft | Wert |
|---|---|
| Angemeldet als | assumed-role/voclabs/<user> |
| Rolle für Dienste | LabRole |
| Instanzprofil für EC2 | LabInstanceProfile (enthält LabRole) |
Für das Projekt relevante Vertrauensstellungen der LabRole | lambda, ec2, ssm, sqs, events, scheduler, logs |
| Relevante verwaltete Policy | AmazonSSMManagedInstanceCore, damit sich Instanzen bei SSM melden |
Resultate
Stand des Prüflaufs vom 06.11.2026 in us-east-1.
| Prüfung | Ergebnis | Aufruf / Fehler |
|---|---|---|
| IAM: eigene Rolle erstellen | verweigert | not authorized to perform: iam:CreateRole |
| IAM: LabRole lesen | erlaubt | iam get-role |
| IAM: LabInstanceProfile lesen | erlaubt | iam get-instance-profile |
| Region eu-central-1 nutzbar | verweigert | not authorized to perform: ec2:DescribeVpcs |
| Region us-west-2 nutzbar | erlaubt | ec2 describe-vpcs |
| S3: Bucket erstellen | erlaubt | s3api create-bucket |
| S3: Versionierung aktivieren | erlaubt | s3api put-bucket-versioning |
| S3: Verschlüsselung setzen | erlaubt | s3api put-bucket-encryption |
| S3: Public Access Block setzen | erlaubt | s3api put-public-access-block |
| S3: Objekt schreiben | erlaubt | s3api put-object |
| S3: bedingtes Schreiben (If-None-Match) | erlaubt | s3api put-object |
| S3: Versionen auflisten | erlaubt | s3api list-object-versions |
| DynamoDB: Tabelle erstellen | erlaubt | dynamodb create-table |
| SQS: FIFO Dead-Letter-Queue erstellen | erlaubt | sqs create-queue |
| SQS: FIFO-Queue mit Redrive Policy erstellen | erlaubt | sqs create-queue |
| SQS: Nachricht mit Message-Group und Dedup-ID senden | erlaubt | sqs send-message |
| SSM: SecureString schreiben | erlaubt | ssm put-parameter |
| SSM: SecureString entschlüsselt lesen | erlaubt | ssm get-parameter |
| Lambda: Funktion mit LabRole erstellen | erlaubt | lambda create-function |
| Lambda: Funktion aufrufen | erlaubt | lambda invoke |
| Lambda: Reserved Concurrency setzen | erlaubt | lambda put-function-concurrency |
| Lambda: SQS-Trigger (Event Source Mapping) erstellen | erlaubt | lambda create-event-source-mapping |
| CloudWatch Logs: Lambda-Logs lesen | erlaubt | logs filter-log-events |
| EventBridge: Schedule-Regel erstellen | erlaubt | events put-rule |
| EventBridge: Lambda als Ziel setzen | erlaubt | events put-targets |
| Lambda: Aufrufrecht für EventBridge vergeben | erlaubt | lambda add-permission |
| EventBridge Scheduler: Schedule mit LabRole erstellen | erlaubt | scheduler create-schedule |
| EC2: VPC erstellen | erlaubt | ec2 create-vpc |
| EC2: Subnetz erstellen | erlaubt | ec2 create-subnet |
| EC2: Internet Gateway erstellen | erlaubt | ec2 create-internet-gateway |
| EC2: Internet Gateway anhängen | erlaubt | ec2 attach-internet-gateway |
| EC2: Routing-Tabelle erstellen | erlaubt | ec2 create-route-table |
| EC2: Default-Route setzen | erlaubt | ec2 create-route |
| EC2: Routing-Tabelle zuordnen | erlaubt | ec2 associate-route-table |
| EC2: Public IP im Subnetz aktivieren | erlaubt | ec2 modify-subnet-attribute |
| EC2: Security Group erstellen | erlaubt | ec2 create-security-group |
| EC2: Ingress HTTP freigeben | erlaubt | ec2 authorize-security-group-ingress |
| EC2: Launch Template erstellen | erlaubt | ec2 create-launch-template |
| EC2: Instanz aus Launch Template mit ClientToken und Tags starten | erlaubt | ec2 run-instances |
| EC2: ClientToken verhindert Doppelanlage | erlaubt | ec2 run-instances --client-token |
| EC2: Instanzen per MR-Tag finden | erlaubt | ec2 describe-instances |
| SSM: Instanz meldet sich beim Agent (LabInstanceProfile) | erlaubt | ssm describe-instance-information |
| SSM: Run Command senden | erlaubt | ssm send-command |
| SSM: Run Command installiert Docker und startet Container | erlaubt | ssm get-command-invocation |
| Budgets: Budget erstellen | erlaubt | budgets create-budget |
| Cost Explorer: Kosten abfragen | erlaubt | ce get-cost-and-usage |
| CloudWatch: Billing-Alarm erstellen | erlaubt | cloudwatch put-metric-alarm |
Bedeutung für die User Stories
| User Story | Benötigt | Ergebnis |
|---|---|---|
| US.3: Terraform Remote State | S3 mit Versionierung, State Locking | Möglich. S3 unterstützt bedingtes Schreiben, damit reicht use_lockfile = true ohne DynamoDB. DynamoDB wäre als Alternative ebenfalls erlaubt. |
| US.4: Basis-Infrastruktur | VPC, Subnetz, IGW, Security Group, SQS FIFO + DLQ, Lambda, Launch Template | Möglich, mit LabRole statt eigenen Rollen (E1) und fester Zone (E4). |
| US.6: Deploy | run-instances aus Launch Template, ClientToken, Tags | Möglich. Ein wiederholter Aufruf mit gleichem ClientToken liefert dieselbe Instanz, es entsteht keine zweite. |
| US.8: Update | SSM Run Command auf der Instanz | Möglich. Docker installieren und einen Container starten funktioniert über AWS-RunShellScript. |
| US.9: Destroy | Instanzen per Tag finden und terminieren | Möglich. |
| US.10: Robustheit | Dead-Letter-Queue, Reserved Concurrency | Möglich. |
| US.11: Aufräumen | EventBridge-Regel oder Scheduler mit Lambda als Ziel | Möglich, der Scheduler nutzt die LabRole. |
| US.12: Kosten | AWS Budgets, Cost Explorer | Möglich. Budget, Billing-Alarm und Kostenabfrage sind erlaubt. |