Tutorial do schema
Tutorial do schemaLição 21: Não vazar credenciais ao conectar-se a serviços

Lição 21: Não vazar credenciais ao conectar-se a serviços

Esta query GraphQL recupera credenciais de um valor de ambiente e evita que sejam impressas na resposta ou nos logs, evitando assim riscos de segurança:

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

A seguir há uma explicação de como essa query funciona.

Como as credenciais podem ser vazadas

Frequentemente precisamos fornecer credenciais ao conectar-se a serviços externos. Por exemplo, a REST API do GitHub requer um token de acesso para endpoints onde os dados são privados ou são modificados:

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

Precisamos ter cuidado e evitar expor nossas credenciais:

  • Na query GraphQL: As credenciais nunca devem ser incorporadas no código-fonte, pois estariam em texto simples, criando um risco de segurança
  • Na resposta GraphQL: Se o campo que se conecta ao serviço produzir um erro, uma mensagem de erro será adicionada na resposta GraphQL sob a entrada errors; essa mensagem pode imprimir o nome do campo que falhou junto com seus argumentos, imprimindo assim as credenciais
  • Nos logs do servidor: Se as credenciais forem acessadas por meio de uma variável, e essa variável for fornecida como parâmetro de URL, ela poderá ser registrada nos logs do servidor web

Query GraphQL que evita o vazamento de credenciais

Esta query GraphQL passa as credenciais para a API do GitHub evitando o vazamento das credenciais:

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

Isso ocorre porque:

  • As credenciais são recuperadas de uma variável de ambiente GITHUB_ACCESS_TOKEN, portanto não precisam ser incorporadas no código-fonte
  • O campo githubAccessToken é removido com @remove, portanto não é impresso na resposta
  • O input _sendJSONObjectItemHTTPRequest(auth:) referencia a variável dinâmica $__githubAccessToken, portanto se o campo produzir um erro, é a string literal "$__githubAccessToken" que será impressa na mensagem de erro (não o seu valor)

Para demonstrar o último item, fornecer à API do GitHub a URL de um repositório inexistente "leoloso/NonExisting" gera um erro, e obtemos esta resposta (observe auth: {password: $__githubAccessToken} na mensagem de erro):

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