Schema-Tutorial
Schema-TutorialLektion 21: Keine Zugangsdaten preisgeben beim Verbinden mit Diensten

Lektion 21: Keine Zugangsdaten preisgeben beim Verbinden mit Diensten

Diese GraphQL-Query ruft Zugangsdaten aus einem Umgebungswert ab und verhindert, dass sie in der Antwort oder in den Logs ausgegeben werden, wodurch Sicherheitsrisiken vermieden werden:

query {
  githubAccessToken: _env(name: "GITHUB_ACCESS_TOKEN")
    @remove
 
  _sendJSONObjectItemHTTPRequest(input:{
    url: "https://api.github.com/repos/GatoGraphQL/GatoGraphQL",
    method: PATCH,
    options: {
      auth: {
        password: $__githubAccessToken
      },
      body: "{\"has_wiki\":false}"
    }
  })
}

Im Folgenden wird erklärt, wie diese Query funktioniert.

Wie Zugangsdaten preisgegeben werden könnten

Beim Verbinden mit externen Diensten müssen wir häufig Zugangsdaten angeben. Zum Beispiel erfordert die REST API von GitHub ein Access-Token für Endpunkte, bei denen Daten privat sind oder verändert werden:

query {
  _sendJSONObjectItemHTTPRequest(input:{
    url: "https://api.github.com/repos/GatoGraphQL/GatoGraphQL",
    method: PATCH,
    options: {
      auth: {
        password: "{ GITHUB_ACCESS_TOKEN }"
      },
      body: "{\"has_wiki\":false}"
    }
  })
}

Wir müssen sorgfältig vorgehen und vermeiden, unsere Zugangsdaten preiszugeben:

  • In der GraphQL-Query: Zugangsdaten dürfen niemals in den Quellcode eingebettet werden, da sie dort im Klartext vorliegen und ein Sicherheitsrisiko darstellen
  • In der GraphQL-Antwort: Wenn das Feld, das sich mit dem Dienst verbindet, einen Fehler erzeugt, wird in der GraphQL-Antwort unter dem Eintrag errors eine Fehlermeldung hinzugefügt; diese Meldung könnte den Namen des fehlgeschlagenen Feldes zusammen mit seinen Argumenten ausgeben und so die Zugangsdaten preisgeben
  • In den Server-Logs: Wenn auf Zugangsdaten über eine Variable zugegriffen wird und diese Variable als URL-Parameter übergeben wird, könnte sie in den Logs des Webservers aufgezeichnet werden

GraphQL-Query, die keine Zugangsdaten preisgibt

Diese GraphQL-Query übermittelt die Zugangsdaten an die API von GitHub, ohne sie preiszugeben:

query {
  githubAccessToken: _env(name: "GITHUB_ACCESS_TOKEN")
    @remove
 
  _sendJSONObjectItemHTTPRequest(input:{
    url: "https://api.github.com/repos/GatoGraphQL/GatoGraphQL",
    method: PATCH,
    options: {
      auth: {
        password: $__githubAccessToken
      },
      body: "{\"has_wiki\":false}"
    }
  })
}

Das liegt daran, dass:

  • Die Zugangsdaten aus der Umgebungsvariable GITHUB_ACCESS_TOKEN abgerufen werden und daher nicht in den Quellcode eingebettet werden müssen
  • Das Feld githubAccessToken mit @remove entfernt wird und daher nicht in der Antwort ausgegeben wird
  • Der Input _sendJSONObjectItemHTTPRequest(auth:) auf die dynamische Variable $__githubAccessToken verweist, sodass bei einem Fehler des Feldes der Literalstring "$__githubAccessToken" in der Fehlermeldung ausgegeben wird (nicht sein Wert)

Um den letzten Punkt zu veranschaulichen: Wenn man der API von GitHub die URL eines nicht existierenden Repositorys "leoloso/NonExisting" übergibt, wird ein Fehler ausgelöst, und wir erhalten diese Antwort (beachte auth: {password: $__githubAccessToken} in der Fehlermeldung):

{
  "errors": [
    {
      "message": "Client error: `PATCH https://api.github.com/repos/leoloso/NonExisting` resulted in a `404 Not Found` response:\n{\"message\":\"Not Found\",\"documentation_url\":\"https://docs.github.com/rest/repos/repos#update-a-repository\"}\n",
      "locations": [
        {
          "line": 21,
          "column": 3
        }
      ],
      "extensions": {
        "path": [
          "_sendJSONObjectItemHTTPRequest(input: {url: \"https://api.github.com/repos/leoloso/NonExisting\", method: PATCH, options: {auth: {password: $__githubAccessToken}, body: \"{\"has_wiki\":false}\"}})",
          "query { ... }"
        ],
        "type": "QueryRoot",
        "field": "_sendJSONObjectItemHTTPRequest(input: {url: \"https://api.github.com/repos/leoloso/NonExisting\", method: PATCH, options: {auth: {password: $__githubAccessToken}, body: \"{\"has_wiki\":false}\"}})",
        "id": "root",
        "code": "PoP/ComponentModel@e1"
      }
    }
  ],
  "data": {
    "_sendJSONObjectItemHTTPRequest": null
  }
}