Kiedy pracujemy z bankami i dużymi przedsiębiorstwami, Kafka rzadko bywa tematem zaczynanym od zera.

Najczęściej Kafka działa już od lat. Zespoły są od niej zależne, przepływają przez nią dane krytyczne, a platforma zgromadziła długą historię decyzji operacyjnych, konwencji nazewniczych, kont serwisowych, wzorców topiców i reguł dostępu. Zanim organizacja zdecyduje się na przejście na Confluent Platform, Kafka nie jest już tylko systemem przesyłania komunikatów. Stanowi część kręgosłupa produkcyjnego.

Ten kontekst ma znaczenie, ponieważ migracje w takich środowiskach to nie tylko projekty techniczne. To ćwiczenia z zarządzania ryzykiem.

W pierwszej fazie migracji do Confluent najbezpieczniejszym podejściem jest zwykle zmienianie jak najmniejszej liczby rzeczy. Celem jest przeniesienie fundamentu platformy, ustabilizowanie go, a dopiero potem wprowadzanie większych usprawnień. Uwierzytelnianie i autoryzacja są częścią tej historii. Istniejące instalacje Kafki często opierają się na ACL Apache Kafka, ponieważ ACL to wbudowany model autoryzacji dostępny w open-source’owej Kafce.

Confluent Platform udostępnia jednak również RBAC: kontrolę dostępu opartą na rolach. RBAC jest zwykle łatwiejszy do ogarnięcia w skali organizacji, lepiej pasuje do nadzoru nad platformą i naturalnie integruje się z innymi komponentami Confluent, takimi jak Metadata Service, Control Center oraz Confluent for Kubernetes.

Pojawia się więc pytanie: jak przejść z istniejącego środowiska Kafka opartego na ACL do Confluent RBAC, nie zamieniając kontroli dostępu w obarczoną wysokim ryzykiem migrację ręczną?

Właśnie dlatego zbudowaliśmy monedula-acl-rbac-converter.

Dlaczego migracja z ACL do RBAC jest trudniejsza, niż się wydaje

Mały klaster Kafka z kilkoma topicami i użytkownikami można zmigrować ręcznie. Przeglądasz ACL, decydujesz o równoważnych rolach RBAC, tworzysz powiązania, weryfikujesz dostęp i usuwasz stare ACL.

Ale tak nie wygląda większość dojrzałych środowisk korporacyjnych.

W rzeczywistych wdrożeniach możesz napotkać setki lub tysiące reguł ACL. Niektóre stworzyły zespoły platformowe. Niektóre zespoły aplikacyjne. Niektóre pochodzą z automatyzacji. Niektóre są stare, ale wciąż używane. Niektóre korzystają ze wzorców topiców z prefiksem. Niektóre odwołują się do użytkowników serwisowych, którzy zostali w międzyczasie przemianowani. Niektóre zostały wyeksportowane ze skryptów, których nikt nie dotykał od lat.

Ręczna migracja w takim kontekście ma kilka problemów:

  • jest powolna,
  • jest podatna na błędy,
  • trudno ją przejrzeć,
  • trudno ją powtórzyć,
  • trudno ją audytować,
  • a staje się niebezpieczna, gdy zaczyna się porządkowanie.

Tworzenie nowych powiązań RBAC to dopiero połowa migracji. Bardziej delikatną częścią jest udowodnienie, że nowe powiązania zapewniają taki sam efektywny dostęp jak stare ACL, i dopiero wtedy usunięcie źródłowych ACL.

Dlatego nie chcieliśmy narzędzia, które po prostu „tłumaczy plik”. Chcieliśmy przepływu migracji.

Co robi konwerter

monedula-acl-rbac-converter to narzędzie wiersza poleceń, które odczytuje istniejące ACL Kafki, konwertuje je na plan powiązań ról RBAC w Confluent i pomaga operatorom przeprowadzić migrację w sposób kontrolowany i audytowalny.

Potrafi odczytywać ACL z wielu rzeczywistych źródeł, w tym z:

  • działającego klastra Kafka,
  • wyeksportowanego wyniku kafka-acls.sh --list,
  • zrzutów JSON, YAML lub CSV,
  • manifestów Strimzi KafkaUser,
  • manifestów Confluent for Kubernetes,
  • działającego klastra Kubernetes,
  • lub skryptu powłoki zawierającego polecenia kafka-acls --add ....

