GraphQL API Sicherheit

AppSync und Security

Dieser Artikel beschreibt bewährte Sicherheitsverfahren, die tarienna für den Betrieb von GraphQL-API-Endpunkten auf Basis der Infrastruktur, Technologie und Technik von Amazon Webservices (AWS) nutzt und empfiehlt.

AWS AppSync ist ein vollständig von AWS verwalteter Dienst, der den Einsatz und die Interaktion mit serverlosen skalierbaren GraphQL-Backends in der Cloud ermöglicht. Als GraphQL-Service bietet AppSync zuverlässige Sicherheitsfunktionen für Unternehmen, um den Zugriff auf einzelne GraphQL-Endpunkte zu konfigurieren und zu verwalten.

Amplify ist eine Plattform als auch ein Framework, um sichere und skalierbare Anwendungen in der Cloud zu erstellen. In diesem Artikel zeigen wir anhand der @auth Direktive, wie GraphQL-Schemadefinitionen und Regeln zur Zugriffssteuerung in AppSync-APIs als Teil eines Amplify-Projekts einfach erstellt werden können.

API-Endpunkte sind in der Regel öffentlich im Internet zugänglich. Es ist deshalb unumgänglich, den unbefugten Zugriff zu verhindern. AppSync bietet vier verschiedene Möglichkeiten für die Autorisierung, um die Anfrage durch einen Token oder durch das Signieren der Anfrage mit Zugangsdaten abzusichern:

  • API-Schlüssel (API_KEY)
  • Amazon Cognito-Benutzerpools (AMAZON_COGNITO_USER_POOLS)
  • OpenID Connect (OPENID_CONNECT)
  • AWS Identitäts- und Zugriffsverwaltung (AWS_IAM)

Grundsätzlich müssen AppSync-APIs einen allgemein definierten Standardberechtigungsmodus haben. Es ist möglich, weitere Berechtigungsmodi in derselben API hinzuzufügen sowie diese zu mischen und anzupassen. Im GraphQL-Schema können diese Berechtigungen durch AppSync-spezifische Direktiven mit einzelnen Typen, Feldern oder Operationen verknüpft werden.

Bei einer AppSync-API mit API-Keys als Standardberechtigungsmodus und Cognito User Pools als zusätzlichem Berechtigungsmodus gewährt beispielsweise die folgende Typdefinition in einem API-GraphQL-Schema den Zugriff auf den Typ Device für beide Berechtigungsmodi:

Copy to Clipboard

Soll lediglich der Zugriff auf den Autorisierungsmodus Cognito User Pools erfolgen, so ist dies durch die folgende Schema-Definition möglich.

Copy to Clipboard

Wenn eine Direktive zur Autorisierung an einen Typ angefügt wird, findet diese standardmäßig auf alle Felder des Typs Anwendung. Du kannst den Zugriff auf bestimmte Felder zusätzlich einschränken, indem du die Direktiven zu den Feldern hinzufügst, die du einschränken möchtest.

Copy to Clipboard

Beide Berechtigungsmodi haben in dem Beispiel Zugriff auf den Typ und das id-Feld. Auf das Feld description kann lediglich der Modus Cognito User Pools zugreifen. Wichtig dabei ist, dass der Zugriff sowohl auf den Typ als auch das Feld selbst gewährt werden muss, damit die Berechtigung auf Feldebene wirksam werden kann. Sekundäre Autorisierungmodi werden im gesamten Schema zunächst grundsätzlich abgelehnt und müssen explizit für Verknüpfungen und Operationen kaskadierend angegeben werden.

In einem Amplify-Projekt kannst du die GraphQL-Transformation verwenden, um deine AppSync-API zu definieren und bereitzustellen. Du nutzt die @auth-Direktive, um für die einzelnen Modi Berechtigungsregeln innerhalb des GraphQL-Schemas zu erstellen. Für die Provider userPools und oicd kannst du in Amplify zusätzliche Regeln angeben, um automatisch feingranulare Geschäftslogik für die Zugriffskontrolle zu generieren. In der folgenden Tabelle erkennst du, wie die AppSync-Berechtigungsrichtlinien und die Regeln der @auth-Direktive in Amplify zusammenhängen.

AppSync Direktive Amplify @auth Regel
@aws_api_key { allow: public, provider: apiKey }
@aws_iam { allow: public|private, provider: iam}
@aws_oidc { allow: private|owner, provider: oidc}
@aws_cognito_user_pools
@aws_auth
{ allow: private|owner|groups, provider: userPools }

