Warum gibt meine API-Gateway-Proxy-Ressource mit einem Lambda-Genehmiger, bei dem das Caching aktiviert ist, den HTTP 403-Fehler „User is not authorized to access this resource“ zurück?

Lesedauer: 5 Minute
0

Meine Amazon API Gateway-Proxy-Ressource mit einem AWS Lambda-Genehmiger, bei dem Caching aktiviert ist, gibt die folgende HTTP 403-Fehlermeldung zurück: „User is not authorized to access this resource“.

Kurzbeschreibung

Hinweis: API Gateway kann aus verschiedenen Gründen Fehler 403 User is not authorized to access this resource zurückgeben. Dieser Artikel behandelt 403-Fehler im Zusammenhang mit API Gateway-Proxy-Ressourcen mit einem Lambda-Genehmiger, für den nur das Caching aktiviert ist. Informationen zum Beheben anderer Arten von 403-Fehlern findest du unter Wie behebe ich HTTP-403-Fehler von API Gateway?

Die Ausgabe eines Lambda-Genehmigers gibt eine AWS Identity and Access Management (IAM, Identitäts- und Zugriffsmanagement)-Richtlinie an API Gateway zurück. Die IAM-Richtlinie enthält ein explizites API- „Resource“ -Element des API Gateways im folgenden Format:

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

Wenn Genehmigungs-Caching auf einem Lambda-Genehmiger aktiviert ist, wird die zurückgegebene IAM-Richtlinie zwischengespeichert. Die zwischengespeicherte IAM-Richtlinie wird dann auf alle zusätzlichen API-Anforderungen angewendet, die innerhalb des angegebenen Time-to-Live-Zeitraums (TTL) des Caches gestellt werden.

Wenn die API eine Proxy-Ressource mit der gierigen Pfadvariablen {proxy+} hat, ist die erste Autorisierung erfolgreich. Alle zusätzlichen API-Anforderungen, die innerhalb des TTL-Zeitraums des Caches an einen anderen Pfad gestellt werden, schlagen fehl und geben den folgenden Fehler zurück:

„message“: „User is not authorized to access this resource“

Die zusätzlichen Anforderungen schlagen fehl, weil die Pfade nicht mit dem expliziten API-Element „Resource“ des API Gateways übereinstimmen, das in der zwischengespeicherten IAM-Richtlinie definiert ist.

Um das Problem zu beheben, kannst du den Code der Lambda-Genehmigerfunktion so ändern, dass stattdessen eine Platzhalterressource (*/*) in der Ausgabe zurückgegeben wird. Weitere Informationen findest du unter Ressourcen und Bedingungen für Lambda-Aktionen.

Hinweis: Um das Genehmiger-Caching zu aktivieren, muss der Genehmiger eine Richtlinie zurückgeben, die für alle Methoden in einem API-Gateway gilt. Der Code der Lambda-Genehmigerfunktion muss in der Ausgabe eine Platzhalterressource (*/*) zurückgeben, um alle Ressourcen zuzulassen. Die Cache-Richtlinie erwartet, dass derselbe Ressourcenpfad zwischengespeichert wird, es sei denn, du hast dieselbe Anforderung zweimal auf demselben Ressourcenpfad gestellt.

Lösung

Hinweis: Passe die Beispielcodeausschnitte für die Lambda-Genehmigerfunktion in diesem Artikel an deinen Anwendungsfall an.

In den folgenden Beispieleinrichtungen extrahieren die Lambda-Funktionen den id-Wert des API-Gateways aus dem Amazon-Ressourcennamen (ARN) der Methode („event.methodArn“). Dann definieren die Funktionen eine Platzhaltervariable „Resource“, indem sie die Pfade der Methode ARN mit dem id-Wert der API und einem Platzhalter (*/*) kombinieren.

Beispiel für einen tokenbasierten Funktionscode des Lambda-Genehmigers, der eine Platzhaltervariable „Resource“ zurückgibt

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;
}

Beispielanforderung für einen parameterbasierten Funktionscode des Lambda-Genehmigers, der eine Platzhaltervariable „Resource“ zurückgibt

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

Weitere Informationen zum Bearbeiten des Lambda-Funktionscodes findest du unter Bereitstellung von Lambda-Funktionen, die als .zip-Dateiarchive definiert sind.

Ähnliche Informationen

Testen von Lambda-Funktionen in der Konsole

AWS OFFICIAL
AWS OFFICIALAktualisiert vor 2 Monaten