Ten ostatni przypadek jest szczególnie przydatny w środowiskach typu brownfield. Wiele zespołów nie zaczyna od czystego eksportu. Zamiast tego mają stary skrypt instalacyjny, który w pierwszej kolejności utworzył ACL.

Na przykład skrypt wejściowy może zawierać polecenia takie jak:

kafka-acls.sh \
  --bootstrap-server kafka.example.com:9093 \
  --command-config admin.properties \
  --add \
  --allow-principal User:svc-billing \
  --operation Read \
  --topic billing.events \
  --group billing-consumer

kafka-acls.sh \
  --bootstrap-server kafka.example.com:9093 \
  --command-config admin.properties \
  --add \
  --allow-principal User:svc-billing \
  --operation Describe \
  --topic billing.events

Konwerter potrafi wyodrębnić te definicje ACL do kanonicznego pliku acls.json. Stamtąd może wygenerować przejrzany plan migracji, wyemitować skrypty lub manifesty, zastosować powiązania bezpośrednio w Confluent MDS, zweryfikować wynik i wygenerować skrypty czyszczenia dla starych ACL.

Przepływ zaprojektowany dla zmian wysokiego ryzyka

Migracje kontroli dostępu wymagają zabezpieczeń. Błędne uprawnienie może uszkodzić obciążenia produkcyjne. Zbyt szerokie uprawnienie może spowodować incydent bezpieczeństwa. Krok porządkowania wykonany zbyt wcześnie może wywołać awarię.

Z tego powodu przepływ produkcyjny jest jawny i podzielony na kroki:

1. extract       -> utwórz kanoniczny zrzut ACL
2. plan          -> przekonwertuj ACL na plan migracji RBAC
3. apply dry-run -> podejrzyj zmiany w MDS
4. apply         -> utwórz powiązania ról RBAC
5. verify        -> sprawdź efektywny dostęp
6. wait          -> pozwól użytkownikom przećwiczyć nową ścieżkę
7. delete-acls   -> wygeneruj skrypt usuwania starych ACL
8. review + run  -> wykonaj porządkowanie ręcznie

Każdy krok tworzy artefakty, które można zbadać, przejrzeć, wersjonować lub dołączyć do wniosku o zmianę.

Narzędzie celowo oddziela planowanie od stosowania, stosowanie od weryfikacji, a weryfikację od usuwania. Dzięki temu migracja jest łatwiejsza do ogarnięcia i bezpieczniejsza w uruchamianiu w środowiskach regulowanych.

Przykład: migracja ze skryptu konfigurującego ACL

Załóżmy, że punktem wyjścia jest skrypt powłoki z poleceniami kafka-acls.sh --add.

1. Wyodrębnij ACL

Najpierw wyodrębnij ACL do kanonicznej reprezentacji JSON:

monedula-acl-rbac extract \
  --from script \
  --input setup-acls.sh \
  --vars vars.yaml \
  --out runs/billing-batch-1/acls.json

Opcjonalny plik vars.yaml jest przydatny, gdy skrypt zawiera zmienne. Narzędzie nie zgaduje nierozwiązanych wartości. Jeśli występują zmienne, należy je podać jawnie lub skrypt powinien zostać wstępnie rozwinięty przed migracją.

Na tym etapie wynikiem jest wciąż tylko zrzut. Żaden stan zewnętrzny nie jest zmieniany.

2. Utwórz plan migracji

Następnie przekonwertuj wyodrębnione ACL na plan powiązań ról:

monedula-acl-rbac plan \
  --acls runs/billing-batch-1/acls.json \
  --scopes scopes.yaml \
  --rules rules.yaml \
  --principals principals.yaml \
  --out runs/billing-batch-1/plan.json

Plik scopes.yaml identyfikuje klastry Confluent, na które powinny być nakierowane powiązania RBAC. Opcjonalne pliki rules.yaml i principals.yaml pozwalają operatorom dostosować konwersję do swojego środowiska, na przykład mapując źródłowe principale na format principala oczekiwany przez MDS.