Die AppSync-Direktiven in der linken Spalte verwendest du, wenn du direkt mit AppSync arbeitest. Dies ist z.B. dann der Fall, wenn du GraphQL-API-Schemas direkt in der AWS-Konsole bearbeitest oder wenn du CloudFormation zur Definition des Schemas in einer Vorlage verwendest. Die Regeln in der rechten Spalte verwendest du hingegen, wenn die GraphQL-API-Berechtigung mit der @auth-Direktive in Amplify-Projekten definiert wird. Also unter der Verwendung des Amplify CLI mit amplify add api.

Als nächstes schauen wir uns die einzelnen Autorisierungsmodi mit passenden Anwendungsfällen und Konfigurationsbeispielen näher an. Zu Schluss treffen wir noch eine Aussage zu den Sicherheits- und Compliance-Standards von AppSync.

API Key

Diese Methode erlaubt es, einen statischen API-Key zu definieren, durch den ein Request mit dem HTTP-Header x-api-key autorisieret wird. Wir erstellen einen Schlüssel stets mit einem Ablaufdatum und AppSync akzeptiert Requests für diesen API-Key, solange der Schlüssel existiert und noch nicht abgelaufen ist. API-Schlüssel sind mit einem Gültigkeitszeitraum von maximal 365 Tagen konfigurierbar, wir können jedoch ein bestehendes Ablaufdatum um bis zu weitere 365 Tage nach dem Tag der Änderung  verlängern. Ein Schlüssel kann nach Ende seines Ablaufdatums nicht wieder verlängert werden.

Wann solltest du API-Keys verwenden?

Der API-Schlüssel ist ein hat-codierter Wert in deiner Software. API-Keys empfehlen wir deshalb für Entwicklungszwecke oder für Fälle, in denen es sicher ist, den öffentlichen Zugang zu einem API ohne spezielle Anforderungen an die Authentifizierung zu bieten (z.B. für Gastbenutzer). Wir empfehlen API-Schlüssel zu verwenden, wenn du mit der API-Entwicklung beginnst, schnell iterieren möchtest und dir zunächst keine Gedanken über kompliziertere Autorisierungsmethoden machen willst.

Anwendungen, von denen erwartet wird, dass sie langlebig und allgemein verfügbar sind, sollten keine API-Schlüssel verwenden! Ausnahmen sind Anwendungsfälle, in denen die gesamte oder eine Teilanwendung stets einen Gastzugang unterstützt.

Beispielkonfiguration

Wenn du den API-Key als zusätzlichen Berechtigungsmodus in AppSync verwendest, kannst du die Direktive @aws_api_key in deinem Schema verwenden, um festzulegen, dass dieses Feld API_KEY autorisiert ist. Die folgenden Definition gewährt ausschließlich den Zugriff durch Requests die mit dem API-Key autorisiert sind.

Copy to Clipboard

Das gleiche Ergebnis erhalten wir mit der Amplify @auth Transformation auf einen @model basierenden Typ.

Copy to Clipboard

Diese Konfiguration gewährt öffentlichen Lesezugriff auf Devices, wenn die Zugriffsmethode API_KEY verwendet wird. Amplify verwendet für den öffentlichen Zugriff die Methode API_KEY als Standard. In diesem Fall können wir den provider angeben, müssen es aber nicht.

Amazon Cognito User Pools

Diese Methode der Authentifizierung nutzt Amazon Cognito User Pools. User Pools verwenden den offene Industrie-Standard JSON Web Token (JWT), um nach der Anmeldung Ihrer Anwendung die Tokens bereitzustellen. Die Tokens nutzt Ihre Anwendung, um Anfragen an die AppSync API zu autorisieren. Eine feingranuläre Zugriffskontrolle auf API-Ebene ist möglich, indem Informationen über den angemeldeten Benutzer, seinen Gruppen und zusätzliche spezifische Eigenschaften des Benutzers verwendet werden. So kann z.B. der Zugriff auf bestimmte Objekte innerhalb der API entsprechend der Identität des Benutzers oder seiner Gruppenmitgliedschaft eingeschränkt werden.

Wann solltest du Amazon Cognito User Pools verwenden?

Amazon Cognito User Pools bieten ein vollständig verwaltetes Benutzerverzeichnis. Außerdem ermöglicht diese Berechtigungsmethode den Benutzern deiner Anwendung, sich bei dieser mit ihrem sozialen Profil (z.B. Google, Facebook, Amazon oder Apple) anzumelden. Zusätzlich kann ein User Pool mit bestehenden SAML-Identitätsanbietern und OpenID Connect (OIDC)-Identitätsanbietern verknüpft werden.

