Jakie są zalety umieszczania tajnych wartości witryny jako zmiennych środowiskowych?

24

Wytyczne devops na https://12factor.net/config sugerują umieszczenie tajnych stron internetowych (hasła bazy danych, klucze API itp.) W zmiennych środowiskowych. Jakie zalety ma to zamiast używania plików tekstowych (JSON, XML, YAML, INI itp.) Zignorowanych podczas kontroli wersji?

O wiele łatwiej jest mi skopiować plik konfiguracyjny z kluczami tajnymi niż obsługiwać zmienne środowiskowe w pliku .bash_profile i konfiguracji serwera WWW. Czy coś mi umknęło?

Aidas Bendoraitis
źródło
1
Teoretycznie łatwiej jest odczytać plik niż pamięć, więc można uznać, że powierzchnia ataku jest większa, a złożoność mniejsza.
Florin Asăvoaie,
Zasadą mojego programisty jest, że przechowywanie ustawień w zmiennych środowiskowych najlepiej wykonywać tylko w środowiskach podobnych do dokerów. Poza maszynami wirtualnymi kontenera zatwierdza / preferuje wszystkie inne punkty 12factor.net i użycie plików konfiguracyjnych. Nikt z nas nie lubił niepewnej natury zmiennych środowiskowych podczas regularnych wdrożeń serwera.
Corey Ogburn,

Odpowiedzi:

21

Autor podaje ich uzasadnienie, choć jest to trochę rozłączne. Ich głównym argumentem jest to, że łatwo jest przypadkowo sprawdzić plik konfiguracyjny, a pliki konfiguracyjne mają różne formaty i mogą być rozproszone po całym systemie (wszystkie trzy są w najlepszym razie przeciętnymi argumentami dla konfiguracji związanej z bezpieczeństwem, takimi jak tokeny uwierzytelniania i poświadczenia).

Biorąc pod uwagę moje własne doświadczenie, masz zasadniczo następujące trzy opcje, z powiązanymi zaletami i wadami:

Przechowuj dane w plikach konfiguracyjnych.

Stosując to podejście, najlepiej odizoluj je od samego repozytorium i upewnij się, że znajdują się poza obszarem, w którym aplikacja przechowuje jego zawartość.

Zalety:

  • Bardzo łatwy do wyodrębnienia i kontroli dostępu, szczególnie jeśli używasz takich rzeczy jak SELinux lub AppArmor do poprawy ogólnego bezpieczeństwa systemu.
  • Zasadniczo łatwa do zmiany dla użytkowników nietechnicznych (jest to zaleta dla opublikowanego oprogramowania, ale niekoniecznie dla oprogramowania specyficznego dla Twojej organizacji).
  • Łatwe zarządzanie w dużych grupach serwerów. Istnieje wiele rodzajów narzędzi do wdrażania konfiguracji.
  • Dość łatwo zweryfikować, jaka jest dokładnie używana konfiguracja.
  • W przypadku dobrze napisanej aplikacji można zwykle zmienić konfigurację bez przerywania usługi, aktualizując plik konfiguracyjny, a następnie wysyłając określony sygnał do aplikacji (zwykle SIGHUP).

Niedogodności:

  • Konieczne jest właściwe planowanie, aby zapewnić bezpieczeństwo danych.
  • Być może będziesz musiał nauczyć się różnych formatów (choć w dzisiejszych czasach jest tylko garstka powodów do zmartwienia, a one na ogół mają podobną składnię).
  • Dokładne miejsca przechowywania mogą być zakodowane na stałe w aplikacji, co potencjalnie może utrudnić wdrożenie.
  • Analiza plików konfiguracyjnych może być problematyczna.

Przechowuj dane w zmiennych środowiskowych.

Zwykle odbywa się to przez uzyskanie listy zmiennych środowiskowych i wartości ze skryptu uruchamiania, ale w niektórych przypadkach może po prostu podać je w wierszu poleceń przed nazwą programu.

Zalety:

  • W porównaniu do parsowania pliku konfiguracyjnego wyciąganie wartości ze zmiennej środowiskowej jest banalne w prawie każdym języku programowania.
  • Nie musisz się martwić o przypadkowe opublikowanie konfiguracji.
  • Zyskujesz pewien stopień bezpieczeństwa dzięki niejasnościom, ponieważ taka praktyka jest rzadka, a większość osób, które włamują się do Twojej aplikacji, nie będą od razu myśleć o zmiennych środowiskowych.
  • Dostęp może być kontrolowany przez samą aplikację (gdy spawnuje procesy potomne, może łatwo przeszukiwać środowisko w celu usunięcia poufnych informacji).

