При развертывании лямбда-функции в VPC вам необходимо предоставить набор разрешений, связанных с сетевым интерфейсом, для роли выполнения лямбда-выражения. Руководства по AWS совет использовать для этого управляемую политику AWSLambdaVPCAccessExecutionRole, которая выглядит так:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents",
"ec2:CreateNetworkInterface",
"ec2:DescribeNetworkInterfaces",
"ec2:DeleteNetworkInterface",
"ec2:AssignPrivateIpAddresses",
"ec2:UnassignPrivateIpAddresses"
],
"Resource": "*"
}
]
}
Как видите, эта политика не ограничивает сетевые интерфейсы, которые может изменять лямбда, что потенциально позволяет ему вмешиваться в работу сети за пределами собственного VPC. Я хотел бы ограничить действия, которые лямбда может выполнять, для VPC или подсетей, в которых она фактически развернута. Однако до сих пор мне не удалось разработать рабочую политику для этого.
Пробовал проверить VPC в политике так:
"Condition": {"StringEquals": {"ec2:Vpc": "${my_vpc_arn}" }}
но все равно получил отказ в разрешении.
Событие CloudTrail содержит следующее сообщение авторизации), расшифрованное с помощью aws sts decode-authorization-message
): https://pastebin.com/P9t3QWEY, где я не вижу полезных ключей для проверки.
Итак, можно ли ограничить лямбду, развернутую в VPC, только изменением определенных сетевых интерфейсов?
Служба Lambda должна иметь возможность создавать и удалять сетевые интерфейсы в вашем VPC. Это связано с тем, что общий ENI будет развернут в VPC. Как только все контексты выполнения будут завершены, этот общий ENI будет снова удален. Это также объясняет, почему необходимы разрешения на описание, поскольку службе, вероятно, необходимо выяснить, развернут ли уже общий ENI для конкретной лямбда-функции.
К сожалению, это означает, что вы не можете ограничить операции удаления/изменения какими-либо конкретными ENI, поскольку они создаются и удаляются динамически.
В соответствии с документацией конкретные разрешения, необходимые для роли:
Я проверил документацию, и действия «Создать + Удалить» позволяют (среди прочего) выполнять следующие условия:
Это означает, что это должно быть возможно. Возможно, вам поможет разделение разрешений ec2:*
на отдельное выражение с вышеупомянутыми условиями.
Вы не можете ограничить политику отдельными сетевыми интерфейсами, поскольку вы не знаете их идентификаторы до тех пор, пока не создадите их. Но вы должны иметь возможность ограничить доступ к определенному VPC, используя следующую политику выполнения лямбда:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AccessToSpecificVPC",
"Effect": "Allow",
"Action": [
"ec2:CreateNetworkInterface",
"ec2:DeleteNetworkInterface",
"ec2:UnassignPrivateIpAddresses",
"ec2:AssignPrivateIpAddresses",
"ec2:DescribeNetworkInterfaces"
],
"Resource": "*",
"Condition": {
"ArnLikeIfExists": {
"ec2:Vpc": "arn:aws:ec2:<your-region>:<your-account-id>:vpc/<vpc-id>"
}
}
},
{
"Sid": "CWLogsPermissions",
"Effect": "Allow",
"Action": [
"logs:CreateLogStream",
"logs:CreateLogGroup",
"logs:PutLogEvents"
],
"Resource": "*"
}
]
}
С частью «IfExists» это действительно работает, спасибо! Однако мне интересно, действительно ли это означает, что изменение интерфейса при создании лямбды отличается от его обновления в качестве обычного пользователя/роли IAM. т.е. когда я выдаю ec2: CreateNetworkInterface, в запросе будет ключ ec2: Vpc, а во время развертывания лямбда - нет. Если это так, то это решение правильное.
@demosito Вы можете получить больше информации о ifExists
здесь. Как там объясняется, иногда для выполнения некоторых действий требуется доступ к различным ресурсам. Без IfExist
условие будет применяться для каждого такого ресурса, даже если он может не поддерживать такое условие, что приведет к отказу. Ifexists
применяет условия к ресурсам и действиям, которые предоставляют такой ключ условия.
Я понимаю это, однако условие без IfExists
не работает, даже если «Действие» содержит одну запись (я тестировал с ec2:CreateNetworkInterface). Это означает, что ключ ec2:Vpc
действительно отсутствует в этом запросе, хотя согласно документации должен. Что приводит меня к выводу, что при развертывании лямбда-функции эти действия выполняются как-то иначе.
Спасибо за ваш ответ, но, как я уже сказал, я попытался проверить точные предложенные вами условия (ec2:Vpc и ec2:Subnet) с помощью «Condition»: {«StringEquals»: {«ec2:Vpc»: «${my_vpc_arn }" }}, но это вызвало ошибку PermissionDenied. Похоже, что эти ключи по какой-то причине не устанавливаются в запросах.