Cognito User Pools sind eine gute Wahl, wenn deine Anwendung über einen AppSync-Endpunkt mit JWT und anderen AWS Diensten interagieren soll. Hierzu werden die JWT-Token des User Pools mit temporären AWS-Anmeldeinformationen in Cognito Identity Pools auf sichere Weise ausgetauscht.

Beispielkonfiguration

Du kannst die Direktive @aws_auth innerhalb deiner AppSync API verwenden, wenn du den Zugriff auf bestimmte Cognito-Gruppen einschränken möchtest und der Cognito User Pool der einzige Autorisierungsmodus ist. Das folgende Schema beschränkt z.B. den Zugriff auf Benutzer, die Teil der Gruppe Developer und Tester sind.

Copy to Clipboard

Wenn du weitere Berechtigungsmodi verwendest (im folgenden Beispiel API-Key), solltest du mit der AppSync-Direktive @aws_cognito_user_pools festlegen, dass ein bestimmtes Feld AMAZON_COGNITO_USER_POOLS-autorisiert sein soll.

Copy to Clipboard

Wenn du in deinem Amplify-Projekt mit @model oder @searchable Typen arbeitest, kannst du mit der @auth Direktive automatisch eine spezifische Geschäftslogik zur Autorisierung in AppSync erstellen. Dies ermöglicht dir, den Zugriff auf Amazon DynamoDB-Tabellen oder Amazon Elasticsearch-Cluster basierend auf der Identität oder Gruppenmitgliedschaft des Benutzers zu steuern.

Das folgende Beispiel erlaubt dem Eigentümer (identifiziert durch den Benutzernamen des Cognito User Pools) vollen Zugriff auf die IoT-Devices, die ihm gehören, und beschränkt Mitglieder der Gruppe „Developers“ und „Testers“ auf das Lesen der Device-Informationen. Wenn der Benutzer ein IoT-Device erstellt, verknüpft die Autorisierungslogik innerhalb der AppSync-Resolver den Benutzernamen mit dem zugehörigen Datensatz. Der Benutzername sowie die Gruppenmitgliedschaft werden nun automatisch beim Aufruf der Operationen überprüft.

Copy to Clipboard

Zusätzlich zu den integrierten statischen Gruppen der Cognito User Pools kannst du den Gruppenzugriff auch dynamisch auf der Basis der Gruppeninformationen jedes einzelnen Datensatzes steuern. Beim Zugriff auf einen Datensatz wird auf diese Weise die Gruppenmitgliedschaft eines Benutzers gegen die Gruppen überprüft, die im gespeicherten Gruppenfeld der DynamoDB-Tabelle definiert sind.

Copy to Clipboard

OpenID Connect

Die OpenID Connect (OIDC) Autorisierungsmethode ist mit der Amazon Cognito User Pools-Methode vergleichbar. In diesem Kontext konfigurierst du AppSync mit einem, dem Standard vollständig entsprechenden, OIDC-Identitätsanbieter (IdP) wie z.B. Auth0 als Autorisierungprovider. Beim Zugriff auf die API validiert AppSync das Zugriffstoken mit dem JSON Web Key (JWK) der OIDC IdP. Ist die Validierung erfolgreich, autorisiert AppSync die Anfrage.

Wann solltest du OpenID Connect verwenden?

Die OpenID Connect Methode (OICD) solltest du verwenden, wenn du bereits über eine bestehende Benutzerbasis verfügst und nicht planst mit Hilfe von AWS-Anmeldeinformationen auf andere AWS-Dienste zuzugreifen. Sollte deine Anwendung Zugriff auf andere Dienste benötigen, die AWS-Anmeldeinformationen zur Autorisierung verwenden, kannst du die Cognito User Pools verwenden und deinen bestehenden OIDC IdP in den User Pool integrieren.

Beispielkonfiguration

Wenn du mehrere Autorisierungsmodi verwendest, legt die @aws_oidc Direktive in AppSync fest, dass ein Feld OPENID_CONNECT autorisiert wird.

Copy to Clipboard

Auf die selbe Weise wie du Cognito User Pools verwendest, kannst du für OpenID Connect in deinem Amplify-Projekt die @auth-Direktive verwenden, indem du als Provider oidc definierst. Die @auth-Direktive unterstützte individuelle Claims sowohl für Cognito User Pools als auch für OIDC. Bei einem OIDC-Provider macht Amplify keine Annahme darüber, welche Claims die Informationen zur Benutzeridentität und der Gruppenmitgliedschaft enthalten. Du musst deshalb explizit die Claims, welche die Identitätsinformationen sowie die Gruppenmitgliedschaft entsprechend mit identityClaim bzw. groupClaim definieren.

