Perché la mia risorsa proxy API Gateway con un sistema di autorizzazione Lambda con la memorizzazione nella cache attivata restituisce gli errori HTTP 403 "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 memorizzazione nella cache attivata restituisce il seguente messaggio di errore HTTP 403: "L'utente non è autorizzato ad accedere a questa risorsa". Perché si verifica questo problema e come posso risolverlo?

Breve descrizione

Nota: API Gateway può restituire gli errori 403 L'utente non è autorizzato ad accedere a questi errori di risorsa per una serie di motivi. Questo articolo affronta errori 403 relativi alle risorse proxy API Gateway con un sistema di autorizzazione Lambda con solamente la memorizzazione nella cache attivata. Per informazioni sulla risoluzione di altri tipi di errori 403, consulta In che modo posso risolvere gli errori HTTP 403 da API Gateway?

Un output di un sistema di autorizzazione Lambda restituisce una policy AWS Identity and Access Management (IAM) ad API Gateway. La policy IAM include un elemento API**"Resource"** di API Gateway esplicito nel seguente formato:

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

Quando la memorizzazione nella cache delle autorizzazioni è attivata su un sistema di autorizzazione Lambda, 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 di durata (TTL) specificato della cache.

Se l'API ha una risorsa proxy con una variabile di percorso greedy di {proxy+}, la prima autorizzazione ha esito positivo. Eventuali richieste API aggiuntive effettuate su un percorso diverso all'interno del periodo TTL della cache non riescono e restituiscono il seguente errore:

"messaggio": "L'utente non è autorizzato ad accedere a questa risorsa"

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

Per risolvere il problema, puoi modificare il codice della funzione del sistema di autorizzazione Lambda per restituire invece una risorsa jolly (*/*) nell'output. Per ulteriori informazioni, consulta Risorse e condizioni per le operazioni Lambda.

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

Risoluzione

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

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

Esempio di codice della funzione del sistema di autorizzazione Lambda basato su token che restituisce una variabile jolly "Resource"

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 funzione del sistema di autorizzazione Lambda basato su parametri di richiesta che restituisce una variabile jolly "Resource"

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 funzione Lambda, consulta Implementazione di funzioni Lambda definite come archivi di file .zip.


Informazioni correlate

Modifica il codice utilizzando l'editor della console