Niedogodności

  • W większości systemów UNIX dostęp do zmiennych środowiskowych procesu jest dość łatwy. Niektóre systemy zapewniają sposoby złagodzenia tego (na przykład hidepidopcja montowania /procw LInux), ale nie są domyślnie włączone i nie chronią przed atakami użytkownika będącego właścicielem procesu.
  • Nietrudno jest zobaczyć dokładne ustawienia, których używa dany użytkownik, jeśli poprawnie poradzi sobie z wyżej wymienionym problemem bezpieczeństwa.
  • Musisz ufać aplikacji, że będzie szorować środowisko podczas odradzania procesów potomnych, w przeciwnym razie wyciekną informacje.
  • Nie można łatwo zmienić konfiguracji bez pełnego ponownego uruchomienia aplikacji.

Do przekazywania danych używaj argumentów wiersza polecenia.

Poważnie, unikaj tego za wszelką cenę, nie jest to bezpieczne i utrzymanie go w dupie.

Zalety:

  • Nawet łatwiejsze do przeanalizowania niż zmienne środowiskowe w większości języków.
  • Procesy potomne nie dziedziczą automatycznie danych.
  • Zapewnia łatwy sposób szybkiego przetestowania określonych konfiguracji podczas opracowywania aplikacji.

Niedogodności:

  • Podobnie jak zmienne środowiskowe, w większości systemów łatwo jest odczytać wiersz poleceń innego procesu.
  • Niezwykle żmudne aktualizowanie konfiguracji.
  • Stawia twardy limit czasu trwania konfiguracji (czasami nawet 1024 znaki).
Austin Hemmelgarn
źródło
1
Jednym z nieistotnych punktów jest nienadzorowany (ponowny) rozruch serwera, bez ręcznego podawania żadnych haseł, w końcu są one gdzieś na dysku
PlasmaHH
7
W większości systemów UNIX można odczytywać praktycznie dowolne zmienne środowiskowe procesów bez potrzeby posiadania znaczących uprawnień. - Czy możesz to rozwinąć? Plik / proc / #### / Environment jest czytelny tylko dla właściciela, więc musisz być rootem lub mieć sudo.
rrauenza
Myślę, że niektóre z tych trendów konfiguracji env powstały również z rzeczy takich jak okno dokowane, w którym używasz standardowego kontenera i konfigurujesz go, przekazując zmienne env do kontenera.
rrauenza
@rrauenza Własność procesu nie jest znaczącym przywilejem, chyba że wykonasz bardzo dobrą segregację rzeczy według kont, a faktycznie potrzebujesz tylko możliwości CAP_SYS_ADMIN (która niejawnie ma root), jeśli nie jesteś właścicielem. Ponadto, jeśli chodzi o zmienną środowiskową, prawdopodobnie masz rację, ale jest to marginalna konstrukcja nawet w przypadku Dockera.
Austin Hemmelgarn
3
Zgadzam się z twierdzeniem @rrauenza. Odpowiedź jest całkiem dobra, ale chciałbym wyjaśnić, w jaki sposób dokładnie odczytywać praktycznie dowolne zmienne środowiskowe procesów bez potrzeby posiadania znaczących uprawnień . Odnośnie do „ a tak naprawdę potrzebujesz tylko zdolności CAP_SYS_ADMIN (którą root ma domyślnie) ...” cóż, jeśli złośliwy agent ma uprawnienia rootowania , dalsza dyskusja jest zbędna, a CAP_SYS_ADMIN może być również uprawnieniem roota (patrz man7.org/linux /man-pages/man7/capabilities.7.html , CAP_SYS_ADMIN i uwagi dla programistów jądra )
Nubarke
13

Zmienne środowiskowe będą dziedziczone przez każdy proces potomny serwera WWW. To każda sesja, która łączy się z serwerem i każdy program odradzany przez nich. Sekrety zostaną automatycznie ujawnione wszystkim tym procesom.

Jeśli trzymasz sekrety w plikach tekstowych, muszą one być czytelne dla procesu serwera, a więc potencjalnie dla każdego procesu potomnego. Ale przynajmniej programy muszą je znaleźć i je znaleźć; nie są udostępniane automatycznie. Być może będziesz w stanie sprawić, że niektóre procesy potomne będą działały na różnych kontach, a tajemnice będą czytelne tylko dla tych kont. Na przykład suEXEC robi to w Apache.

