Надлишкові права доступу: де ламаються IAM-політики S3
Права, надані під завдання «на час», майже ніколи не відкликають. Сервісному акаунту додають s3:GetObject на весь бакет, щоб разово вивантажити звіт: звіт поїхав, завдання закрито — а правило залишилося в політиці.
Через кілька релізів таких «тимчасових» записів десятки, і вже ніхто не пам'ятає, який із них чому служить.
Звичайний моніторинг цього не зловить: він дивиться на коди відповідей, час відгуку й доступність, а надлишковий доступ не дає ні помилок, ні сплесків. Запити валідні, відповіді успішні, графіки рівні — тривог немає, хоча дані давно читає той, кому вони не призначені. Публічний доступ до об'єктів небезпечний саме цим: сховище працює штатно, а відмова вже сталася.
Ламається все на трьох типових місцях. Символ підстановки в Resource або Action — політика виглядає вузькою за назвою, але покриває весь бакет. Відсутність Condition за джерелом запиту: правило не прив'язане ні до мережі, ні до конкретної ролі.
І ACL на рівні окремого об'єкта, який розширює доступ всупереч політиці бакета, якщо ніде не стоїть явна заборона.
Лікується це не разовим чищенням, а режимом: принцип найменших привілеїв плюс регулярний аудит доступу до сховища — звірка наданих прав із тими, що реально використовуються за логами звернень. Розбираємо, як це вибудувати так, щоб «тимчасове» перестало ставати постійним.
Що перестає ламатися після суворих політик доступу
Явна заборона в політиці корзини перебиває будь-який дозвіл, тому контур спочатку закривається повністю, а доступ видається точково. Політика на корзині відповідає за те, що можна робити з об'єктами: за префіксом, з яких мереж, лише захищеним каналом.
IAM-правила відповідають за те, кому це доступно. Поки рівні змішані, права висять на акаунті, а не на ролі.
| Клас відмови | Як виникав | Що стало після політик |
|---|---|---|
| Доступ живе після звільнення | права на особистому акаунті | роль виключено з групи — доступ закрито |
| Дані виходять із закритого контуру | прапорець публічного доступу на об'єкті | публічний доступ заборонено на рівні корзини |
| Читання чужих префіксів | одна широка політика на всіх | доступ видано за префіксом і роллю |
Видача доступу стає операцією на хвилини: роль із потрібним набором прав описана як код у Terraform, її залишається призначити співробітнику. Відкликання прав при звільненні — одне виключення з групи, закриваються й довгоживучі ключі, і тимчасові токени.
Зміна ролі співробітника всередині команди перестає вимагати нової заявки: права перезбираються під час переведення.
Частка даних у закритому контурі зростає не за рахунок ручних перевірок, а тому що публічний доступ заборонено на самій корзині й обійти його випадковим прапорцем не можна.
Зникають зовсім: читання чужих префіксів, доступ після звільнення, об'єкт у відкритому доступі через помилку в скрипті.
Способи розмежування доступу: порівняння варіантів
Розмежування доступу в об'єктному сховищі вирішується на чотирьох рівнях — від IAM-політик провайдера до власної перевірки перед видачею посилання. Вибір залежить від того, хто запитує об'єкт: внутрішній сервіс, зовнішній партнер або браузер кінцевого користувача.
Жоден рівень не закриває завдання повністю. Правила провайдера не знають вашої бізнес-логіки, а власна перевірка не рятує від обходу через пряму адресу. Тому рівні комбінують: знизу жорстка основа, зверху точкові винятки.
| Варіант | Коли підходить | Обмеження |
|---|---|---|
| Правила провайдера (IAM) | Сервісні облікові записи всередині платформи, доступ на читання або запис повністю | Немає контексту застосунку, права роздаються широкими групами |
| Правила рівня бакета | Публічний або партнерський обмін, один набір умов на весь контейнер | Гранулярність до окремого об'єкта обмежена, ізоляція досягається дробленням бакетів |
| Правила рівня об'єкта й тимчасові посилання на файли | Видача файлу конкретному користувачу на короткий строк, без розкриття ключів | Посилання не можна відкликати до закінчення строку: при витоку вона працює в будь-кого |
| Власний шар авторизації перед видачею посилання | Ролі, власники, орендарі, аудит кожного звернення | Додатковий сервіс у критичному шляху — потрібен запас щодо відмовостійкості |
Як вибрати рівень
Якщо правило описується однією умовою, тримайте його на боці провайдера. Якщо рішення залежить від даних у вашій базі — виносьте перевірку у власний шар, а тимчасове посилання робіть короткоживучим.
Порядок впровадження: від інвентаризації до передачі
Починаємо з фактів, а не із шаблону: інвентаризація показує, хто реально звертається до сховища — сервіси, аналітика, зовнішні підрядники. Без цієї карти схема ролей будується навмання, а перемикання політик перетворюється на пошук відмови в доступі за логами.
- Інвентаризація прав доступу. Вивантажуємо чинні bucket policy, IAM-ролі, публічні ACL та активні посилання на об'єкти, звіряємо з логами звернень. На виході — карта «хто, до якого бакета, які операції» і список зайвих дозволів.
- Схема ролей. Ролі проєктуємо під функції — читання аналітики, запис із сервісу, обмін із підрядником за окремим префіксом, — а не під конкретних людей. У кожної ролі мінімальний набір дій та умова застосування.
- Налаштування політик. Обмеження за префіксами, умова на джерело запиту, обов'язкове шифрування, заборона публічного доступу. Явна заборона перекриває випадково надані дозволи.
- Перевірка на копії даних. Тестовий контур на знеособленій копії: проганяємо читання, запис, видалення, генерацію посилань. Окремо — негативні перевірки: доступ закрито там, де він має бути закритий.
- Переведення без простою. Старі й нові політики працюють паралельно, перемикаємо за сервісами з вікном спостереження за логами відмов. Кожен крок відкочується поверненням попередньої версії конфігурації.
- Регламент. Фіксуємо, хто видає доступ, на який строк, як проходить рев'ю і що робити при звільненні або зміні підрядника. Правила зберігаються в репозиторії, зміни — через перевірку.
- Передача. Документація, схеми ролей, конфігурації в репозиторії та моніторинг відмов у доступі — щоб команда далі працювала самостійно.
Що залишається у вас на руках: конфігурації та регламенти
Ми передаємо не архів із налаштуваннями, а робочий контур доступу, який ваша команда зможе читати й змінювати без нас.
Конфігурації IAM-політик і bucket policies лежать у репозиторії поруч з інфраструктурним кодом: зміна проходить перевірку й залишається в історії — видно, хто і коли розширив права.
- Матриця доступу — таблиця «суб'єкт → ресурс → дія → умова»: за нею видно, чому конкретний сервіс або співробітник має право на потрібний префікс бакета і де межа його повноважень.
- Схема ролей — які ролі існують, чим відрізняються, які видаються людям через федерацію, а які — сервісам; окремо позначено ролі з правом змінювати самі політики.
- Робочі конфігурації — версіоновані файли політик з осмисленими іменами й коментарями замість вивантаження з консолі.
- Регламент видачі прав — порядок: заявка, погодження власником даних, строк дії, автоматичне відкликання; для постійних ролей — періодичний перегляд.
- Документація з доступу — імена бакетів, точки входу, порядок ротації облікових даних і типові помилки при зверненні.
- Опис інтеграцій — які системи звертаються до сховища, з якими правами і що станеться з ними при зміні політики.
- Процедура перевірки — набір звернень, який має проходити, і набір, який має отримувати відмову.
На виході залишається керована система, а не разове налаштування: доступ новому підряднику видається за регламентом, а при розборі інциденту є журнал змін і зрозуміла точка відкату.
Кейс: як закрили публічний доступ до об'єктного сховища
Що було до змін
Аудит почали з інвентаризації: пройшли по всіх бакетах у всіх акаунтах і звірили bucket policy, ACL та налаштування блокування публічного доступу.
Результат — 17% бакетів віддавали об'єкти анонімно: частину відкрили під швидкий запуск і не закрили, частину — коли підрядникам видавали посилання «на час».
Окрема біда — наслідування: правка політики одного бакета непомітно відкривала сусідні, і в S3-сумісному сховищі MinIO це ловилося лише ручною звіркою.
Процеси додавали своє. Права видавалися через тікети: 2-3 дні від заявки до робочого доступу, а відкликання при звільненні затягувалося до тижня — ключі весь цей час залишалися активними.
Підтримка отримувала кілька десятків звернень на місяць лише щодо доступів, і половина — «дайте те саме, що в колеги».
Що змінили і що отримали
Публічність закрили на двох рівнях: на акаунті увімкнули блокування публічних політик, а для сервісів із реальною зовнішньою аудиторією залишили точкові умови — явний список джерел і короткий строк життя посилань.
Права перевели на ролі з атрибутами: доступ визначається тегами користувача й бакета, а не ручним переліченням. Нова команда отримує потрібний набір автоматично, при зміні ролі старі дозволи знімаються разом із тегом.
Видачу зробили самообслуговуванням через каталог ролей. Метрики після: частка анонімно доступних бакетів — нуль, повний аудит прав займає один прогін скрипта замість тижня ручної звірки, звернення до підтримки щодо доступів скоротилися в п'ять разів.
Чим IAM-політики S3 відрізняються від правил бакета
В об'єктного сховища, наприклад Amazon S3, два незалежні рівні доступу. Політика IAM кріпиться до суб'єкта — користувача, ролі, сервісного облікового запису — і відповідає, що цей суб'єкт має право робити: які дії та над якими ресурсами.
Правило бакета кріпиться до самого бакета, містить указівку на суб'єкта й описує зворотний бік — хто ззовні звертається до даних, включно з іншими акаунтами.
При перетині моделі складаються за логікою: дозволено, якщо дозволено хоч десь, заборонено — якщо заборонено хоч десь.
Дозволи об'єднуються, а в явної заборони найвищий пріоритет: один Deny в IAM-політиці або в правилі бакета перекриває будь-яку кількість Allow, у тому числі виданих через групу. Це і є пріоритет заборони — бар'єр, який не обходиться додаванням нового дозволу.
Звідси практичний поділ. Усередині одного акаунта достатньо ролей IAM: команди й внутрішні сервіси отримують доступ через роль, а не через статичні ключі. Правило бакета потрібне там, де звернення йде ззовні — партнерський акаунт, зовнішній сервіс, роздача статики.
У змішаній схемі обмеження рівня організації працюють верхньою межею, яку не розширить жодна з моделей.
Налаштовуємо від заборон: спочатку закриваємо публічний доступ і вивантаження без шифрування каналу, потім додаємо дозволи за префіксами й ролями.
Розбір відмови йде в тому самому порядку — IAM, правило бакета, обмеження організації; найчастіше доступ блокує не відсутній Allow, а явний Deny в одному з шарів.
Технічні сумніви щодо розмежування доступу
Сумніви щодо розмежування доступу зазвичай стосуються не самої політики, а того, як вона вживеться з уже працюючими інтеграціями і що станеться при помилці в правилах. Нижче — п'ять технічних питань, які найчастіше ставлять перед стартом.
Чи не зламає нова IAM-політика чинні інтеграції?
Спочатку знімаємо поточні звернення й збираємо карту: хто до яких префіксів ходить. Потім видаємо явні дозволи й вмикаємо заборону за замовчуванням — сервіс, який не потрапив у карту, відвалюється на перевірці, а не в проді.
Чи можна видати доступ до окремих об'єктів, а не до всього сховища?
Можна: політика описує і префікси, і конкретні ключі. Для точкової видачі дозволяємо один об'єкт, для вибірок — префікс з умовою за іменем. Підрядник отримує рівно ті файли, які потрібні.
Як давати доступ зовнішнім підрядникам, щоб не роздавати спільний ключ?
Зовнішнім видаємо окремого користувача або роль з обмеженням за строком і діапазоном адрес. Доступ відкликається однією правкою, а історія звернень залишається в логах.
Як переконатися, що правила працюють саме так, як задумано?
Після застосування проганяємо сценарії: службові ключі, ключі підрядника, анонімний запит, запит до сусіднього префікса. Очікувану відповідь — дозволено або відмову — фіксуємо, щоб регрес ловився при наступній зміні.
Що буде з даними, якщо правило відкличе потрібні права?
Дані не постраждають: змінюється лише відповідь на запит. Відкат — повернення попередньої версії політики, це хвилини, без повторного вивантаження й заливання об'єктів.
Обговоримо завдання: розмежування доступу до сховища
Оцінка робіт щодо доступу до сховища будується не на загальному описі, а на фактичному стані політик. Поки не видно, хто і через яку роль читає дані сьогодні, будь-які строки будуть ворожінням — тому просимо надіслати кілька артефактів, і на їхній основі збираємо план:
- вивантаження чинних правил: bucket-політики, IAM-політики ролей і користувачів, а також ACL, якщо вони ще застосовуються;
- карту сховищ: бакети, їхнє призначення, які набори даних і наскільки чутливі в них лежать;
- перелік сервісів і застосунків із зазначенням ролей, під якими вони звертаються до сховища, включно із зовнішніми інтеграціями;
- вимоги щодо розмежування: кому і до якого префікса потрібен доступ, де важливі обмеження за мережею, часом або джерелом запиту;
- налаштування логування звернень: куди пишуться події доступу і як довго зберігаються;
- обмеження на вашому боці: вікна обслуговування, регламент погодження правок, хто підтверджує зміни в проді.
У відповідь повертаємося з планом впровадження: схема наслідування доступів, розподіл за ролями під реальні завдання сервісів, готові чернетки політик поруч із конфігурацією сервісу та порядок викату з точками відкату.
Перший крок займає небагато й одразу дає результат:
- Інвентаризація: зводимо всі правила в одну таблицю «хто — що — звідки».
- Фіксація надлишкових доступів і місць, де права ширші за необхідне.
- Налаштування логування й тестового стенда, де правки перевіряються без ризику для проду.
- Передача плану впровадження й погодження порядку викату.
Опишіть завдання й додайте те, що є під рукою, — повернемося з оцінкою та планом.







