Perché la mia risorsa proxy Gateway API con un sistema di autorizzazione Lambda con caching attivato restituisce errori HTTP 403 "User is not authorized to access this resource" (L'utente non è autorizzato ad accedere a questa risorsa)?

6 minuti di lettura
0

La mia risorsa proxy Gateway Amazon API con un sistema di autorizzazione AWS Lambda con caching attivato restituisce il messaggio di errore HTTP 403 seguente: "User is not authorized to access this resource" (L'utente non è autorizzato ad accedere a questa risorsa).

Breve descrizione

Nota: Gateway API può restituire errori 403 User is not authorized to access this resource (L'utente non è autorizzato ad accedere a questa risorsa) per una serie di motivi. Questo articolo tratta solo gli errori 403 relativi alle risorse proxy Gateway API con un sistema di autorizzazione Lambda con caching attivato. Per informazioni sulla risoluzione di altri tipi di errori 403, consulta Come posso risolvere gli errori HTTP 403 di Gateway API?

L'output di un sistema di autorizzazione Lambda restituisce una policy AWS Identity and Access Management (IAM) a Gateway API. La policy IAM include un elemento di tipo "Resource" dell'API di Gateway API esplicito nel formato seguente:

"arn:aws:execute-api:<region>:<account>:<API_id>/<stage>/<http-method>/[<resource-path-name>/[<child-resources-path>]"

Quando in un sistema di autorizzazione Lambda è attivato il Caching delle autorizzazioni, la policy IAM restituita viene memorizzata nella cache. La policy IAM memorizzata nella cache viene quindi applicata a qualsiasi richiesta API aggiuntiva effettuata entro il periodo time-to-live (TTL) specificato per la cache.

Se l'API ha una risorsa proxy con una variabile del percorso greedy {proxy+}, la prima richiesta viene autorizzata. Qualsiasi richiesta API aggiuntiva effettuata verso un percorso diverso nel periodo TTL della cache viene rifiutata con l'errore seguente:

"message": "User is not authorized to access this resource" (L'utente non è autorizzato ad accedere a questa risorsa)

Le richieste aggiuntive hanno esito negativo perché i percorsi non corrispondono all'elemento "Resource" dell'API di Gateway API esplicito definito nella policy IAM memorizzata nella cache.

Per risolvere il problema, puoi modificare il codice della funzione del sistema di autorizzazione Lambda in modo che restituisca invece una risorsa con carattere jolly (*/*) nell'output. Per ulteriori informazioni, consulta Resources and conditions for Lambda actions.

Nota: per attivare la memorizzazione nella cache del sistema di autorizzazione, questo deve restituire una policy applicabile a tutti i metodi di un Gateway API. Il codice della funzione del sistema di autorizzazione Lambda deve restituire una risorsa con carattere jolly (*/*) nell'output, in modo da consentire tutte le risorse. La policy della cache si attende lo stesso percorso di risorsa memorizzato nella cache, a meno che non sia stata effettuata la stessa richiesta due volte sullo stesso percorso.

Risoluzione

Nota: modifica i frammenti di codice di esempio delle funzioni del sistema di autorizzazione Lambda in questo articolo per adattarli al tuo caso d'uso.

Nelle configurazioni di esempio seguenti, le funzioni Lambda estraggono il valore id di Gateway API dal nome della risorsa Amazon (ARN) del metodo ("event.methodArn"). Quindi, le funzioni definiscono una variabile "Resource" con caratteri jolly combinando i percorsi dell'ARN del metodo con il valore id dell'API e un carattere jolly ( */*).

Esempio di codice di una funzione del sistema di autorizzazione Lambda basata su token che restituisce una variabile "Resource" con caratteri jolly

exports.handler =  function(event, context, callback) {
    var token = event.authorizationToken;
    var tmp = event.methodArn.split(':');
    var apiGatewayArnTmp = tmp[5].split('/');

    // Create wildcard resource
    var resource = tmp[0] + ":" + tmp[1] + ":" + tmp[2] + ":" + tmp[3] + ":" + tmp[4] + ":" + apiGatewayArnTmp[0] + '/*/*';
    switch (token) {
        case 'allow':
            callback(null, generatePolicy('user', 'Allow', resource));
            break;
        case 'deny':
            callback(null, generatePolicy('user', 'Deny', resource));
            break;
        case 'unauthorized':
            callback("Unauthorized");   // Return a 401 Unauthorized response
            break;
        default:
            callback("Error: Invalid token"); // Return a 500 Invalid token response
    }
};
// Help function to generate an IAM policy
var generatePolicy = function(principalId, effect, resource) {
    var authResponse = {};

    authResponse.principalId = principalId;
    if (effect && resource) {
        var policyDocument = {};
        policyDocument.Version = '2012-10-17';
        policyDocument.Statement = [];
        var statementOne = {};
        statementOne.Action = 'execute-api:Invoke';
        statementOne.Effect = effect;
        statementOne.Resource = resource;
        policyDocument.Statement[0] = statementOne;
        authResponse.policyDocument = policyDocument;
    }

    // Optional output with custom properties of the String, Number or Boolean type.
    authResponse.context = {
        "stringKey": "stringval",
        "numberKey": 123,
        "booleanKey": true
    };
    return authResponse;
}

Esempio di codice di una funzione del sistema di autorizzazione Lambda basata su parametri di richiesta che restituisce una variabile "Resource" con caratteri jolly

exports.handler = function(event, context, callback) {        

    // Retrieve request parameters from the Lambda function input:
    var headers = event.headers;
    var queryStringParameters = event.queryStringParameters;
    var pathParameters = event.pathParameters;
    var stageVariables = event.stageVariables;

    // Parse the input for the parameter values
    var tmp = event.methodArn.split(':');
    var apiGatewayArnTmp = tmp[5].split('/');

    // Create wildcard resource
    var resource = tmp[0] + ":" + tmp[1] + ":" + tmp[2] + ":" + tmp[3] + ":" + tmp[4] + ":" + apiGatewayArnTmp[0] + '/*/*';
    console.log("resource: " + resource);
    // if (apiGatewayArnTmp[3]) {
    //     resource += apiGatewayArnTmp[3];
    // }

    // Perform authorization to return the Allow policy for correct parameters and
    // the 'Unauthorized' error, otherwise.
    var authResponse = {};
    var condition = {};
    condition.IpAddress = {};


    if (headers.headerauth1 === "headerValue1"
        && queryStringParameters.QueryString1 === "queryValue1"
        && stageVariables.StageVar1 === "stageValue1") {
        callback(null, generateAllow('me', resource));
    }  else {
        callback("Unauthorized");
    }
}

// Help function to generate an IAM policy
var generatePolicy = function(principalId, effect, resource) {
    // Required output:
    console.log("Resource in generatePolicy(): " + resource);
    var authResponse = {};
    authResponse.principalId = principalId;
    if (effect && resource) {
        var policyDocument = {};
        policyDocument.Version = '2012-10-17'; // default version
        policyDocument.Statement = [];
        var statementOne = {};
        statementOne.Action = 'execute-api:Invoke'; // default action
        statementOne.Effect = effect;
        statementOne.Resource = resource;
        console.log("***Resource*** " + resource);
        policyDocument.Statement[0] = statementOne;
        console.log("***Generated Policy*** ");
        console.log(policyDocument);
        authResponse.policyDocument = policyDocument;
    }
    // Optional output with custom properties of the String, Number or Boolean type.
    authResponse.context = {
        "stringKey": "stringval",
        "numberKey": 123,
        "booleanKey": true
    };

    return authResponse;
}

var generateAllow = function(principalId, resource) {
    return generatePolicy(principalId, 'Allow', resource);
}

var generateDeny = function(principalId, resource) {
    return generatePolicy(principalId, 'Deny', resource);
}

Per ulteriori informazioni su come modificare il codice delle funzioni Lambda, consulta Deploying Lambda functions defined as .zip file archives.

Informazioni correlate

Testing Lambda functions in the console