Lambda@Edge IAM — 리전 제약

클라우드·인프라3분조회 –

Lambda@Edge 함수를 조회만 할 수 있는 IAM 정책을 만들어 붙였고, 그 권한으로 콘솔에서 함수를 열자 AccessDenied 가 났습니다.

CloudFront 앞에서 경로를 다시 쓰거나 헤더를 붙이려고 올려 둔 함수고, Lambda@Edge 는 엣지 로케이션에서 돌고 함수 자체는 어느 리전에서든 만들 수 있지만 CloudFront 에 붙이려면 us-east-1 에 있어야 합니다.

함수가 거기밖에 없으니 다른 리전을 열어 줄 이유가 없다고 보고, 정책도 us-east-1 리소스만 열어 줬습니다. 권한을 최소로 주는 건 기본이고 이런 조회용 정책은 나중에 사람이 늘어나도 그대로 쓰게 되니, 처음에 좁게 잡아 두는 편입니다.

함수는 us-east-1, 조회는 서울 리전으로

Action: lambda:GetFunction
On resource(s): arn:aws:lambda:ap-northeast-2:...:function:my-edge-function
Context: no identity-based policy allows the action

함수는 us-east-1 에만 배포됐고 정책도 us-east-1 만 허용했는데, 에러에 찍힌 리소스 ARN 은 ap-northeast-2(서울)입니다.

AWS 콘솔이 함수를 열 때 현재 보고 있는 리전으로도 GetFunction 을 던집니다. 서울 리전에서 콘솔을 보고 있으면 서울로도 조회가 가고 거기에 권한이 없으니 거부됩니다.

서울 리전 ARN 을 Resource 에 넣되, 그 함수 하나로만 좁힙니다.

{
  "Sid": "AllowReadOnlyThatOneInSeoul",
  "Effect": "Allow",
  "Action": [
    "lambda:GetFunction",
    "lambda:GetFunctionConfiguration",
    "lambda:ListVersionsByFunction"
  ],
  "Resource": [
    "arn:aws:lambda:ap-northeast-2:123456789012:function:my-edge-function",
    "arn:aws:lambda:ap-northeast-2:123456789012:function:my-edge-function:*"
  ]
}

리전이 ap-northeast-2 로 적혀 있지만 거기엔 함수가 없으니 이 줄로 실제로 열리는 건 없습니다. 콘솔이 서울로 던지는 조회가 AccessDenied 대신 빈 결과로 끝나게 해 줄 뿐입니다.

ListFunctions — 리소스 단위 제한 불가

리전을 맞춰 준 뒤에도 목록이 안 보였습니다.

Action: lambda:ListFunctions
Context: no identity-based policy allows the action

ListFunctions 는 리소스 단위 제한이 안 되는 액션이라 특정 함수 ARN 을 Resource 에 적을 수 없고 "*" 를 써야 합니다.

"*" 를 그냥 열면 모든 리전의 모든 함수 목록이 열려서 리전 조건으로 범위를 좁혔습니다.

{
  "Sid": "AllowListInUsEast1",
  "Effect": "Allow",
  "Action": "lambda:ListFunctions",
  "Resource": "*",
  "Condition": {
    "StringEquals": { "aws:RequestedRegion": "us-east-1" }
  }
}

그러면서 서울 리전 목록은 Explicit Deny 로 막았습니다.

{
  "Sid": "DenyListInSeoul",
  "Effect": "Deny",
  "Action": "lambda:ListFunctions",
  "Resource": "*",
  "Condition": {
    "StringEquals": { "aws:RequestedRegion": "ap-northeast-2" }
  }
}

리소스로 못 좁히는 액션은 조건으로 좁히면 되고, aws:RequestedRegion 이 그럴 때 쓰는 조건 키입니다.

다 맞는데도 막힘 — 상위 제약(Boundary·세션 정책)

여기까지 맞추고도 계속 거부되면 정책 위에 얹힌 제약을 봐야 합니다.

Permissions Boundary 가 역할에 걸려 있으면 정책에서 허용해도 경계가 그 액션을 안 열어 주는 한 막히니, 경계 쪽에도 같은 허용이 있어야 통과합니다. AssumeRole 로 받은 세션에 세션 정책이 씌워져 있을 때도 마찬가지고, 세션 정책은 교집합으로 작동해서 역할 정책이 아무리 넓어도 세션 쪽이 좁으면 좁은 쪽이 이깁니다.

identity 정책과 경계·세션 정책이 겹치는 범위만 남고, 어디든 명시적 Deny 가 하나 있으면 거기서 끝나니, identity 정책만 들여다보면 왜 막히는지 안 보입니다. 정책상 분명히 허용했는데도 AccessDenied 가 나면 경계와 세션 정책을 확인하는 게 다음 순서입니다.

참고

  1. 불러오는 중