Tutorial dello schema
Tutorial dello schemaLezione 21: Non divulgare le credenziali durante la connessione ai servizi

Lezione 21: Non divulgare le credenziali durante la connessione ai servizi

Questa query GraphQL recupera le credenziali da un valore di ambiente, e ne evita la stampa nella risposta o nei log, evitando così rischi per la sicurezza:

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}"
    }
  })
}

Di seguito è riportata una spiegazione del funzionamento di questa query.

Come potrebbero essere divulgate le credenziali

Spesso è necessario fornire credenziali quando ci si connette a servizi esterni. Ad esempio, l'API REST di GitHub richiede un token di accesso per gli endpoint in cui i dati sono privati o vengono modificati:

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

Dobbiamo fare attenzione ed evitare di esporre le nostre credenziali:

  • Nella query GraphQL: Le credenziali non devono mai essere incorporate nel codice sorgente, poiché sarebbero in testo normale, creando un rischio per la sicurezza
  • Nella risposta GraphQL: Se il campo che si connette al servizio produce un errore, nella risposta GraphQL verrà aggiunto un messaggio di errore sotto la voce errors; questo messaggio potrebbe stampare il nome del campo che ha fallito insieme ai suoi argomenti, stampando così le credenziali
  • Nei log del server: Se le credenziali vengono accedute tramite una variabile, e questa variabile viene fornita come parametro URL, potrebbe essere registrata nei log del server web

Query GraphQL che evita la divulgazione delle credenziali

Questa query GraphQL trasmette le credenziali all'API di GitHub evitando di divulgarle:

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}"
    }
  })
}

Questo perché:

  • Le credenziali vengono recuperate da una variabile di ambiente GITHUB_ACCESS_TOKEN, quindi non è necessario incorporarle nel codice sorgente
  • Il campo githubAccessToken viene rimosso con @remove, quindi non viene stampato nella risposta
  • L'input _sendJSONObjectItemHTTPRequest(auth:) fa riferimento alla variabile dinamica $__githubAccessToken, quindi se il campo produce un errore, è la stringa letterale "$__githubAccessToken" che verrà stampata nel messaggio di errore (non il suo valore)

Per dimostrare quest'ultimo punto, fornire all'API di GitHub l'URL di un repository inesistente "leoloso/NonExisting" genera un errore, e otteniamo questa risposta (si noti auth: {password: $__githubAccessToken} nel messaggio di errore):

{
  "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
  }
}