Distroless образы довольно давно уже вошли в обиход. И у нас в Додо вообще есть требование, что все наши сервисы должны работать на них. Но я всё ещё в разговорах замечаю, что большинство вообще не сечёт, о чём это и для чего.
Оно в целом не удивительно: это довольно неочевидно с одной стороны и довольно очевидно с другой. Поэтому с одной стороны не задают вопросов, а с другой — не видят смысла в ответах.
Чтобы полностью проникнуться всей сутью, нужно знать довольно много о докере и о контейнерах, но главную суть, которую нужно понимать, — следующее:
Контейнер — это просто процесс, запущенный с определёнными ограничениями. То есть это не виртуалка.
Любому процессу нужно давать как можно меньше прав, и все это прекрасно знают. Но почему?
Ведь я сам написал весь код, если даже не я написал этот код, то я проведу ревью, и, если в коде есть какие-то подозрительные места, то я их уничтожу!
Так думает обыватель, и он по-своему прав в этой невинной наивности.
Но есть такая штука, как нугет-пакеты, и хуже того — есть нугет-пакеты, которые используются в нугет-пакетах.
И весь код, который там написан, как вы понимаете, поревьюить, мягко говоря, не получится.
Не использовать нугет-пакеты — это первый шаг к тому, чтобы уединиться в лесу и тихо там умереть в шапочке из фольги.
Да — очень простую. К примеру, в одной из транзитивных NuGet-зависимостей появилась строка, которая при инициализации вызывает запуск внешней программы через Process.Start. Если в контейнере есть утилиты (bash, sh, curl, wget), то вредоносный код может просто запустить их и отправить конфиденциальные данные (переменные окружения, файлы конфигурации, нюдсы, дикпики) на внешний сервер или вызвать внутренний админ-эндпоинт под именем сервиса.
🅰️ как нам поможет distroless?
А так, что в distroless-образе этих внешних утилит просто нет — нет bash, нет curl, нет sh и даже нюдсов и дикпиков нет. Поэтому сценарий «внезапно запустить системную утилиту из контейнера» потерпит поражение: бинарник не найден, команда не выполнится. Это закрывает быстрый и «грубый» вектор дополнительной загрузки кода, который часто используется в мелких эксплойтах и supply-chain-атаках.
Очевидно, что это не стопроцентная защита. Если вредоносный код использует возможности самого рантайма (в .NET — HttpClient, файловые операции и т.д.), он по-прежнему сможет делать сетевые запросы или читать файлы. Distroless снижает эти конкретные риски. Вот, собственно, и всё.
Поделитесь по-сестрински этим знанием с теми, кто ещё не в курсе. Рили почему-то мало людей понимают про это.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥4❤3 3
Я тут подумал, ведь бывает так, что призраками становятся не только люди, но и репозитории! К примеру вы хреначили репозиторий, который набрал пару тысяч звезд, а потом… Ну просто забили. И репозиторий как бы жив и популярен, но никому уже не нужен. Получается застрял между двух состояний. Выходит – призракопозиторий
Короче, за вечер с браузером атлас навайбкодил слот-машину, которая позволяет почтить память почивших репозиториев.
Идея простая:
1. Заходите на сайт
2. Крутите слот-машину 🎰 (тянем рычаг справа вниз)
3. Вам выпадает три рандомных репозитория с большим количеством звезд, но с последним коммитом, сделанным Бог знает когда
4. Ставите репозиторию звезду
5. Автор охреневает и радуется!
Если вы давно читаете мой канальчик, но то вы точно знаете, как я люблю пропагандировать поставку звезд на репозитории. Так что эта механика идеально ложится в мой вайб и в сегодняшнюю тематику)
Можно даже язык программирования профильтровать. Я пока вчера залипал в свое собственное казино, нашел много прикольных реп, с классными фичами для юньки. Короче, попробуйте! Даже если звезду не вьебете, то все равно инетерсно посмотреть, что было популярно и померло лет эдак пять назад.
Ну и моей репке тоже звездочку там аккуратно звезданите
Please open Telegram to view this post
VIEW IN TELEGRAM
Вчерашний хэллоуин обернулся настоящим кошмаром — сегодня рабочая суббота!
💯8😡3 3😱2
Пиздос как это круто! Вообще у нас супер-крутая команда работает над авторизацией. Регулярно что-то поставляют такое, чего нам людям даже и не снилось – атакующие корабли, пылающие над Орионом, лучи Си разрывающие мрак у ворот Тангейзера. Все эти моменты теперь дополнены и такой вот автозизованной библиотекой
❤8 3😎2
Forwarded from Dodo Engineering
Они разрабатывают и продвигают открытые стандарты для безопасной аутентификации без паролей по всему миру. Более того, FIDO Alliance включил наш способ в список библиотек, рекомендованных к использованию.
Почему это круто?
Passkey безопаснее и удобнее паролей. Не надо ничего запоминать, можно использовать биометрию.
Мы разработали собственное высококачественное решение для авторизации с помощью Passkey, подходящее именно нам. Когда мы искали подобные решения на рынке, то нашли всего два: одно — очень дорогое, а другое — технологически устаревшее.
Наше решение признали на международном уровне и теперь рекомендуют для использования в других компаниях.
Чем занимается FIDO?
Fast IDentity Online Alliance устраняет зависимость от уязвимых к фишингу, перехвату и утечкам паролей. Они стремятся:
В FIDO Alliance входят: Apple, Google, Microsoft, Amazon, Intel, Samsung, Mastercard, VISA, Bank of America и другие крупные компании.
🌐 Где используются FIDO-стандарты?
💻 И где теперь это будет использоваться?
Во-первых, мы сами использовали нашу библиотеку, чтобы подключить к Dodo IS Passkey.
Во-вторых, наша библиотека — OpenSource. Ее могут использовать все, кому нужно, и везде, где есть вход по логину/паролю, а бэкенд написан на .Net. Сейчас есть 9 форков — это немного, но уже значит, что кто-то сделал себе копию и доработал ее под себя.
Please open Telegram to view this post
VIEW IN TELEGRAM
👏7 6
Сегодня – .NET Conf и, конечно, день релиза .NET 10
На самом деле, в этом году я впервые ждал новую версию .NET по двум причинам:
🥇 Запускаемые файлы C# — для меня эта фича самая ожидаемая. Шарпику уже давно было пора сделать что-то со своей инфраструктурой. Я с огромной завистью смотрел на то, как быстро запускается всё питоновское и нодовское на компе. Как удобно вообще можно запускать любую утилиту просто из консоли — и прям дико завидовал. Большая часть изменений в .NET до этого, на мой взгляд, — ну не хуйня, но близко к этому. Каждый раз, когда говорили про то, что упростят написание очередного свитч-кейса тем, что дадут писать палочку вместо слова, рука сама небрежно касалась лица, производя шлепок.
🥈 И вторая причина, по которой жду .NET 10, — это просто LTS-версия. До недавнего времени не видел смысла переходить на STS-версии, ибо при таком манёвре ты фактически обрекал себя на переезд строго через год. А это обычно в ноябре, под Новый год, когда сроки горят. То есть окно манёвра было мизерное. А я, к примеру, предпочитаю перестраховаться и взять сразу то, что будет долго поддерживаться, чтобы переехать потом спокойно — под сезон отпусков, когда страсти поутихают.
Такие дела. Плюс, говорят, там ускорили что-то, что-то там на стек перенесли. Но это уже перестало удивлять — его, кажется, каждый год ускоряют в сто раз. Так что скоро новая версия дотнета уйдёт в нирвану и начнёт обрабатывать ещё не отправленные запросы.
На самом деле, в этом году я впервые ждал новую версию .NET по двум причинам:
🥇 Запускаемые файлы C# — для меня эта фича самая ожидаемая. Шарпику уже давно было пора сделать что-то со своей инфраструктурой. Я с огромной завистью смотрел на то, как быстро запускается всё питоновское и нодовское на компе. Как удобно вообще можно запускать любую утилиту просто из консоли — и прям дико завидовал. Большая часть изменений в .NET до этого, на мой взгляд, — ну не хуйня, но близко к этому. Каждый раз, когда говорили про то, что упростят написание очередного свитч-кейса тем, что дадут писать палочку вместо слова, рука сама небрежно касалась лица, производя шлепок.
🥈 И вторая причина, по которой жду .NET 10, — это просто LTS-версия. До недавнего времени не видел смысла переходить на STS-версии, ибо при таком манёвре ты фактически обрекал себя на переезд строго через год. А это обычно в ноябре, под Новый год, когда сроки горят. То есть окно манёвра было мизерное. А я, к примеру, предпочитаю перестраховаться и взять сразу то, что будет долго поддерживаться, чтобы переехать потом спокойно — под сезон отпусков, когда страсти поутихают.
Такие дела. Плюс, говорят, там ускорили что-то, что-то там на стек перенесли. Но это уже перестало удивлять — его, кажется, каждый год ускоряют в сто раз. Так что скоро новая версия дотнета уйдёт в нирвану и начнёт обрабатывать ещё не отправленные запросы.
🔥7 5😁4❤1👍1👌1
В пятницу классно поразгоняли с ребятами на наших внутренних техпосиделках про переезд на .NET 10.
Хедлайнером у нас был ослепительный @granstel, который перевёл свой сервис на .NET 10 первым (как минимум в Додо а может и в мире, кто знает). Сервис некритичный, но полезный — он является бэком для этой охуенной интерактивной карты. Идеальная площадка для тестов.
Так вот что удалось выяснить в процессе переезда/обсуждений:
1) В целом всё работает
2) Но есть один довольно критичный ишуй
В версии 10.0.100 внезапно сломан хендлинг вложенных try/catch/finally.
Как показано на пояснительном дикпике выше
Если внутренний finally бросает исключение, то:
внутренний catch не вызывается,
внутренний finally не доходит до конца,
внешний finally не вызывается вообще,
исключение вылетает наружу без обработки.
Довольно жёсткая штука — потому что using и await using разворачиваются компилятором именно во вложенные try/finally. А значит, при dispose может соскочить вся цепочка освобождения ресурсов.
То есть вложенный try/catch в принципе не перехватывает исключение из вложенного finally. А это уже влияет и на using, и на await using.
То есть вот такой код может быть потенциально опасным, если disposableTwo в своем диспоузе кинет исключение
using System;
using System.Threading.Tasks;
await using var disOne = new FirstDisposable("ONE");
await using var disTwo = new SecondDisposable("TWO");
Console.WriteLine("Before throw");
throw new Exception("FUCK");
sealed class FirstDisposable : IAsyncDisposable
{
private readonly string _name;
public FirstDisposable(string name) => _name = name;
public async ValueTask DisposeAsync()
{
Console.WriteLine($"DisposeAsync({_name}) START");
await Task.Delay(10);
Console.WriteLine($"DisposeAsync({_name}) END");
// На .NET 10.0.100 этот DisposeAsync вообще НЕ вызовется,
// потому что исключение из DisposeAsync(TWO) оборвёт цепочку.
Console.WriteLine($"NOTE: DisposeAsync({_name}) WAS CALLED — но это произойдёт только на .NET 8");
}
}
sealed class SecondDisposable : IAsyncDisposable
{
private readonly string _name;
public SecondDisposable(string name) => _name = name;
public ValueTask DisposeAsync()
{
Console.WriteLine($"DisposeAsync({_name}) THROWS — сейчас всё сломается");
throw new Exception($"DisposeAsync boom: {_name}");
}
}
Это утечки коннектов, файлов, сокетов, транзакций — что угодно.
Учитывая, что многие библиотеки используют IAsyncDisposable — в общем может стрельнут.
Все уже пофикшено судя по всему, наверняка заедет в следующую версию.
🚧 Вообще не всем дано переехать сразу.
Например, я попытался перевезти свою Базу знаний на новые рельсы, но столкнулся с тем, что нужный пакет Pomelo.EntityFrameworkCore.MySql пока отсутствует для .NET 10.
Так что переехать сходу смогут не все.
Может, даже и хорошо — с таким багом можно и потерпеть
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5👾5🤝2
С этим красавчиком мы вместе делаем новую Базу Знаний для Додошки) Вообще классно работать с заряженными людьми!
❤4🤝1
Forwarded from Женя, расскажи про AI
Знакомьтесь, Blok!
Blok — это блочный, визуальный open-source редактор типа Notion.
В основу Blok лёг Editor.js — прекрасный визуальный редактор, который в своём развитии остановился где-то в 2018-м году, где было приемлемо иметь средненький UX, плохую документацию и решение не поддерживающее современные фреймворки.
Blok призван решить все эти проблемы и стать тем самым визуальным редактором, который вы искали.
Уже сейчас в Blok, в отличие от Editor.js, исправлены многие баги и проблемы безопасности, повышена стабильность и тестируемость редактора, а также появилась возможность перетаскивать блоки с помощью drag&drop!
В ближайших обновлениях Blok станет React-first для максимально удобной интеграции с вашими приложениями.
Blok доступен бесплатно прямо сейчас!
Blok — это блочный, визуальный open-source редактор типа Notion.
В основу Blok лёг Editor.js — прекрасный визуальный редактор, который в своём развитии остановился где-то в 2018-м году, где было приемлемо иметь средненький UX, плохую документацию и решение не поддерживающее современные фреймворки.
Blok призван решить все эти проблемы и стать тем самым визуальным редактором, который вы искали.
Уже сейчас в Blok, в отличие от Editor.js, исправлены многие баги и проблемы безопасности, повышена стабильность и тестируемость редактора, а также появилась возможность перетаскивать блоки с помощью drag&drop!
В ближайших обновлениях Blok станет React-first для максимально удобной интеграции с вашими приложениями.
Blok доступен бесплатно прямо сейчас!
🔥4 3✍1❤1
А вот результат, ради чего все это делается! Человек пару недель ночами не спал – делал возможным Notion-like экпириенс для наших редакторов! 🧨
На гифке короткое представление, как было и как стало:
На гифке короткое представление, как было и как стало:
This media is not supported in your browser
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
❤🔥10 4🔥2
Год назад делали с Серегой Орловым LiveActivities на андроиде.
Это такая штука, как на пояснительном дикпике выше. Выглядит просто.
Но я тогда открыл для себя, что в Андроиде все вещи, которые выглядят простыми скорее всего делать будет тупо сложно!
Короче, в своей статье Серега рассказывает как с помощью новой фичи LiveUpdates можно сделать такую вот штучку с прогресс-баром и как это пока что ограниченно в возможностях.
К примеру на верхней картинке верхний и нижний островок – это тупо разные компоненты, а не один и тот же просто переверстанный👁 👁
Вообще мне всегда было забавно, как у нас ребята на андроиде радуются таким вот штучкам. Мне всегда это было как-то до лампочки, у меня вообще все уведомления выключены. А у них там целая история в этих отключенных оповещениях!
Короче, статья вышла прикольная! Заслуживает плюсика в карму💯
Это такая штука, как на пояснительном дикпике выше. Выглядит просто.
Но я тогда открыл для себя, что в Андроиде все вещи, которые выглядят простыми скорее всего делать будет тупо сложно!
Короче, в своей статье Серега рассказывает как с помощью новой фичи LiveUpdates можно сделать такую вот штучку с прогресс-баром и как это пока что ограниченно в возможностях.
К примеру на верхней картинке верхний и нижний островок – это тупо разные компоненты, а не один и тот же просто переверстанный
Вообще мне всегда было забавно, как у нас ребята на андроиде радуются таким вот штучкам. Мне всегда это было как-то до лампочки, у меня вообще все уведомления выключены. А у них там целая история в этих отключенных оповещениях!
Короче, статья вышла прикольная! Заслуживает плюсика в карму
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5 3👍1
В первый раз за долгое время в практике понадобилось использовать бэкграундную таску.
Нужно было добавить в процесс логина автоприсваивание пользователям определенных доступов. Операция не обязательная и из-за нее не должен падать логин. Тем более процесс логина из-за нее тоже не хочется растягивать.
Можно было сделать fire and forget опустив слово await:
groupAccessService.AssignPredefinedSpacesAsync(existingUser, CancellationToken.None);
То есть пустить таску на самотек. С одной стороны просто и понятно, но хочется как-то понимать, дошла таска до своего финала или нет и как-то все это залогировать. Короче хочется больше контроля над таким.
Вспомнил, что когда-то с IHostedService слышал про BackgroundTaskQueue
Оказалось, что в доке прям есть кусок кода, который мне нужен. По нему решил реализовать вот такой простенький бэкграунд кью воркер
using System.Threading.Channels;
namespace Dodo.KnowledgeBase.Web.Services.BackgroundTasks;
public class BackgroundTaskQueue(IServiceScopeFactory serviceScopeFactory) : IBackgroundTaskQueue
{
private readonly Channel<Func<CancellationToken, ValueTask>> _queue =
Channel.CreateUnbounded<Func<CancellationToken, ValueTask>>();
public async ValueTask QueueAsync(Func<CancellationToken, ValueTask> workItem)
{
ArgumentNullException.ThrowIfNull(workItem);
await _queue.Writer.WriteAsync(workItem);
}
public async ValueTask QueueAsync(Func<IServiceProvider, CancellationToken, ValueTask> workItem)
{
ArgumentNullException.ThrowIfNull(workItem);
await _queue.Writer.WriteAsync(ScopedWorkItem);
return;
async ValueTask ScopedWorkItem(CancellationToken ct)
{
using var scope = serviceScopeFactory.CreateScope();
await workItem(scope.ServiceProvider, ct);
}
}
internal async IAsyncEnumerable<Func<CancellationToken, ValueTask>> DequeueAsync(
[System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken ct)
{
await foreach (var item in _queue.Reader.ReadAllAsync(ct))
{
yield return item;
}
}
}
В котором вы по сути кладете функцию в канальчик, а бэкграундный хостед сервис этот канальчик потихоньку разгребает вот так:
namespace Dodo.KnowledgeBase.Web.Services.BackgroundTasks;
public class QueuedHostedService(
IBackgroundTaskQueue taskQueue,
ILogger<QueuedHostedService> logger) : BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken ct)
{
logger.LogInformation("Queued Hosted Service is running");
await foreach (var workItem in ((BackgroundTaskQueue)taskQueue).DequeueAsync(ct))
{
try
{
await workItem(ct);
}
catch (Exception ex)
{
logger.LogError(ex, "Error occurred executing task work item");
}
}
}
}
И вот так это можно использовать:
await backgroundTaskQueue.QueueAsync(async (sp, ct) =>
{
var groupAccessService = sp.GetRequiredService<IGroupAccessService>();
await groupAccessService.AssignPredefinedSpacesAsync(existingUser, ct);
});
Вроде несложно, но если что упадет, то всегда можно увидеть в логах в отличие от fire and forget запуска.
В отличие от варианта в доке сделал через IAsyncEnumerable. Так что вышло ну чуть покрасивше и с моей любимой фичей, которую редко когда получается заюзать.
Please open Telegram to view this post
VIEW IN TELEGRAM
Docs
Background tasks with hosted services in ASP.NET Core
Learn how to implement background tasks with hosted services in ASP.NET Core.