TL;DR
- Используйте API ValidatePolicy AWS IAM Access Analyzer в CI/CD для обнаружения чрезмерно разрешающих политик до деплоя—это бесплатно и обнаруживает грамматические ошибки плюс нарушения лучших практик
- Комбинируйте статический анализ (Checkov) с симуляцией политик (IAM Policy Simulator) для полного покрытия—статический обнаруживает паттерны, симуляция обнаруживает runtime поведение
- Cross-cloud IAM тестирование требует разных инструментов: AWS Access Analyzer, Azure Policy Insights, GCP Policy Analyzer имеют уникальные возможности
Идеально для: Команд, управляющих IAM политиками в IaC, которым нужно предотвратить эскалацию привилегий и обеспечить минимальные привилегии Не подходит если: Вы используете managed identity сервисы, где политики абстрагированы (например, AWS SSO с готовыми permission sets) Время чтения: 14 минут
Чрезмерно разрешающие IAM политики остаются одной из главных причин облачных breaches. Один "Resource": "*" или отсутствующее условие может раскрыть всю вашу AWS учётную запись. Исследования показывают, что 82% облачных misconfigurations происходят из-за человеческих ошибок—делая автоматизированное тестирование IAM политик необходимым, а не опциональным.
Для более широкого контекста тестирования инфраструктуры, смотрите Тестирование Policy as Code и Тестирование Compliance для IaC.
Подходы с Использованием ИИ
Инструменты ИИ отлично справляются с анализом сложных IAM политик и генерацией комплексных тестовых наборов.
Анализ IAM политик на чрезмерные разрешения:
Проанализируй эту AWS IAM политику на проблемы безопасности:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:*"],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": ["iam:PassRole"],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": ["ec2:*"],
"Resource": "*",
"Condition": {
"StringEquals": {"ec2:Region": "us-east-1"}
}
}
]
}
Определи: Риски эскалации привилегий, чрезмерно широкие разрешения,
отсутствующие условия, и предоставь альтернативу с минимальными
привилегиями для роли CI/CD пайплайна.
Генерация тест-кейсов для IAM политик:
Сгенерируй pytest тест-кейсы для валидации AWS IAM политик с использованием boto3:
1. Проверить, что никакие политики не разрешают iam:* или iam:PassRole к Resource "*"
2. Проверить, что S3 политики требуют условия шифрования
3. Убедиться, что никакие политики не разрешают assume-role к внешним аккаунтам без условий
4. Валидировать, что admin политики прикреплены только к break-glass ролям
Включи правильную настройку AWS сессии, парсинг документов политик и чёткие assertions.
Создание кастомных проверок Checkov:
Напиши кастомную проверку Checkov на Python, которая валидирует:
1. IAM политики не должны разрешать actions, заканчивающиеся на "*" (например, s3:*, ec2:*)
2. Все iam:PassRole statements должны иметь явные Resource ARNs
3. Политики с административными actions должны иметь MFA условия
4. Cross-account trust политики должны указывать явные account IDs
Включи класс проверки, логику оценки и поддерживаемые типы ресурсов.
Когда Использовать Разные Подходы к Тестированию
Фреймворк Принятия Решений по Стратегии Тестирования
| Тип Теста | Инструмент | Когда Запускать | Что Обнаруживает |
|---|---|---|---|
| Валидация грамматики | IAM Access Analyzer | Pre-commit, CI | Синтаксические ошибки, устаревшие элементы |
| Лучшие практики | Access Analyzer ValidatePolicy | CI пайплайн | Чрезмерно разрешающие actions, отсутствующие условия |
| Статический анализ | Checkov, cfn-nag | Pre-commit, CI | Известные плохие паттерны (Resource: “*”) |
| Симуляция политик | IAM Policy Simulator | Pre-deploy | Реальное поведение разрешений |
| Анализ доступа | Находки Access Analyzer | Непрерывно | Внешний доступ, неиспользуемые разрешения |
| Кастомные правила | OPA/Rego | CI пайплайн | Специфичные требования организации |
Критические Проверки IAM Политик
| Check ID | Описание | Уровень Риска |
|---|---|---|
| CKV_AWS_1 | IAM политики не должны разрешать полные административные привилегии “*” | Критический |
| CKV_AWS_49 | IAM политики не должны разрешать PassRole к “*” | Критический |
| CKV_AWS_40 | IAM политики не должны разрешать эскалацию привилегий | Критический |
| CKV_AWS_62 | IAM политики не должны иметь пустой SID | Низкий |
| CKV_AWS_109 | IAM политики не должны разрешать раскрытие credentials | Высокий |
| CKV_AWS_110 | IAM политики не должны разрешать управление разрешениями без ограничений | Высокий |
Тестирование AWS IAM Политик
Валидация Политик с IAM Access Analyzer
# Установка Terraform IAM Policy Validator
pip install tf-policy-validator
# Валидация Terraform шаблона
tf-policy-validator validate \
--template-path ./terraform \
--region us-east-1
# Запуск конкретных проверок
tf-policy-validator validate \
--template-path ./terraform \
--region us-east-1 \
--check-type VALIDATE_POLICY \
--check-type CHECK_NO_NEW_ACCESS
Интеграция с GitHub Actions
name: Валидация IAM Политик
on:
pull_request:
paths:
- 'terraform/**/*.tf'
- 'cloudformation/**/*.yaml'
jobs:
validate-iam-policies:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Настройка AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1
- name: Валидация Terraform IAM Политик
uses: aws-actions/terraform-aws-iam-policy-validator@v1
with:
template-path: terraform/
region: us-east-1
check-no-new-access: true
check-access-not-granted: true
check-no-public-access: true
- name: Запуск Checkov
uses: bridgecrewio/checkov-action@v12
with:
directory: terraform/
check: CKV_AWS_1,CKV_AWS_40,CKV_AWS_49,CKV_AWS_109,CKV_AWS_110
framework: terraform
Checkov для IAM Политик
# Установка Checkov
pip install checkov
# Сканирование на IAM-специфичные проблемы
checkov -d ./terraform --check CKV_AWS_1,CKV_AWS_40,CKV_AWS_49
# Вывод в JUnit для CI
checkov -d ./terraform --framework terraform \
--check CKV_AWS_1,CKV_AWS_40,CKV_AWS_49,CKV_AWS_109,CKV_AWS_110 \
--output junitxml > iam-checkov-results.xml
Кастомная Проверка Checkov
# custom_checks/iam_no_passrole_star.py
from checkov.terraform.checks.resource.base_resource_check import BaseResourceCheck
from checkov.common.models.enums import CheckResult, CheckCategories
import json
class IAMNoPassRoleStar(BaseResourceCheck):
def __init__(self):
name = "Убедиться, что IAM политики не разрешают PassRole ко всем ресурсам"
id = "CKV_CUSTOM_IAM_1"
supported_resources = ['aws_iam_policy', 'aws_iam_role_policy']
categories = [CheckCategories.IAM]
super().__init__(name=name, id=id, categories=categories,
supported_resources=supported_resources)
def scan_resource_conf(self, conf):
policy = conf.get('policy', [None])[0]
if not policy:
return CheckResult.UNKNOWN
# Обработка форматов string и dict
if isinstance(policy, str):
try:
policy = json.loads(policy)
except json.JSONDecodeError:
return CheckResult.UNKNOWN
statements = policy.get('Statement', [])
for statement in statements:
if statement.get('Effect') != 'Allow':
continue
actions = statement.get('Action', [])
if isinstance(actions, str):
actions = [actions]
resources = statement.get('Resource', [])
if isinstance(resources, str):
resources = [resources]
# Проверка на PassRole с ресурсом *
has_passrole = any('PassRole' in action for action in actions)
has_star_resource = '*' in resources
if has_passrole and has_star_resource:
return CheckResult.FAILED
return CheckResult.PASSED
check = IAMNoPassRoleStar()
Тестирование Политик на Python с boto3
import boto3
import json
import pytest
class TestIAMPolicies:
@pytest.fixture
def iam_client(self):
return boto3.client('iam')
@pytest.fixture
def access_analyzer_client(self):
return boto3.client('accessanalyzer')
def test_no_admin_star_policies(self, iam_client):
"""Проверить, что никакие политики не дают полный admin доступ."""
paginator = iam_client.get_paginator('list_policies')
for page in paginator.paginate(Scope='Local'):
for policy in page['Policies']:
version = iam_client.get_policy_version(
PolicyArn=policy['Arn'],
VersionId=policy['DefaultVersionId']
)
document = version['PolicyVersion']['Document']
statements = document.get('Statement', [])
for stmt in statements:
if stmt.get('Effect') != 'Allow':
continue
actions = stmt.get('Action', [])
if isinstance(actions, str):
actions = [actions]
resources = stmt.get('Resource', [])
if isinstance(resources, str):
resources = [resources]
# Ошибка если Action: "*" и Resource: "*"
assert not (
'*' in actions and '*' in resources
), f"Политика {policy['PolicyName']} имеет admin привилегии"
def test_validate_policy_with_access_analyzer(self, access_analyzer_client):
"""Использовать Access Analyzer для валидации политики."""
policy_document = {
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": ["s3:GetObject"],
"Resource": "arn:aws:s3:::my-bucket/*"
}]
}
response = access_analyzer_client.validate_policy(
policyDocument=json.dumps(policy_document),
policyType='IDENTITY_POLICY'
)
# Проверка на ошибки и предупреждения безопасности
findings = response.get('findings', [])
errors = [f for f in findings if f['findingType'] == 'ERROR']
security_warnings = [f for f in findings
if f['findingType'] == 'SECURITY_WARNING']
assert len(errors) == 0, f"Ошибки валидации политики: {errors}"
assert len(security_warnings) == 0, f"Предупреждения безопасности: {security_warnings}"
Тестирование с IAM Policy Simulator
def test_policy_denies_unauthorized_actions(iam_client):
"""Симулировать политику для проверки запрещённых действий."""
# Проверить, что роль разработчика не может получить доступ к production
response = iam_client.simulate_principal_policy(
PolicySourceArn='arn:aws:iam::123456789012:role/DeveloperRole',
ActionNames=[
'ec2:TerminateInstances',
's3:DeleteBucket',
'iam:CreateUser'
],
ResourceArns=[
'arn:aws:ec2:us-east-1:123456789012:instance/*',
'arn:aws:s3:::production-*',
'arn:aws:iam::123456789012:user/*'
]
)
for result in response['EvaluationResults']:
assert result['EvalDecision'] == 'implicitDeny', \
f"Роль разработчика не должна иметь разрешение {result['EvalActionName']}"
def test_policy_allows_required_actions(iam_client):
"""Проверить, что роль имеет необходимые разрешения."""
response = iam_client.simulate_principal_policy(
PolicySourceArn='arn:aws:iam::123456789012:role/CICDRole',
ActionNames=[
's3:PutObject',
'ecr:PushImage',
'ecs:UpdateService'
],
ResourceArns=[
'arn:aws:s3:::deployment-artifacts/*',
'arn:aws:ecr:us-east-1:123456789012:repository/my-app',
'arn:aws:ecs:us-east-1:123456789012:service/my-cluster/my-service'
]
)
for result in response['EvaluationResults']:
assert result['EvalDecision'] == 'allowed', \
f"CICD роль без требуемого разрешения: {result['EvalActionName']}"
Тестирование Azure IAM
Azure Policy для Валидации RBAC
# Список кастомных определений ролей
az role definition list --custom-role-only true --output table
# Проверка назначений ролей
az role assignment list --scope /subscriptions/<sub-id> --output table
# Валидация с Azure Policy
az policy assignment list --query "[?policyDefinitionId contains 'rbac']"
InSpec для Azure RBAC
control 'azure-no-owner-custom-roles' do
impact 1.0
title 'Кастомные роли не должны иметь разрешений эквивалентных Owner'
azure_role_definitions.where(role_type: 'CustomRole').ids.each do |role_id|
describe azure_role_definition(name: role_id) do
its('permissions.first.actions') { should_not include '*' }
its('permissions.first.not_actions') { should_not be_empty }
end
end
end
control 'azure-no-subscription-owner-assignments' do
impact 1.0
title 'Роль Owner не должна назначаться на уровне подписки'
describe azure_role_assignments.where(
scope: "/subscriptions/#{input('subscription_id')}",
role_name: 'Owner'
) do
its('count') { should be <= 2 } # Разрешить только break-glass аккаунты
end
end
Тестирование GCP IAM
GCP Policy Analyzer
# Анализ IAM политики проекта
gcloud policy-intelligence analyze-iam-policy \
--project=my-project \
--full-resource-name="//cloudresourcemanager.googleapis.com/projects/my-project"
# Проверка на чрезмерно разрешающие bindings
gcloud projects get-iam-policy my-project --format=json | \
jq '.bindings[] | select(.members[] | contains("allUsers") or contains("allAuthenticatedUsers"))'
Terraform Валидация для GCP IAM
# variables.tf - Определение разрешённых ролей
variable "allowed_project_roles" {
type = list(string)
default = [
"roles/viewer",
"roles/editor",
# Явно перечислить разрешённые роли
]
}
# Валидация в ресурсе
resource "google_project_iam_binding" "binding" {
project = var.project_id
role = var.role
members = var.members
lifecycle {
precondition {
condition = contains(var.allowed_project_roles, var.role)
error_message = "Роль ${var.role} не в списке разрешённых ролей."
}
precondition {
condition = !contains(var.members, "allUsers") && !contains(var.members, "allAuthenticatedUsers")
error_message = "Публичные IAM bindings (allUsers/allAuthenticatedUsers) не разрешены."
}
}
}
Интеграция CI/CD
Полный Workflow GitHub Actions
name: Безопасность IAM Политик
on:
pull_request:
paths:
- 'terraform/iam/**'
- 'policies/**'
jobs:
static-analysis:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Запуск IAM проверок Checkov
uses: bridgecrewio/checkov-action@v12
with:
directory: terraform/iam/
check: CKV_AWS_1,CKV_AWS_40,CKV_AWS_49,CKV_AWS_109,CKV_AWS_110
output_format: sarif
output_file_path: checkov-iam.sarif
- name: Загрузка SARIF
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: checkov-iam.sarif
access-analyzer:
runs-on: ubuntu-latest
needs: static-analysis
steps:
- uses: actions/checkout@v4
- name: Настройка AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: us-east-1
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
- name: Terraform Init
run: terraform init
working-directory: terraform/iam/
- name: Валидация с Access Analyzer
uses: aws-actions/terraform-aws-iam-policy-validator@v1
with:
template-path: terraform/iam/
region: us-east-1
check-no-new-access: true
policy-simulation:
runs-on: ubuntu-latest
needs: access-analyzer
if: github.event.pull_request.draft == false
steps:
- uses: actions/checkout@v4
- name: Настройка AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: us-east-1
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Установка зависимостей
run: pip install boto3 pytest
- name: Запуск тестов симуляции политик
run: pytest tests/iam/ -v --tb=short
Измерение Успеха
| Метрика | До Тестирования | После Тестирования | Как Отслеживать |
|---|---|---|---|
| Чрезмерно разрешающие политики | Найдены на аудитах | 0 в production | Отчёты Checkov |
| Пути эскалации привилегий | Неизвестны | 0 обнаружено | Находки Access Analyzer |
| Время валидации политик | Ручная проверка (часы) | Автоматизировано (минуты) | Метрики CI/CD |
| Неиспользуемые разрешения | Накапливаются со временем | Квартальная очистка | Access Analyzer |
Сигналы, что ваше IAM тестирование не работает:
- Checkov проходит, но находки Access Analyzer в production
- “Экстренные” изменения политик обходят CI/CD
- Роли накапливают разрешения со временем
- Service accounts с admin привилегиями
Заключение
Эффективное тестирование IAM политик требует нескольких уровней валидации:
- Статический анализ (Checkov) обнаруживает известные плохие паттерны в коде
- Валидация грамматики (Access Analyzer ValidatePolicy) обеспечивает синтаксис и структуру политик
- Симуляция политик (IAM Policy Simulator) проверяет реальное поведение разрешений
- Непрерывный анализ (находки Access Analyzer) обнаруживает drift и неиспользуемые разрешения
Ключевая идея: IAM политики слишком критичны для только ручной проверки. Автоматизированное тестирование в CI/CD пайплайнах обнаруживает проблемы до достижения production, а непрерывный мониторинг обнаруживает drift политик со временем.
Смотрите также
- Тестирование Policy as Code - OPA и Sentinel для кастомных IAM правил
- Тестирование Security Groups - Тестирование контроля доступа на сетевом уровне
- Тестирование Compliance для IaC - Выполнение регуляторных IAM требований
- Стратегии Тестирования Terraform - Полная пирамида тестирования IaC
- Тестирование Инфраструктуры AWS - Более широкие стратегии тестирования AWS