Andrew Schulman
źródło
1
„To każda sesja, która łączy się z serwerem” jest mylącym stwierdzeniem. Nie można otworzyć sesji http na serwerze i uzyskać dostępu do jego zmiennych środowiskowych, ani też nie można zalogować się do powłoki na tym serwerze i uzyskać ich, chyba że masz dostęp do konta root lub jesteś właścicielem procesu serwera WWW.
Segfault
Każdy proces odradzany przez serwer WWW dziedziczy jego środowisko, chyba że podejmiesz inne aktywne kroki. Strona HTML nie ma możliwości korzystania z tych informacji, ale skrypt.
Andrew Schulman
Chociaż poprawna, ta odpowiedź może przynieść pewne poprawki / ustępstwa, szczególnie w odniesieniu do tego terminu sesji . Po pierwszym czytaniu wydaje się malować użycie zmiennych środowiskowych w złym świetle, co prawie sugeruje możliwości ujawnienia informacji klientowi zewnętrznemu. Można również uzyskać koncesję porównywalną do suexec dla ograniczonego ustawiania środowisk env, np. Ustawianie env-vars na proces (a la MYVAR=foo /path/to/some/executable) ogranicza propagację do procesu i tylko jego dzieci - i tam, gdzie jest to potrzebne, demony nadrzędne mogą szorować / resetować / modyfikować środowisko procesów potomnych.
shalomb 17.01.2018
2

Nawet jeśli istnieją pewne kompromisy związane z bezpieczeństwem, jeśli chodzi o zmienne środowiskowe lub pliki, nie sądzę, że bezpieczeństwo było główną siłą napędową tego zalecenia. Pamiętaj, że autorzy 12factor.net są (lub byli także?) Twórcami Heroku PaaS. Zapewnienie wszystkim używania zmiennych środowiskowych prawdopodobnie znacznie uprościło ich rozwój. Różnorodność formatów i lokalizacji plików konfiguracyjnych jest tak duża i trudno byłoby je wszystkie obsłużyć. Zmienne środowiskowe są łatwe do porównania.

Nie trzeba wiele wyobraźni, aby odgadnąć niektóre rozmowy.

Deweloper A: „Ach, ten tajny interfejs pliku konfiguracyjnego jest zbyt zagracony! Czy naprawdę potrzebujemy listy rozwijanej, która przełącza się między json, xml i csv?”

Deweloper B: „Och, życie byłoby tak wspaniałe, gdyby tylko wszyscy używali zmiennych środowiskowych do konfiguracji aplikacji”.

Deweloper A: „W rzeczywistości istnieją pewne prawdopodobne powody związane z bezpieczeństwem. Zmienne środowiskowe prawdopodobnie nie zostaną przypadkowo sprawdzone pod kontrolą źródła”.

Deweloper B: „Czy nie ustawiasz zmiennych środowiskowych za pomocą skryptu uruchamiającego demona lub pliku konfiguracyjnego?”

Deweloper A: „Nie w Heroku! Zmusimy ich do wpisania ich w interfejsie użytkownika”.

Deweloper B: „Spójrz, mój alert nazwy domeny dla 12factor.net właśnie wyszedł.”1


1 : źródło: wykonane.

Segfault
źródło
1

TL; DR

Istnieje wiele powodów, dla których warto używać zmiennych środowiskowych zamiast plików konfiguracyjnych, ale dwa z nich najczęściej pomijane to wartość użyteczna konfiguracji pozapasmowej i ulepszonej separacji serwerów, aplikacji lub ról organizacyjnych. Zamiast przedstawiać wyczerpującą listę wszystkich możliwych powodów, w swojej odpowiedzi poruszam tylko te dwa tematy i lekko dotykam ich wpływu na bezpieczeństwo.

Konfiguracja pozapasmowa: oddzielanie sekretów od kodu źródłowego

Jeśli przechowujesz wszystkie swoje sekrety w pliku konfiguracyjnym, musisz rozpowszechniać te sekrety na każdym serwerze. Oznacza to albo sprawdzenie tajemnic w celu kontroli wersji obok kodu, albo posiadanie całkowicie oddzielnego repozytorium lub mechanizmu dystrybucji tajnych danych.

