캐싱이 활성화된 Lambda 권한 부여자를 포함하는 API Gateway 프록시 리소스에서 HTTP 403 'User is not authorized to access this resource' 오류를 반환하는 이유는 무엇인가요?

5분 분량
0

캐싱이 활성화된 AWS Lambda authorizer가 있는 Amazon API Gateway 프록시 리소스에서 HTTP 403 오류 메시지 'User is not authorized to access this resource'를 반환합니다. 왜 이런 현상이 발생하며, 이 오류를 해결하려면 어떻게 해야 합니까?

간략한 설명

참고: API Gateway는 다양한 이유로 403 사용자에게 이 리소스 오류에 액세스할 권한이 없음 오류를 반환할 수 있습니다. 이 문서에서는 캐싱이 활성화된 Lambda 권한 부여자만 포함하는 API Gateway 프록시 리소스와 관련된 403 오류를 다룹니다. 다른 403 오류 유형을 해결하는 방법에 대한 자세한 내용은 API Gateway의 HTTP 403 오류를 해결하려면 어떻게 해야 하나요?를 참조하세요.

Lambda 권한 부여자의 출력은 AWS Identity and Access Management(IAM) 정책을 API Gateway로 반환합니다. IAM 정책에는 다음과 같은 형식의 명시적 API Gateway API 'Resource' 요소가 포함되어 있습니다.

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

Lambda 권한 부여자에서 **권한 부여 캐싱(Authorization Caching)**이 활성화되면 반환된 IAM 정책이 캐싱됩니다. 그러면 캐싱된 IAM 정책이 캐시의 지정된 유지 시간(TTL) 내에 생성된 모든 추가 API 요청에 적용됩니다.

API에 **{proxy+}**와 같은 복잡한 경로 변수의 프록시 리소스가 있으면 첫 번째 권한 부여에 성공합니다. 이때 캐시의 TTL 기간 내에 다른 경로에 대한 추가 API 요청은 실패하고 다음 오류를 반환합니다.

"message": "사용자에게 이 리소스에 액세스할 권한이 없음"

경로가 캐싱된 IAM 정책에 정의된 명시적 API Gateway API 'Resource' 요소와 일치하지 않기 때문에 추가 요청이 실패합니다.

이 문제를 해결하려면 대신 출력에서 와일드카드(*/*) 리소스를 반환하도록 Lambda 권한 부여자 함수의 코드를 수정할 수 있습니다. 자세한 내용은 Lambda 작업에 대한 리소스 및 조건을 참조하세요.

참고: 권한 부여자 캐싱을 활성화하려면 권한 부여자가 API Gateway의 모든 메서드에 적용되는 정책을 반환해야 합니다. 모든 리소스를 허용하려면 Lambda 권한 부여자 함수의 코드가 와일드카드(*/*) 리소스를 출력에 반환해야 합니다. 동일한 리소스 경로에서 동일한 요청을 보내지 않는 한, 캐시 정책은 동일한 리소스 경로가 캐싱될 것으로 예상합니다.

해결 방법

참고: 사용 사례에 맞게 이 문서의 Lambda 권한 부여자 함수 코드 조각 예시를 수정해야 할 수도 있습니다.

다음 예제 설정에서 Lambda 함수는 메서드의 Amazon 리소스 이름(ARN)('event.methodArn')에서 API Gateway의 id을 추출합니다. 그런 다음, 함수는 메서드 ARN의 경로와 API의 id 값 및 와일드카드(*/*)를 결합하여 와일드카드 define a wildcard 'Resource' 변수를 정의합니다.

와일드카드 'Resource' 변수를 반환하는 토큰 기반 Lambda 권한 부여자 함수 코드 예시

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

와일드카드 'Resource' 변수를 반환하는 요청 파라미터 기반 Lambda 권한 부여자 함수 코드 예시

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

Lambda 함수 코드를 편집하는 방법에 대한 자세한 내용은 .zip 파일 아카이브로 정의된 Lambda 함수 배포를 참조하세요.


관련 정보

콘솔 편집기를 사용하여 코드 편집

댓글 없음

관련 콘텐츠