Copy to Clipboard

AWS Identitäts- und Zugriffsmanagement (IAM)

Im IAM-Autorisierungsmodus werden API Aufrufe über den AWS Signature Version 4 Signing-Prozess signiert und AppSync gewährt den Zugriff entsprechend den definierten Berechtigungen. Um diesen Modus verwenden zu können, musst du in IAM einen Benutzer oder eine Rolle erstellen. Die Berechtigungen definierst du in einer Richtlinie (policy), welche du dem erstellten Benutzer oder der Rolle zuweist.

Das folgende Beispiel definiert eine Richtline, die den Abruf von Devices (und allen Feldern) über eine getDevice und listDevices Abfrage einer bestimmten AppSync-API erlaubt.

Weitere Informationen findest du in der Auflistung der von AWS AppSync unterstützen Aktionen für IAM-Policies.

Copy to Clipboard

Wann solltest du IAM verwenden?

Der Autorisierungsmodus IAM ist die beste Wahl, wenn deine API für den Zugriff von Backend-Systemen konfiguriert wird, welche mit AWS Anmeldeinformationen abgesichert werden können. Dies sind z.B. Amazon EC2 Instanzen oder auch AWS Lambda Funktionen, wobei EC2 Instanzen mit Instanzenprofilen und Lambda Funktionen mit Ausführungsrollen konfiguriert werden.

Den IAM-Autorisierungsmodus verwendest du auch, wenn deine App öffentlichen Zugriff auf deine AppSync API bieten soll. Dieser „Gastzugriff“ erfolgt mit einer sogenannten nicht authentifizierten Identität aus einem Amazon Cognito Identity Pool. Diesen nicht authentifizierten Zugriff kannst du z.B. nutzen, wenn Clients auch auf AWS-Dienste wie z.B. S3 zugreifen sollen, bevor sich der Benutzer an deiner Anwendung angemeldet hat. Bei der Definition der Richtlinien für diese Rollen solltest du darauf achten, den Grundsatz der geringsten Priviliegien für den Zugriff auf deine Ressourcen zu verfolgen. Temporäre Zugangsdaten (Credentials) für authorisierte und nicht authorisierte Benutzer werden durch das Amplify Authentication Modul automatisch verwaltet.

Beispielkonfiguration

Wenn du mehrere Autorisierungsmodi verwendest, legt die @aws_iam Direktive in AppSync fest, dass ein Feld AWS_IAM autorisiert wird.

Copy to Clipboard

Die Amplify @auth Direktive macht es einfach, eine Regel zu definieren, mit der Apps mit IAM Credentials auf deine AppSync API zugreifen können. Die folgende Konfiguration ermöglicht es Benutzern oder Diensten mit korrekten AWS-Anmeldeinformationen und den nötigen Berechtigungen IoT-Devices zu lesen und zu aktualisieren. Du kannst diese Konfiguration z.B. verwenden, damit eine ereignisgesteuerte Lambda Funktion regelmäßig die dynamische IP-Adresse eines IoT-Devices in deiner Anwendung aktualisieren kann.

Copy to Clipboard

Auf die gleiche Weise kannst du den öffentlichen Zugriff mit IAM als Autorisierungsmodus definieren. Wenn du außerdem eine Auth-Kategorie mit Hilfe von Amplify definiert hast, wird automatisch eine neue Richtline erstellt, die einen Lesezugriff auf IoT-Devices gewährt und automatisch mit der unauthorized Identität eines Cognito Identity Pools verknüpft wird. Eine Auth-Kategorie erstellst du z.B. mit der Amplify CLI und dem folgenden Kommando.

Copy to Clipboard

In deiner Anwendung kannst nun temporäre Anmeldeinformationen anfordern, um die AppSync-Anfragen zu signieren und Informationen zu IoT-Devices  zu lesen.

Copy to Clipboard

Fazit

Wir haben dir hier verschiedene Wege der Absicherung deiner AppSync API vorgestellt. Darüber hinaus ist AppSync auch vollständig mit verschiedenen Industriestandards wie ISO, PCI, SOC, IRAP, HIPAA, MTCS, C5, ENS High, OSPAR, HITRUST CSF kompatibel. Wenn du also Geschäftsanwendungen entwickelst, die die Einhaltung eines oder mehrerer der eben genannten Sicherheitsstandards erfordert, kannst du mit AppSync Compliance konforme Anwendungen und Apps erstellen.

Du möchtest noch mehr über AWS AppSync und Security wissen? Wir freuen uns auf deine Nachricht.