Szyfrowanie twoich tajemnic tak naprawdę nie pomaga w rozwiązaniu tego. Wszystko, co robi, to przesunąć problem do jednego usunięcia, ponieważ teraz musisz się również martwić o zarządzanie kluczami i ich dystrybucję!

Krótko mówiąc, zmienne środowiskowe są podejściem do przenoszenia danych z serwera źródłowego lub aplikacji z kodu źródłowego, gdy chcesz oddzielić programowanie od operacji. Jest to szczególnie ważne, jeśli opublikowałeś kod źródłowy!

Zwiększ separację: serwery, aplikacje i role

Chociaż z pewnością możesz mieć plik konfiguracyjny do przechowywania swoich sekretów, jeśli przechowujesz je w kodzie źródłowym, masz problem ze specyfiką. Czy masz oddzielny oddział lub repozytorium dla każdego zestawu sekretów? Jak upewnić się, że odpowiedni zestaw sekretów trafia na właściwe serwery? Czy też zmniejszasz bezpieczeństwo, mając „tajemnice”, które są wszędzie takie same (lub czytelne wszędzie, jeśli masz je wszystkie w jednym pliku), a zatem stanowią większe ryzyko w przypadku niepowodzenia kontroli bezpieczeństwa jednego systemu?

Jeśli chcesz mieć unikalne sekrety na każdym serwerze lub dla każdej aplikacji, zmienne środowiskowe eliminują problem z zarządzaniem wieloma plikami. Jeśli dodasz nowy serwer, aplikację lub rolę, nie musisz tworzyć nowych plików ani aktualizować starych: wystarczy zaktualizować środowisko danego systemu.

Rozstanie myśli o bezpieczeństwie

Chociaż dogłębne badanie bezpieczeństwa jądra / pamięci / pliku nie wchodzi w zakres tej odpowiedzi, warto zauważyć, że odpowiednio zaimplementowane zmienne środowiskowe dla poszczególnych systemów są nie mniej bezpieczne niż „zaszyfrowane” sekrety. W obu przypadkach system docelowy nadal musi przechowywać odszyfrowany sekret w niektórych momencie, aby ją wykorzystać.

Warto również zauważyć, że gdy wartości są przechowywane w pamięci ulotnej w danym węźle, nie ma pliku na dysku, który można skopiować i zaatakować offline. Jest to ogólnie uważane za zaletę tajemnic w pamięci, ale z pewnością nie jest rozstrzygające.

Kwestia zmiennych środowiskowych w porównaniu z innymi technikami zarządzania tajemnicami dotyczy raczej kompromisów w zakresie bezpieczeństwa i użyteczności niż absolutów. Twój przebieg może się różnić.

CodeGnome
źródło
2
Nie jest to przekonujące, ponieważ wszystkie wady, o których wspomniałeś w przypadku plików konfiguracyjnych, dotyczą również zmiennych środowiskowych. Zmienne środowiskowe to dane konfiguracyjne. Nie ustawiają się magicznie. Muszą być dystrybuowane do każdego systemu, a do ich ustawienia należy użyć pewnego rodzaju mechanizmu konfiguracyjnego .
jpaugh
@jpaugh Kłócisz się o słomkę i atakujesz coś, czego nigdy nie powiedziałem. Problemy, które rozwiązuję, to konfiguracja pozapasmowa i separacja danych. Jak jasno wyjaśniono, możesz robić te rzeczy w dowolny sposób. Jeśli wolisz, możesz opublikować swoje sekrety razem z kodem publicznie na GitHub, ale z pewnością wydaje się to nierozsądne w ogólnym przypadku. Jednakże, tylko ty możesz określić kompromisy niezbędne dla Twojego systemu, aby prawidłowo funkcjonować w ramach danego modelu zagrożenia.
CodeGnome
2
Wszystkie twoje punkty są poprawne, z wyjątkiem tego, że dotyczy to zmiennych środowiskowych w takim samym stopniu, jak wszelkich innych danych konfiguracyjnych. Jeśli przechowujesz zmienne środowiskowe w plikach, możesz je zatwierdzić; a jeśli wysyłasz je poza pasmem, łatwiej jest to zrobić w pliku niż wpisując je. Ale jeśli wolisz je wpisać, dlaczego zamiast tego nie napisać obiektu JSON i przeczytać go na standardowym ekranie? To jest właściwie bezpieczniejsze niż wiersz poleceń.
jpaugh
1