Krok planowania generuje również raport. To jeden z najważniejszych punktów przeglądu w całym przepływie. Pokazuje, czym stało się każde źródłowe ACL, i oznacza wszystko, czego nie udało się zmapować lub czego nie należy konwertować automatycznie.

3. Przeczytaj raport

Zanim cokolwiek zostanie zastosowane, operatorzy powinni przeczytać wygenerowany raport.

To tutaj praca migracyjna staje się widoczna. Zamiast polegać na konwersji typu czarna skrzynka, zespół może przejrzeć wygenerowane powiązania, zbadać niezmapowane ACL i zdecydować, czy potrzebne są niestandardowe reguły mapowania.

Na szczególną uwagę zasługują ACL typu DENY. Confluent RBAC nie ma równoważnej semantyki odmowy, więc ACL typu DENY nie są po cichu konwertowane. Są zgłaszane i obsługiwane osobno.

4. Wykonaj krok apply na sucho (dry-run)

Przed utworzeniem powiązań ról w MDS uruchom przebieg na sucho:

monedula-acl-rbac apply \
  --plan runs/billing-batch-1/plan.json \
  --mds-url https://mds.example.com \
  --mds-token-file ~/.confluent/token \
  --dry-run

Przebieg na sucho podgląda wywołania MDS, które zostałyby wykonane. Wykonuje również sprawdzenia odczytu, aby istniejące powiązania mogły zostać idempotentnie pominięte.

Daje to operatorom kolejny punkt kontrolny przed pierwszą rzeczywistą zmianą.

5. Zastosuj powiązania RBAC

Po przejrzeniu wyniku przebiegu na sucho zastosuj plan:

monedula-acl-rbac apply \
  --plan runs/billing-batch-1/plan.json \
  --mds-url https://mds.example.com \
  --mds-token-file ~/.confluent/token \
  --confirm

Krok apply tworzy powiązania RBAC w Confluent MDS. Został zaprojektowany tak, aby można go było ponawiać: jeśli powiązanie już istnieje, jest pomijane.

6. Zweryfikuj efektywny dostęp

Po zastosowaniu powiązań RBAC zweryfikuj, że rzeczywiście przyznają one dostęp pierwotnie zapewniany przez ACL:

monedula-acl-rbac verify \
  --plan runs/billing-batch-1/plan.json \
  --mds-url https://mds.example.com \
  --mds-token-file ~/.confluent/token

To więcej niż sprawdzenie, czy powiązanie istnieje. Celem jest potwierdzenie efektywnego dostępu dla oryginalnego principala, operacji i zasobu.

To rozróżnienie ma znaczenie w środowiskach korporacyjnych, gdzie propagacja tożsamości, przynależność do grup, integracja z LDAP lub niezgodności zakresów (scope) mogą sprawić, że powiązanie istnieje, ale nie zachowuje się zgodnie z oczekiwaniami.

7. Wygeneruj skrypty usuwania ACL

Dopiero po pomyślnej weryfikacji i po zdefiniowanym przez operatora okresie wyczekiwania należy usunąć źródłowe ACL.

Narzędzie nie usuwa ACL bezpośrednio. Zamiast tego generuje skrypt, który operatorzy sami przeglądają i uruchamiają:

monedula-acl-rbac delete-acls \
  --plan runs/billing-batch-1/plan.json \
  --verify runs/billing-batch-1/verify.json \
  --bootstrap-server kafka.example.com:9093 \
  --command-config admin.properties \
  --principal User:svc-billing \
  --confirm \
  --i-understand-this-is-destructive

Wygenerowane artefakty obejmują:

delete-acls.sh
deleted-acls.json
rollback.sh

To celowy punkt kontrolny z udziałem człowieka. Operator może otworzyć skrypt, przejrzeć każde polecenie kafka-acls --remove, uruchomić je dla jednego principala naraz i zachować skrypt wycofania (rollback), dopóki migracja nie będzie stabilna.

Różne wyniki dla różnych modeli operacyjnych

Nie każda organizacja chce tego samego modelu stosowania zmian.

