Les 21: Geen inloggegevens lekken bij verbinding met services
Deze GraphQL query haalt inloggegevens op uit een omgevingsvariabele en voorkomt dat ze worden afgedrukt in de respons of logs, waarmee beveiligingsrisico's worden vermeden:
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}"
}
})
}Hieronder volgt een uitleg van hoe deze query werkt.
Hoe inloggegevens kunnen lekken
We moeten vaak inloggegevens opgeven bij het verbinden met externe services. GitHub's REST API vereist bijvoorbeeld een toegangstoken voor endpoints waar gegevens privé zijn of worden gewijzigd:
query {
_sendJSONObjectItemHTTPRequest(input:{
url: "https://api.github.com/repos/GatoGraphQL/GatoGraphQL",
method: PATCH,
options: {
auth: {
password: "{ GITHUB_ACCESS_TOKEN }"
},
body: "{\"has_wiki\":false}"
}
})
}We moeten voorzichtig zijn en vermijden dat onze inloggegevens worden blootgesteld:
- In de GraphQL query: Inloggegevens mogen nooit worden ingebed in de broncode, omdat ze dan als gewone tekst aanwezig zijn, wat een beveiligingsrisico vormt
- In de GraphQL-respons: Als het veld dat verbinding maakt met de service een fout produceert, wordt er een foutbericht toegevoegd aan de GraphQL-respons onder het item
errors; dit bericht kan de naam van het mislukte veld afdrukken samen met de argumenten ervan, waardoor de inloggegevens worden blootgesteld - In de serverlogs: Als inloggegevens worden benaderd via een variabele en deze variabele wordt meegegeven als URL-parameter, kan deze worden geregistreerd in de logs van de webserver
GraphQL query die het lekken van inloggegevens voorkomt
Deze GraphQL query geeft de inloggegevens door aan GitHub's API zonder ze te lekken:
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}"
}
})
}Dit komt doordat:
- De inloggegevens worden opgehaald uit een omgevingsvariabele
GITHUB_ACCESS_TOKEN, zodat ze niet in de broncode hoeven te worden ingebed - Veld
githubAccessTokenwordt verwijderd met@remove, waardoor het niet wordt afgedrukt in de respons - De invoer
_sendJSONObjectItemHTTPRequest(auth:)verwijst naar de dynamische variabele$__githubAccessToken, dus als het veld een fout produceert, wordt de letterlijke string"$__githubAccessToken"afgedrukt in het foutbericht (niet de waarde ervan)
Ter illustratie van het laatste punt: het opgeven van de URL van een niet-bestaande repository "leoloso/NonExisting" aan GitHub's API geeft een fout, en we krijgen deze respons (let op auth: {password: $__githubAccessToken} in het foutbericht):
{
"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
}
}