Osobiście nie zalecałbym ustawiania zmiennych środowiskowych, .bashrcponieważ stają się one widoczne dla wszystkich procesów uruchomionych przez powłokę, ale ustawiania ich na poziomie demona / przełożonego (skrypt init / rc, konfiguracja systemd), aby ich zakres był ograniczony w razie potrzeby .

Tam, gdzie oddzielne zespoły zarządzają operacjami, zmienne środowiskowe zapewniają łatwy interfejs do ustawiania środowiska dla aplikacji bez konieczności znajomości plików / formatów konfiguracji i / lub uciekania się do zniekształcania ich zawartości. Jest to szczególnie prawdziwe w ustawieniach wielojęzycznych / wieloramowych, w których zespoły operacyjne mogą wybrać system wdrażania (system operacyjny, procesy nadzorcy) w zależności od potrzeb operacyjnych (łatwość wdrożenia, skalowalność, bezpieczeństwo itp.).

Innym zagadnieniem są potoki CI / CD - ponieważ kod przechodzi przez różne środowiska(tj. dev, test / qa, inscenizacja, produkcja) dane środowiskowe (strefy wdrażania, dane połączenia z bazą danych, dane uwierzytelniające, adresy IP, nazwy domen itp.) są najlepiej ustawiane przez dedykowane narzędzia / struktury zarządzania konfiguracją i wykorzystywane przez aplikację procesy ze środowiska (w OSUSZANIU, napisz raz, uruchom dowolne miejsce). Tradycyjnie, gdy programiści mają tendencję do zarządzania tymi problemami operacyjnymi, mają tendencję do rejestrowania plików konfiguracyjnych lub szablonów oprócz kodu - a następnie dodają obejścia i inną złożoność, gdy zmieniają się wymagania operacyjne (np. Nowe środowiska / wdrożenie / witryny przychodzą, skalowalność / bezpieczeństwo zważyć,

  • Env-vars upraszczają konfigurację / złożoność na dużą skalę.
  • Env-vars umieszczają konfigurację operacyjną dokładnie razem z zespołem odpowiedzialnym za aspekty aplikacji niezwiązane z kodem w jednolity (jeśli nie standardowy), niewiążący sposób.
  • Env-vars obsługują zamianę procesów master / superwizora (np. God, monitor, supervisord, sysvinit, systemd itp.), Które wspierają aplikację - a na pewno nawet system wdrażania (systemy operacyjne, obrazy kontenerów itp.) Itd. Jako wymagania operacyjne ewoluować / zmieniać. Podczas gdy każdy framework językowy ma obecnie pewien rodzaj środowiska uruchomieniowego procesu, są one zazwyczaj gorsze pod względem operacyjnym, bardziej odpowiednie dla środowisk programistycznych i / lub zwiększają złożoność w środowiskach produkcyjnych w wielu językach / w wielu środowiskach.

W przypadku produkcji wolę ustawić środowisko aplikacji w pliku środowiska, takim jak ten, /etc/default/myapplication.confktóry jest wdrażany przez zarządzanie konfiguracją i ustawiany do odczytu tylko przezroot takiego systemd( aby cokolwiek innego w tym przypadku) mógł odrodzić aplikację pod dedykowanym użytkownikiem systemu z uprawnieniami w trybie prywatnym grupa . Wspierane przez dedykowane grupy użytkowników dla opsi sudo- te pliki są domyślnie nieczytelne na całym świecie. Jest to zgodne z 12-czynnikowym wsparciem dla wszystkich zalet Dev + Ops plus, które ma wszystkie zalety przyzwoitego bezpieczeństwa, jednocześnie pozwalając programistom / testerom na upuszczenie własnych plików EnvironmentFiles w środowiskach dev / qa / testowych.

shalomb
źródło
0

Z perspektywy programisty przechowywanie danych konfiguracyjnych w zmiennych środowiskowych upraszcza wdrażanie w różnych środowiskach - programistycznych, kontroli jakości i produkcji - i uwalnia programistów od martwienia się o wdrożenie niewłaściwego pliku konfiguracyjnego.

Aplikacje sieci Web platformy Azure zapewniają opcję użycia tego wzorca i działa bardzo dobrze.

Ponadto chroni potencjalnie wrażliwe dane przed kontrolą źródła. Zignorowanie tych plików z kontroli źródła nie jest tak naprawdę wykonalne (przynajmniej w .NET), ponieważ w tych plikach znajduje się również wiele niezbędnych konfiguracji płyty głównej.

Derek Gusoff
źródło