malyj_gorgan (
malyj_gorgan) wrote2021-12-24 01:04 pm
![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Entry tags:
log4j ?
Слухайте, а хтось може в парі абзаців пояснити, що то таке сабж і з чим його їдят? Дідько з нею, з його vulterability'ею, я хочу зрозуміти, чим був такий хороший чи зручний чи потрібний сам log4j, що та вульнерабіліті виявилася такою проблємною? Тільки пояснити так, на хлопский розум, без відсилань в непотрібні абревіатури.
Дякую!
Дякую!
no subject
Тобто, це просто logging?
Якщо це просто логописалка, навіть структурована, то я не розумію, нафіга у неж в принципі була функціональність, яку можна було експлуатувати? Вписувати туди таку функціональність -- не просто робити місце для дірок, а і банальний приклад того, що називають overengineering.
no subject
log enrichment - додавати потрібні контекстні дані до логів, які або замахаєшся додавати сам, або забудеш. Так з'являється потреба ${ctx.something}.
remote log destination - писати в локальний файл - це годиться для невеликої кількості процесів. Якщо у нас ферма із кількасот або тисяч процесів, з'являється потреба скидати все в одне місце. (ну і, звісно, enrich логи ще й ${ctx.hostname})
(скажімо, з отих двох можна побудувати ще й log censoring - фільтрувати або обскурувати потрібні контекстні дані, залежно від log destination. gdpr, і таке інше)
different types of log destination - а що, є один-єдиний стандарт і протокол передачі логів і одна-єдина архітектура організації процесу передачі логів?
ну, і от тепер все разом взяти докупи - маємо діру. З одного боку щось виймати з контексту - класна і потрібна річ, з іншого боку - якщо для контексту використовувати JNDI, маємо змогу з контексту виймати arbitrary stuff, або зациклити. Ну, і от arbitrary stuff, виявляється, може бути вказівкою JNDI піти поговорити з іншим сервером, який підтримується JNDI - наприклад, лівий LDAP. Але це вже пішли абревіатури.
no subject
Це часта лажа: якісь рішення, зручні з близької розробникам точки зору, масово поширюються без обдумування можливих проблем і ризиків з усіх інших точок зору, і вуаля: то зручно писати логи -- і діра в безпеці, то зручно тримати в одному місці докер імаджі -- і щось стається з quay.io, і паніка на всю індустрію, то придумали хороші безпечні gdpr -- і кожному першому сервісові доводиться писати окремий код і інфраструктуру даних для Європи (що кидає тінь і на gdpr, і на дизайн кожного першого сервіса)
Комплексні підходи з продуманою архітектурою без дір на півстіни попадаються нечасто. (Чи то ми ще просто ще тих дір не знайшли?) І зрозуміло чому: бо поки ти придумуєш нормальний літак, випробовуєш, шліфуєш, покращуєш, у конкурентів уже куплять єраплан з гівна і палок, склепаний бандою китайських програмістів, яким плювати на якість, які одне одного не розуміють, а індійського PM'а так вже точно, але пробивні американські сейлзи уже зароблять свої відсотки з продажу, так що всьо чотко.
Як з цим боротися -- не знаю. Чекаю, коли хтось зламає github або, краще, Atlassian suite і вкраде пів-інтернету.
no subject
Сенсу нема. :)
Якщо хтось вкраде наш source code - то (а) нічого особливо секретного в 99% коду він не знайде, усі ідеї давно є публічними, (б) без відповідної інфраструктури (включно з людьми) фіг ти той код запустиш.
no subject
Сенсу багато. Краджений код не обов'язково запускати, краджений код -- джерело знань про слабкості систем. Тут, в першу чергу, власне діри в самому коді -- поганого коду в цьому житті більше, ніж хорошого. В другу -- такі набагато простіші до аналізу речі, як які бібліотеки десь в бекендах біжать (у кожного першого, ок, кожного другого бізнесу десь в продашені щось робить legacy код багаторічної давності, для чого регулярно підгружають то туди, то сюди, всякі старі версій бібліотек і знарядь, де були відомі діри, якому потрібні старіші бібліотеки, включно з тими, де є величезні задокументовані діри, залатані в пізніших версіях, але то в пізніших). Ну і, нарешті, найочевидніша і найсумніша дірка в безпеці -- в різних репозиторіях є надто багато різної інформації, якої там просто не може бути. В master гілці якогось софта такого майже нема, в якихось integration чи qa гілках уже менше, але в dev branches.... Там і адмін паролі, набрані прямим текстом, і забуті (спеціально залишені) service backdoor'и типу, і просто прописана текстом PII різного роду. Я впевнений, навіть в найращих компаніях, з двома рівнями code review, розділенням engineering і QA, просто хорошими програмістами і чіткими процедурами, навіть там можна знайти щось з вищезазначеного. А оскільки більшість бізнесів у цьому світі далеко не такі, то у більшості бізнесів можна знайти не щось одне, а всі перечислені класи проблем.
no subject
Для того, щоб отримати доступ до нашого системного коду нічого не треба ламати. Наприклад, Titus та Zuul лежать просто у вільному доступі. Заходь на гітхаб і качай.
Минулого року хакнули приватне репо майкрософту на гітахбі і що? а нічого. Ну знаєш ти, що є такий код і така дірка в ньому - і що далі? Доступа до environment'а в тебе нема, і не буде, бо критичні enviroments як раз і проєктуються з розрахунком на те, що в них будуть деплоїти неідеальний код.
А якщо в твоїй thread model є серйозні загрози, то (а) дірки в коді вони знайдуть навіть без доступа до сирців - просто по непрямим ознакам, (б) захист коду - це дуже вторинне. Бо якщо треба, то серйозні люди просто прийдуть в гості до твоїх SRE, завербують їх чи просто приставлять пістолет до голови (і тоді починати треба з фізичного захисту персоналу).
Часто, до речі, це є анті-паттерном. Є ситуації де це має сенс, але в більшості випадків від цього більше шкоди, ніж користі.
no subject
Вона не "побудована" на obscurity, просто багато де "так склалося". Ну от, нема хорошої продуманої security моделі, але все якось працює, то і добре.
> ... хакнули приватне репо майкрософту на гітахбі і що? ...
і то, що можна гадати, яка кількість дірок в майкрософтівських кодах і/або сервісах, які експлуатували після цього інциденту досі і експлуатуватимуть в майбутньому, була знайдена чи зроблена в результаті цього хаку.
> (а) дірки в коді вони знайдуть навіть без доступа до сирців - просто по непрямим ознакам, (б) захист коду -
> це дуже вторинне. Бо якщо треба, то серйозні люди просто ....
Це все правда, але:
(a) захист власне коду -- лише один з аспектів, в репозиторія є багато всього іншого. Юзернейми/паролі, hash salt'и, порти/ReST-API-запроси для backdoor доступу, записані відкритим текстом в гілках розробників я не придумав, а бачив на власні очі. Не скажу, де і коли :)
(b) "серйозні люди" бувають. Тут як з замками/дверима, аналогія з захистом житла, яку ми недавно згадували, пасує ідеально. Від "серйозного" наїзду не врятують і металеві двері з десятком замків, бо серйозні люди, коли треба, зайдуть в твою хату чи квартиру разом з тобою. Але "серйозні люди" -- це лише частина можливих security-related проблем. Часто -- помітно менша частина. Від опортуністичного бомжа чи навіть боязливого злодія без конкретної наводки замок на міцніших дверях допоможе. Так і тут: значна частина проблем значної частини корпорацій йде не від серйозних людей, a від дрібніших шахраїв, які вичисляють ту чи іншу діру в системі, і потрохи її доять. Але це "потрохи" додається достатньо, щоби втрати ставали відчутчими. В результаті, шукаєш зовнішні сервіси, які будудь тебе берегти. Я в одному з таких сервісів якраз і працюю зараз: клієнт приходить, каже, що його обкрадають, ми дивимося, що можемо зробити, описуємо наші можливості і виставляємо цінник. Після чого якісь клієнти платять нам, якісь вирішують самі себе ремонтувати/охороняти, а якісь вирішують, що ті півмільйона на рік, які в ник крадуть через цю дірку, дешевше продовжувати платити, ніж хоч щось міняти. Я бачив усі три сценарії. Так от, в цьому смислі, security by obscurity працює, ще й як. Кількість онлайн шахрайства, якє стається навколо, просто неймовірна. Я собі навіть не уявляв! Але поки про ту чи іншу діру знають лише кілька зловмисників, ніхто не чухається. А коли і чухається, то дуже трошки. Оптимізують не TTF чи TTR, а EBITDAthisquarter; максимум -- EBITDAthisyear.
(c) не "по ознакам" а "за ознаками"
> Є ситуації де це має сенс, але в більшості випадків ...
Ця "більшість", вона у твоїх спостереженнях, чи за якимись об'єктивними вимірами? Я, як ти знаєш, в індустрії відносно недавно, не претендую, що бачив багато різноманітного софтверного продукту. Тобто, за останній рік з гаком бачив багатенько чужих проблем, але чужий код не читав, хоча часом можна було здогататися, звідки в коді ростуть ноги них проблем. Але навіть в тих трьох місцях, де я працював, спущена зверху всякими просвітленими менеджерами і cost-saving віцепрезидентами мантра "be your own QA" була абсолютно, категорично неправильною. Словом, не маю причин сумніватися, що можливі сценарії, де це працює, але я особисто таких сценаріїв не бачив :) Напевне, я бачив меншість.
Думаю (знову вбрав капітанську шапку), все залежить від області, де ти працюєш. Я стикався, переважно, з різного роду Data Product кодом (ETL / ML / visualizations) різних областей. Плюс, пару років працював в команді, яка, власне, розробляла збір логів в мережах (WAN), то бачив і власне log generation/transmission/processing/storage код, і весь код командування мережею. З тих пір і не можу позбутися глибинного цинізму стосовно всього, зв'язаного з мережами і просто комп'ютерами. Шукаю луддитів-однодумців :)))))
no subject
Так ця мантра і є неправильною. Якщо просто говорити "be your own QA" і більше нічого не робити - то краще не буде, а буде гірше. Але і розподіляти "тут QA, а тут developers" - це теж гірше. Це ж не дихотомія. :)
Для типової розробки я б починав з CI. CD - це набагато важче, але в плані deployment цілком реальна мета - 1-3 деплоймента за добу, не більше 6 годин від коміту до продакшена, в ідеалі - не більше години. Теоретично це можно робити і з окремими QA, але на практиці від підходу "окремі команди перекидають код через паркан" доводиться відмовлятися.
Але це не значить, що ролі QA чи SRE зникають. Вони просто починають виконувати зовсім інші функції.
Контрприклади/edge cases:
* година до продакшену не завжди значить година до кінця деплойменту
* коли галузь технічно унеможливлює швидкі зміни (наприклад, firmware development, де прошивку в чипах не можна змінювати "просто так") - то потрібні інші підходи.
За вимірами. Якщо цікаво - можеш почати з Accelerate, це seminal work. (Там і про тестування, і про infosec є.) Якщо зайде - подивись на щорічні DORA reports.
І я б розрізняв "більшість випадків, які існують" та "більшість випадків, де та чи інша практика є доречною" - це множини, які слабо перетинаються, хоч про дієти мова, хоч про інфосек.
no subject
На цьому можна зупинитися - це саме по собі яскравий antipattern, який вказує на існування більш суворіших antipatterns.
no subject
Насправді, майкрософт доволі прозора в цьому плані корпорація, але то лірика.
Головне в тому, що ми можемо оцінити, як цій хак вплинув на БІЗНЕС майкрософту.
no subject
Або я не розумію твоєї логіки, або ти якось виключно вузько сприйняв мою фразу прро "чекаю, коли хтось зламає гітхаб з бітбакетом" і доказуєш мені щось своє. Бо мені байдуже, як відіб'ється на самих бізнесах поширення їхнього коду. Проблеми від того, що хтось зламає гітхаб з бітбакетом це не проблеми того чи іншого бізнесу, це проблеми усіх. Дірки, які знайдуть в великих софтинах -- фігня. Вірніше, не лише фігня, їх будуть експлуатувати, але їх і так експлуатують, хай трішечки менше. Великі репозиторії -- це софт тисяч дрібніших бізнесів всяких ретейлерів, банків, телефонних провайдерів, виробників еппів, державних установ і т. п...., а ще сотень b2b компаній, які працюють з усіма цими ретейлерами, банками і т. п. і "чисто випадково" мають купу даних їхніх клієнтів. Людські імена, адреси, кредитки, явки, паролі, вотетовотвсьо.
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
(no subject)
no subject
Одягаю Captain Obvious' cape: треба оптимізувати процеси під MTTR, бо спроба оптимізувати під MTTF зазвичай веде до погіршення як MTTF, так і MTTR.
(Я пам'ятаю, ти просив без абревіатур, вибач!)
UPD: мова, звісно, не про safety-critical інфраструктуру, там інші проблеми, і інші методи їх вирішення.
no subject
no subject
З стандартними рішеннями на кшталт grpc+opentracing+log4j усе реалізується невеличким інтерсептором буквально на 5 рядків без втрати перформансу. А ось як цей довольно банальний сценарій реалізувати через System.out.println? (Про це і много чого іншого читайте в свіжому номері журналу "Ніяк".)
Сорі, "музикою навіяло" (с)
no subject
Ну, от візьмемо нижчезгадані 20K qps. Якщо response time 1 ms, то нам потрібно всього 20 threads. Це не такий і великий thread pool. Якщо ми візьмемо context switch за 50 мікросекунд, реактивна модель нам тут може подарувати десь 5% CPU на кожен eliminated context switch. Якщо ми позбуваємось 2....4 context switches, то виграємо десь 15% response time. Непогано, але звертаю увагу, що справа не у unmanageably large number of threads, і виграш workload-specific.
Для масштабу, розглянемо випадок 20K qps із response time 50ms. Тут би нам було потрібно 1000 threads, це забагато для одного невеличкого процесу. Але ми мусимо знати ще одне невідоме: скільки часу ми проводимо на CPU. (Це саме невідоме присутнє і у випадку з response time of 1 ms, але там ми можемо повністю ігнорувати це питання.) Якщо 1ms, то нам уже потрібно 20 CPUs - це не такий вже і малий процес. Ну, і тепер уже можна розглянути питання, а що ми втратимо, якщо ускладнимо реалізацію сервісу, і введемо thread pools обмеженого розміру та черги, де б запити проводили решту часу, тобто, 49ms. Цього разу context switch - це ледве 0.1% часу, і ми можемо собі дозволити 50 context switches before it becomes a measurable problem.
Тобто, 1000 threads таки з'являється, але для великих сервісів ми, по-перше, можемо собі дозволити, а по-друге, можемо таки зменшити кількість threads.
Мораль цієї історії така: якщо ми можемо використати CPU повністю, то ми CPU-bound, і реактивна модель нам дарує the cost of context switch; якщо ми не можемо використати CPU повністю, то ми bound на якомусь іншому ресурсі, і реактивна модель нічого не поліпшує, а лише ускладнює софт. На пітоні та nodejs реактивна модель - єдина можлива; а от на інших мовах треба дивитись.
Ну, і питання: це схоже на правду? Що я пропустив?
(У дужках додам, що реактивна модель і non-blocking IO нам ще дають inversion of control, який є наслідком CPS, але по-перше ніхто насправді цим не користується, бо API немає, а muxer пишуть одиниці (це, власне, netty і т.ін.), а по-друге люди геть про це не згадують, а обмежуються розмовами про розміри thread pools)
no subject
Short answer: так, в 90%+ випадках реактивна модель лише занадто ускладнює код і нафіг не потрібна.
Long answer: є низка випадків, де без реактивщини ніяк, я спробую згадати те, що бачив (і 100% щось забуду :) ).
1) High load. Ті самі 20к RPS перемножити на купу серверів. Виграш в 15% на навантаженні, яке створює computing costs в USD10М за рік - це USD1.5М економії. Якщо код ускладнюється настільки, що треба найняти ще одного інженера чи інженерку за USD500К - все одно автор реактивного коду отримає річний бонус. :)
А якщо рахунок USD100М? А якщо USD1-2-5B? Отож бо. Останнє, звісно, не такий частий приклад, але USD10-100М - не така вже і аберація.
2) High latency. У біллінгу, наприклад, payment processors' SLA часто гарантують відповідь з P99 latency 60s. s, not ms.
І тут навіть 1К RPS нас вбиває.
3) Ultra-low latency та non-linear context switch cost growth. Якщо ми працюємо над системою, де нам треба гарантувати under 1 ms latency, то навіть fixed cost of switching between 2 threads (2-7 microseconds) - це вже помітний імпакт. А в реальному світі, коли мова йдеться про switching между десятками чи сотнями тредів - то це вже буде high double digits (40-70 microseconds).
100% щось забув, але як в тому мемі - "йой, най буде".
Резюме: усе, що я згадав, аж ніяк не суперечить моралі про bottleneck.
Але реактивна модель дозволяє нам наблизитися до більш ефективного використання як CPU, так і IO, і як наслідок - в низці випадків (невеликої, але і не такої малої, щоб її можна було ігнорувати в індустрії в цілому) - отримати реальну економію, від грубих грошей до latency.
no subject
А про ріст context switch cost із ростом кількості threads - це за рахунок чого? Якщо це про CPU contention, то чим відрізняється wait for CPU від wait to be read from socket buffers?
no subject
В випадку малої кількості threads, кожна з яких оперує незначною кількістю даних - цього може і не відбуватися. Як тільки кількість threads/даних зростає - упс. (Якщо код виконується в віртуалізованому середовищі - дабл-упс. Але для випадку 3 це зазвичай не актуально, там bare metal.)
no subject
no subject
Але мені здається, що в випадку реактивного стилю ми не так часто чіпаємо інший код - особливо інший boilerplate code, якого при виконанні `new Thread(...)` повним повен кошик.
І boilerplate data ми не чіпаємо, а в реальному `new Thread(new Runnable{...})`, який робить щось реальне, типу HTTP request, його може бути декілька мегабайт, Java - це ще той memory hog.
no subject
Перечитав і подумав - чи не є реактивною моделлю, але вже без blocking IO? Ні, звісно, так теж можна, але це теж ускладнює код, ні?
no subject
Скажімо, взаємодія із дуже повільним сервісом - в цьому місці вводимо CompletableFuture, продовження якого буде виконано в окремому thread pool, а решту пишемо "нормально".
Тому випадок номер 2 із 60 секунд - там якраз thread per request most of the way.
no subject
Отримуємо в найпростішому випадку:
(Тут, звісно, треба фрейморк, який вміє працювати з такими відповідями, не викликаючи .get, а ціпляючи це до, наприклад, Netty, який крутиться під капотом.)
Собсна, тому що код далі виконується по факту відповіді 3rd party service - то виходить, що частина коду в нас таки реактивна, і єдина різниця в тому, що ми загортаємо "довгу" частину в окремий таск і виконуємо його на окремому тредпулі, який швидко насичується.
Але чому в такому випадку не використати non-blocking IO, раз в нас вже і так код реактивний?
Беремо
Різниці в складності коду нема, а різниця в throughput - якщо я правильно пам'ятаю лоад-тести, які я робив як раз, коли в біллінгу працював - раза в два-три.
(Бо в non-blocking IO немає проблем з насиченим thread pool та нудною оптимізацією його розміру, підтримкою переліку тасків, що виконуються, і ще купою дрібничок - одна лише оптимізація garbage collection нас починає вбивати, бо на 60 секундах це вже зовсім інша справа, ніж на 50мс...)
no subject
так, оце і є "CPS is contagious". Але якраз якщо ми не змушені всі blocking operations переписувати в реактив, то тоді не "Усе, що йдеться далі".
> в non-blocking IO немає проблем з насиченим thread pool та нудною оптимізацією його розміру, підтримкою переліку тасків, що виконуються, і ще купою дрібничок
а от якраз перелік тасків, що виконуються, є проблемою асинхрону :) а насичення thread pool - це ніщо в порівнянні з необмеженим ростом задач, загубленим continuation та боротьбою із error propagation та resource management.
щодо нудної оптимізації розміру - так, вона нудна, але це підлягає автоматизації.
> а різниця в throughput - ... - раза в два-три
цікаво. я такого ще не бачив. а в порівнянні з чим?
no subject
Якщо ми не влітаємо в 5 сек затримки (бо локі, насичений пул, неоптимальні індекси) - то, так, згоден.
Але якщо в нас і БД реактивна, то http worker ми можемо прив'язати до конкретного cpu core і мати два threadpool-а замість трьох.
(Бо синхронний код з цього прикладу не можна виконувати на http worker - інакше сервер просто не буде реагувати на нові запити. я підозрюю, що тут йдеться про стандартну модель http worker thread pool - framework threadpool - separate threadpool for slow operations.)
А якщо ми додаємо HTTP/2 multiplexing і позбавляємося необхідності обробляти кожен новий запит до нашого сервісу як окремий запит з власним connection (чи боротися з connection pooling)... ;)
Різниця в throughput в порівнянні з виконанням
в окремому threadpool (який все одно насичується і примушує чекати батьківській threadpool). Черга тут теоретично може допомогти, а практично в нас є власний SLA і чекати безкінечно в черзі теж не можна - як мінімум, в тому випадку, що я тестував.
Звісно, якщо, наприклад, йдеться не про купівлю товара на сайті, а про відновлення щомісячної переплати, то там інша картинка буде, бо там не буде вимог до нашого latency.
Але, слава Творцю, це проблема людей, що пишуть асинхронні фреймворкі. :)
(no subject)