Niektórym zespołom odpowiada stosowanie zmian bezpośrednio w MDS. Inne wymagają, aby każda zmiana przechodziła przez proces kontroli zmian, przepływ GitOps lub zewnętrzny potok CD.

Konwerter wspiera te scenariusze, emitując różne typy artefaktów:

# Skrypt powłoki z poleceniami powiązań ról Confluent CLI
monedula-acl-rbac emit \
  --plan runs/billing-batch-1/plan.json \
  --format script \
  --out-dir emit/

# Manifesty Confluent for Kubernetes
monedula-acl-rbac emit \
  --plan runs/billing-batch-1/plan.json \
  --format cfk \
  --out-dir emit/

# Polecenia curl wobec REST API MDS
monedula-acl-rbac emit \
  --plan runs/billing-batch-1/plan.json \
  --format mds-curl \
  --out-dir emit/

Sprawia to, że narzędzie jest przydatne zarówno do praktycznej pracy migracyjnej, jak i w środowiskach, w których zmiany infrastruktury muszą przejść przez osobny system zatwierdzania i wdrażania.

Stworzone z myślą o rzeczywistym bałaganie migracji

Staraliśmy się obsłużyć rodzaje danych wejściowych i ograniczeń, które pojawiają się w rzeczywistych środowiskach Kafki, a nie tylko czyste przypadki demonstracyjne.

Obejmuje to:

  • ekstrakcję z działającej Kafki,
  • eksporty tekstowe,
  • pliki strukturalne,
  • zasoby natywne dla Kubernetes,
  • istniejące manifesty Confluent for Kubernetes,
  • stare skrypty instalacyjne,
  • remapowanie principali,
  • niestandardowe reguły konwersji,
  • wykonanie na sucho (dry-run),
  • bezpośrednie stosowanie zmian w MDS,
  • emitowane skrypty i manifesty,
  • weryfikację efektywnego dostępu,
  • generowanie skryptów usuwania,
  • artefakty wycofania (rollback),
  • oraz polecenia status/diff dla powtarzalnych partii migracyjnych.

W rezultacie powstało narzędzie, którego można używać zarówno do eksploracji, jak i do migracji klasy produkcyjnej.

Do małych eksperymentów polecenie jednorazowe convert może wykonać ekstrakcję, planowanie i emisję skryptu w jednym kroku:

monedula-acl-rbac convert \
  --from yaml \
  --input acls.yaml \
  --scopes scopes.yaml \
  --rules rules.yaml \
  --principals principals.yaml \
  > bindings.sh

W przypadku produkcji zalecaną ścieżką jest jawny potok, ponieważ zachowuje on artefakty audytowe i punkty przeglądu.

Podsumowanie

Migracja z ACL Kafki do Confluent RBAC to nie tylko problem konwersji składni.

To kontrolowana zmiana modelu autoryzacji działającej platformy danych. W dużych organizacjach, zwłaszcza w bankowości i branżach regulowanych, taka zmiana musi być możliwa do przejrzenia, powtarzalna, audytowalna i — tam, gdzie to możliwe — odwracalna.

Zbudowaliśmy monedula-acl-rbac-converter, ponieważ wciąż widzieliśmy ten sam wzorzec: Kafka już była, ACL już były, a zespoły chciały przyjąć Confluent RBAC bez ręcznego tłumaczenia setek reguł pod presją migracji.

Narzędzie nie ma na celu ukrywania procesu migracji. Ma na celu uczynienie go widocznym.

Wyodrębnij bieżący stan. Zaplanuj stan docelowy. Przejrzyj raport. Wykonaj zmiany na sucho. Stosuj je rozważnie. Zweryfikuj efektywny dostęp. Wygeneruj skrypty czyszczenia. Przejrzyj je. A potem usuń stare ACL dopiero wtedy, gdy będziesz gotowy.

Taki właśnie przepływ chcemy mieć dla migracji kontroli dostępu.

Zbudowaliśmy go, ponieważ jest przydatny dla nas. Mamy nadzieję, że przyda się też innym.

monedula-acl-rbac-converter znajdziesz na GitHubie. Jeśli znajdziesz błąd lub masz sugestię ulepszenia, śmiało otwórz zgłoszenie (issue).