Jamf Concepts

Guides

Wdrażanie Terraform dla Jamf za pomocą jamformer

~18 min read

W naszych poprzednich artykułach, omawialiśmy podstawy Infrastructure as Code z Terraform i Jamf Pro, a następnie przeszliśmy przez dedykowane dostawców Terraform dla Jamf Protect i platformy Jamf. Jeśli jeszcze ich nie przeczytałeś, zalecamy zacząć od nich — obejmują one podstawy Terraform, strukturę projektu, zarządzanie stanem i sposób definiowania zasobów Jamf w kodzie od podstaw.

Tym razem zajmujemy się pytaniem, które słyszą wiele osób: "To wszystko brzmi świetnie, ale mam już setki zasad, profile, skrypty i grupy w swoim środowisku Jamf. Czy naprawdę muszę przepisać to wszystko ręcznie?"

Krótka odpowiedź: nie. Zbudowaliśmy narzędzie o nazwie jamformer, które pomaga dokładnie w tym — ale zanim się w to zagłębiamy, ważne jest, aby być szczerze o tym, czym jest i czym nie jest.

Co to jest jamformer?

jamformer to narzędzie wsparcia i przyspieszenia dla zespołów wdrażających Jamf z Terraform. Łączy się z istniejącą instancją Jamf, odnajduje wszystko co może znaleźć i generuje projekt Terraform jako punkt wyjścia — realistyczny szkielet, z którego można się uczyć i udoskonalać. Pomyśl o nim jako o moście między miejscem, w którym jesteś dzisiaj (w pełni skonfigurowane środowisko Jamf zarządzane za pośrednictwem konsoli) a miejscem, w którym chcesz być (to samo środowisko zarządzane jako kod) — ale most nie jest przenośnikiem. Wciąż idziesz po nim.

Celowo nie jest:

  • Generatorem kodu produkcyjnego. HCL, który produkuje, jest pierwszą wersją. Zanim będziesz zarządzać rzeczywistą infrastrukturą za jego pomocą, spodziewaj się przejrzenia każdego pliku, refaktoryzacji w twoją własną strukturę modułów, zastosowania konwencji nazewnictwa, wzmocnienia obsługi sekretów i radzenia sobie z osobliwościami dryftu dostawcy.
  • Substytutem dla nauki Terraform lub dostawców Jamf. Spłaszcza krzywą uczenia się; nie usuwa jej.
  • Przyciskiem migracji jednym kliknięciem. Duże lub niezwykłe środowiska Jamf zawsze będą wymagać ludzkiego osądu.

Co robi dobrze:

  • Zobaczenie, co naprawdę znajduje się w instancji Jamf, wyrażone w modelu zasobów dostawców Terraform — atrybuty, odwołania krzyżowe, osobliwości cyklu życia i wszystko.
  • Załadowanie dowodem koncepcji, demonstracjami, warsztaty, wewnętrzne szkolenia i sesje planowania migracji.
  • Danie inżynerom realistycznego szkieletu do refaktoryzacji zamiast patrzenia na pusty edytor.

To jest również tylko do odczytu. jamformer nie modyfikuje, nie tworzy ani nie usuwa nic w instancji Jamf. Jedynym, co pisze, jest zestaw plików Terraform na maszynie lokalnej.

Zachowaj tę ramę dla reszty tego artykułu. Gdy przejdziemy przez przepływ pracy i pokażemy przykładowe dane wyjściowe, patrzysz na surowy materiał dla inżyniera człowieka do udoskonalenia — nie na artykuł gotowy.

Dlaczego nie po prostu użyć terraform import?

Absolutnie możesz, a jeśli przeczytałeś artykuł Protect, widziałeś już, jak terraform import i terraform query z blokami list mogą wprowadzić istniejące zasoby pod zarządzanie.

Ale jeśli przez jakiś czas zarządzałeś środowiskiem Jamf za pośrednictwem konsoli, będziesz wiedzieć, że tam jest wiele. Ręczne importowanie wszystkiego oznacza inwentaryzację każdego typu zasobu, napisanie setek bloków importu z poprawnymi identyfikatorami Jamf, ustalenie, która zasada odnosi się do którego skryptu i której grupy i której kategorii, wyodrębnienie osadzonych skryptów i ładunków profilu konfiguracji do samostojących plików oraz radzenie sobie z osobliwościami dostawcy wokół wartości domyślnych.

To dużo pracy. Chcieliśmy to ułatwić.

Co to obsługuje?

jamformer pracuje z czterema dostawcami Terraform w całej rodzinie produktów Jamf:

Dostawca Jak go odkrywa
Jamf Pro (domyślnie) API Jamf Pro
Jamf Protect terraform query
Jamf Platform terraform query
Jamf Security Cloud (JSC) Źródła danych Terraform

Dla Jamf Pro samego, to obejmuje zasady, skrypty, profile konfiguracji, Smart Groups, Static Groups, etapy prestage komputerów, profile urządzeń mobilnych, atrybuty rozszerzenia, pakiety, kategorie, budynki, departamenty i wiele więcej — plus ustawienia, takie jak Client Check-In, Cloud Distribution Point i konfiguracja Self Service. Autorytatywna, zawsze aktualna lista to jamformer -list-resources (opcjonalnie filtrowana za pomocą -provider).

Co się dzieje, gdy go uruchomisz?

Gdy skierujesz jamformer na instancję Jamf, przechodzi przez kilka etapów. Przejdziemy przez każdy z nich, abyś wiedział, co się spodziewać.

Po pierwsze, odkrywa swoje zasoby. Dla Jamf Pro, uwierzytelnia się do instancji (OAuth2 lub auth podstawowy) i wysyła zapytanie API dla każdego obsługiwanego typu zasobu. Przechodzi przez środowisko w porządku zależności — najpierw witryny i kategorie, potem skrypty i pakiety, potem zasady i profile — aby mapować relacje między zasobami. Dla Jamf Protect i Jamf Platform, używa terraform query z blokami list (to samo podejście, które omówiliśmy w artykule Protect), aby odkryć zasoby bezpośrednio za pośrednictwem dostawcy.

Następnie generuje bloki importu. Dla każdego odkrytego zasobu jamformer pisze blok Terraform import z etykietą pochodzącą od nazwy zasobu. Spacje stają się podkreśleniami, znaki specjalne są usuwane, a jeśli dwa zasoby skończyć się z tą samą etykietą, sufiks numeryczny jest dodawany, aby utrzymać rzeczy unikalne. Generuje również provider.tf, variables.tf i terraform.tfvars skonfigurowane dla odpowiedniego dostawcy.

Oto co mogą wyglądać te bloki importu:

import {
  to = jamfpro_policy.software_update_enforce
  id = "142"
}

import {
  to = jamfpro_script.install_rosetta
  id = "87"
}

import {
  to = jamfpro_category.productivity
  id = "5"
}

Następnie prosi Terraform o wygenerowanie HCL. jamformer uruchamia terraform plan -generate-config-out (lub terraform query -generate-config-out dla Protect i Platform), który ma dostawcę produkować HCL dla każdego importowanego zasobu. Ponieważ dostawca sam robi ciężką pracę tutaj, wygenerowana konfiguracja zawsze pasuje do tego, czego oczekuje dostawca.

Jeśli konkretne zasoby nie importują — zdarza się to, czasami dostawca nie może czysto odczytać konkretnego zasobu — jamformer automatycznie usuwa blok importu, który uległ awarii, i ponawia próbę. Zobaczysz wiadomość o tym, które zasoby zostały pominięte, aby możesz je obsługiwać później.

Na koniec czyści dane wyjściowe. Surowe dane wyjściowe z Terraform to jeden duży plik z wartościami literalnymi wszędzie. jamformer przekształca to w coś, co chciałbyś właściwie pracować:

  • jamformer przepisuje literalne identyfikatory Jamf na odwołania Terraform. Zasada, która odnosi się do kategorii ID 5, staje się jamfpro_category.productivity.id, aby Terraform rozumiał relacje między zasobami — dokładnie tak, jak byś to napisał ręcznie.
  • Osadzone skrypty trafiają do poszczególnych plików pod support_files/scripts/, ładunki profilu konfiguracji do support_files/macos_configuration_profiles/, skrypty atrybutów rozszerzenia do support_files/extension_attributes/ i konfiguracje aplikacji urządzenia mobilnego do support_files/app_configurations/. jamformer aktualizuje HCL za pomocą odwołań file(), aby skrypty i profile były właściwymi plikami, które możesz porównać, przejrzeć i edytować niezależnie. Tokeny rejestracji urządzenia i tokeny zakupów zbiorczych używają zmiennych ścieżki file(var.xxx) — umieszczasz pliki tokena (pobrane z Apple Business Manager) w określonej ścieżce.
  • jamformer rozwiązuje zasoby ikon do adresów URL CDN (ikony nie są pobierane lokalnie) i dodaje blok lifecycle { ignore_changes }, aby zapobiec niepotrzebnym cyklom zniszczenia/utworzenia przy pierwszym zastosowaniu.
  • Opcjonalne atrybuty, które wracają jako null, są usuwane, wartości znane, aby powodować problemy (takie jak category_id = -1 dla zasobów niezakategoryzowanych) są usuwane, a jeden duży plik jest podzielony na pliki dla każdego typu zasobu — policies.tf, scripts.tf, categories.tf itd.
  • Przebieg walidacji uruchamia terraform validate w celu wykrycia warunkowych nieprawidłowych atrybutów — na przykład, atrybuty, które są tylko prawidłowe dla określonego typu CDN — i automatycznie je usuwa, aby nie musiał gonić błędów schematu ręcznie.

Po przetworzeniu końcowym, jamformer skanuje dane wyjściowe pod kątem sekretów. Środowiska Jamf często zawierają poświadczenia osadzone w profilach konfiguracji, skryptach i atrybutach zasobów — rzeczy takie jak hasła bind LDAP, poświadczenia SMTP, wspólne tajemnice Wi-Fi i tokeny API. jamformer używa gitleaks z regułami specyficznymi dla Jamf, aby znaleźć je, zanim przypadkowo je zatwierdzisz do Git.

Gdy jamformer znajduje tajemnice, pokazuje Ci raport pogrupowany według zasobu i atrybutu. W trybie interaktywnym możesz wybrać automatyczne naprawienie wszystkich ustaleń, przejść przez nich pojedynczo lub całkowicie pominąć naprawę. Poprawa przenosi tajemnice do zmiennych Terraform wrażliwych — dla plików .tf, wartość tajemna jest zastąpiona odwołaniem var.; dla plików wsparcia, takich jak skrypty i profile, plik jest konwertowany na szablon .tpl przy użyciu templatefile(). Możesz pominąć ten krok za pomocą -skip-secret-scan, jeśli wolisz obsługiwać tajemnice sam.

Pierwsze kroki

Jeśli śledziłeś artykuł wprowadzający, powinieneś już mieć skonfigurowany Terraform i edytor tekstowy. Kroki tutaj są proste.

1. Zainstaluj jamformer

Homebrew:

brew install Jamf-Concepts/tap/jamformer

Wstępnie skompilowane pliki binarne i instalator .pkg są dostępne na stronie wydań.

Nie musisz instalować Terraform oddzielnie — jamformer automatycznie pobiera go do katalogu tymczasowego, więc nie będzie w konflikcie z istniejącą instalacją Terraform na maszynie.

2. Uruchom to dla instancji

Najłatwiej jest po prostu uruchomić jamformer bez argumentów:

jamformer

Przeprowadzi Cię przez wszystko interaktywnie — którego dostawcę chcesz używać, adres URL instancji i poświadczenia. Wpisujesz hasła i tajemnice klienta jako ukryte dane wejściowe, aby nie pojawiły się w historii terminala.

Tutaj działają również adresy URL skrótów — możesz po prostu wpisać yourinstance i jamformer rozszerzy go na yourinstance.jamfcloud.com. Dla Protect, your-tenant rozszerza się na your-tenant.protect.jamfcloud.com.

Gdy jesteś zaznajomiony z narzędziem lub chcesz je skryptować, możesz ustawić poświadczenia za pośrednictwem zmiennych środowiskowych:

# Jamf Pro z OAuth2
export JAMF_CLIENT_ID='your-client-id'
export JAMF_CLIENT_SECRET='your-client-secret'
jamformer -url https://yourinstance.jamfcloud.com

# Jamf Protect
export JAMF_CLIENT_ID='your-client-id'
export JAMF_CLIENT_SECRET='your-client-secret'
jamformer -provider jamfprotect -url https://your-tenant.protect.jamfcloud.com

jamformer odczytuje poświadczenia tylko ze zmiennych środowiskowych lub interaktywnych monitów — nigdy flagi CLI — aby uniknąć wycieków tajemnic w historii powłoki i listach procesów. Możesz przekazać adres URL jako flagę (-url) lub za pośrednictwem JAMF_URL.

jamformer nie pisze poświadczeń do terraform.tfvars i generuje .gitignore, który wyklucza pliki tfvars, pliki stanu i katalog .terraform/.

3. Importowanie wszystkiego na raz jest opcjonalne

Jeśli Twoje środowisko jest duże i wolisz zacząć od małej, możesz kierować określone typy zasobów:

# Zacznij tylko z polityką, skryptami i kategoriami
./jamformer -include-resources "policies scripts categories"

# Wszystko z wyjątkiem pakietów i ikon
./jamformer -exclude-resources "packages icons"

# Zobacz wszystkie dostępne nazwy filtrów
./jamformer -list-resources

Gdy typ zależności nie jest zawarty (powiedzmy, że importujesz zasady, ale nie kategorie), odwołania do tych typów pozostają jako literalne identyfikatory zamiast wyrażeń Terraform. Możesz zawsze ponownie uruchomić z większą liczbą typów później, gdy się zaznajomisz.

Jak naprawdę wyglądają dane wyjściowe?

Po zakończeniu jamformer będziesz mieć katalog, który wygląda mniej więcej tak:

generated/
  .gitignore
  provider.tf
  variables.tf
  terraform.tfvars
  policies.tf
  policies_import.tf
  scripts.tf
  scripts_import.tf
  categories.tf
  categories_import.tf
  ...
  support_files/
    scripts/
      install_rosetta.sh
      set_wallpaper.sh
    extension_attributes/
      battery_health.sh
    macos_configuration_profiles/
      wifi_corporate.mobileconfig
      filevault_enforce.mobileconfig
    device_enrollment_tokens/     (puste - umieść tutaj swoje pliki .p7m)
    volume_purchasing_tokens/     (puste - umieść tutaj swoje pliki .vpptoken)
    app_configurations/
      managed_browser.xml

Każdy typ zasobu otrzymuje własny plik .tf i odpowiedni plik _import.tf. Katalog support_files/ zawiera wyodrębnione skrypty, profile i konfiguracje aplikacji, do których odwołuje się wyrażenie file(). jamformer tworzy katalogi tokena (device_enrollment_tokens/ i volume_purchasing_tokens/) jako zalecaną lokalizację plików tokenów Apple Business Manager — te używają zmiennych ścieżki file(var.xxx), ponieważ API nie zwraca danych tokena.

Tryb kompaktowy

Domyślnie jamformer generuje jeden blok zasobu na obiekt — płaski, jawny układ, który jest łatwy do odczytania i przejrzenia. Ale jeśli twoje środowisko ma dziesiątki podobnych zasobów (kategorie, budynki, departamenty), dane wyjściowe mogą wydawać się powtarzające się.

Flaga -compact konsoliduje uprawnione typy zasobów do wzorów for_each + locals, producując dane wyjściowe, które są bliższe temu, co byś napisał ręcznie:

jamformer -compact

Bez trybu kompaktowego otrzymałbyś poszczególne bloki:

resource "jamfpro_category" "productivity" {
  name = "Productivity"
}

resource "jamfpro_category" "security" {
  name = "Security"
}

Z włączonym trybem kompaktowym, stają się:

locals {
  categories = {
    productivity = { name = "Productivity" }
    security     = { name = "Security" }
  }
}

resource "jamfpro_category" "all" {
  for_each = local.categories
  name     = each.value.name
}

jamformer automatycznie przepisuje odniesienia między zasobami, aby użyć nowego adresowania — jamfpro_category.all["productivity"].id zamiast jamfpro_category.productivity.id — aby wszystko pozostało połączone. Aktualizuje bloki importu w ten sam sposób.

jamformer dynamicznie określa uprawnienia w czasie uruchamiania. Typ zasobu się kwalifikuje, gdy plik zawiera dwa lub więcej bloków zasobów, które wszystkie dzielą ten sam zestaw atrybutów i żaden nie ma zagnieżdżonych bloków (poza lifecycle). Atrybuty, które są identyczne we wszystkich instancjach, stają się wartościami literalnymi na bloku zasobu; tylko wartości, które się zmieniają, trafiają do mapy locals. To działa na wszystkich czterech dostawcach.

Jeśli chcesz bardziej precyzyjną kontrolę, możesz kierować określone typy:

# Tylko kompaktowe kategorie i budynki
jamformer -compact -compact-include "categories buildings"

# Kompaktuj wszystko uprawnione z wyjątkiem zasad
jamformer -compact -compact-exclude "policies"

Obsługa wielu środowisk

⚠️ Eksperymentalne i wysoce zaawansowane. Ta funkcja kieruje osoby, które już biegle posługują się modułami Terraform, przepływami pracy gałęzi długowiecznych i modelem zasobów dostawcy Jamf. Dane wyjściowe są bardziej stopnia szkieletu niż tryb pojedynczego środowiska, a nie mniej — spodziewaj się edycji wygenerowanego modułu, korzeni dla każdego środowiska i ekstrakcji zmiennych, zanim którakolwiek z nich będzie użyteczna. Traktuj to jako funkcję badawczą/wsparcia, a nie obsługiwany przepływ pracy produkcyjny. Jeśli jesteś nowy w Terraform lub wciąż pracujesz nad swoim pierwszym projektem pojedynczej instancji, zacznij tam i wróć tutaj później.

Jeśli zarządzasz wieloma środowiskami Jamf Pro — staging i produkcja, lub dev i prod — prawdopodobnie myślałeś o tym, jak je synchronizować. jamformer może wygenerować projekt Terraform strukturalny wokół modułu udostępnionego z katalogami korzeni dla każdego środowiska, zaprojektowanymi dla przepływu pracy gałęzi Git, w którym każda długowieczna gałąź reprezentuje środowisko.

export JAMF_URL_STAGING=https://staging.jamfcloud.com
export JAMF_CLIENT_ID_STAGING=xxx
export JAMF_CLIENT_SECRET_STAGING=xxx
export JAMF_URL_PROD=https://prod.jamfcloud.com
export JAMF_CLIENT_ID_PROD=xxx
export JAMF_CLIENT_SECRET_PROD=xxx

jamformer -multi-env "staging prod"

jamformer uruchamia odkrywanie niezależnie dla każdego środowiska, dopasowuje zasoby po nazwie i produkuje dane wyjściowe, które wyglądają tak:

generated/
  modules/jamf/                # wspólne definicje zasobów
    policies.tf                # zasoby obecne we wszystkich środowiskach
    scripts.tf
    categories.tf
    policies_staging_only.tf   # zasoby tylko w staging
    variables.tf               # zmienne wejściowe modułu
    providers.tf
    support_files/             # pliki identyczne we wszystkich środowiskach
      scripts/
      macos_configuration_profiles/
  environments/
    staging/
      main.tf                  # konfiguracja dostawcy + wywołanie modułu
      backend.tf               # symbol zastępczy dla stanu backendu
      variables.tf
      terraform.tfvars         # wartości specyficzne dla środowiska
      imports.tf               # bloki importu z przedrostkiem module.jamf.
      support_files/           # pliki, które różnią się od innego env
    prod/
      main.tf
      backend.tf
      variables.tf
      terraform.tfvars
      imports.tf
      support_files/

Wspólny moduł w modules/jamf/ zawiera definicje zasobów wspólne dla wszystkich środowisk. Jeśli wartości atrybutów różnią się w środowiskach — zasada z innym category_id lub profil z innym description — jamformer wyodrębnia te wartości do zmiennych modułu i ustawia je dla każdego środowiska w terraform.tfvars. Odwołania między zasobami pozostają jako właściwe wyrażenia Terraform (np. jamfpro_category.productivity.id), więc relacje między zasobami pozostają niezmienione.

To działa najlepiej, gdy celowo synchronizujesz swoje środowiska — te same zasady, skrypty, profile i grupy wdrażane na wszystkich instancjach. Im bardziej się zgadzają, tym czystsze dane wyjściowe. To powiedziawszy, jamformer obsługuje wspólne różnice w świecie rzeczywistym:

  • Ten sam zasób, inne ustawienia (np. zasada z inną kategorią lub częstotliwością w staging vs prod) — atrybuty, które się różnią, stają się zmiennymi modułu, z wartościami każdego środowiska w własnym terraform.tfvars. jamformer sortuje zmienne alfabetycznie i grupuje je według typu zasobu dla czytelności.
  • Zasoby, które istnieją w niektórych środowiskach, ale nie w innych (np. testowa zasada tylko w staging) — jamformer oddziela je na wyraźnie oznaczone pliki, takie jak policies_staging_only.tf w modułu. Na gałęzi dla innego środowiska po prostu usuniesz te pliki.
  • Pliki wsparcia, które się różnią (np. skrypt z nieco innym treści na wszystkich instancjach) — pliki identyczne we wszystkich środowiskach znajdują się w katalogu wspólnego modułu support_files/. Gdy pliki się różnią, jamformer umieszcza je w katalogu support_files/ każdego środowiska i przekazuje je do modułu jako zmienne.

Każdy katalog środowiska ma własny backend.tf, własny stan i własne bloki importu z przedrostkiem module.jamf.. Oznacza to, że możesz uruchomić terraform plan i terraform apply niezależnie dla każdego środowiska, równolegle, jeśli chcesz, bez żadnego ryzyka, że stan jednego środowiska będzie ingerować w inne.

jamformer używa pierwszego wymienionego środowiska jako źródła prawdy dla wspólnych definicji zasobów; użyj -source-env aby to zmienić. Dopasowuje zasoby po nazwie, więc zasada zwana "Software Update - Enforce" w staging będzie dopasowywać zasadę o tej samej nazwie w prod, niezależnie od ich identyfikatorów Jamf.

Zamierzona przepływ pracy polega na zatwierdzeniu danych wyjściowych do repozytorium, utworzeniu długowiecznej gałęzi dla każdego środowiska, skonfigurowaniu backend.tf każdej gałęzi z odpowiednim stanu backendu i skonfigurowaniu CI do uruchomienia terraform apply w odpowiednim katalog environments/<env>/ gdy kod trafia na tę gałąź. Zmiany przepływają z gałęzi funkcji do pierwszego środowiska, a następnie są promowane przez gałęzie poprzez pull requesty.

Im bardziej Twoje środowiska się różnią, tym więcej zmiennych i plików specyficznych dla środowiska będą zawierać dane wyjściowe. Jeśli Twoje instancje są zasadniczo różne, możesz być lepiej uruchamiając jamformer oddzielnie dla każdego i utrzymując niezależne projekty Terraform.

Praca z wygenerowanymi danymi wyjściowymi

Powiedzieliśmy to na górze i powtórzymy to tutaj, ponieważ to jest część, która ma znaczenie — wygenerowana konfiguracja nie jest gotową do produkcji Terraform. jamformer to narzędzie wsparcia i przyspieszenia. Daje Ci realistyczny punkt wyjścia w podróży do zarządzania środowiskiem Jamf jako kodzie — nie skrót, który Cię tam natychmiast dostaje. Zaplanuj spędzenie rzeczywistego czasu na przeglądzie, udoskonalaniu i rozumieniu tego, co produkuje, zanim cokolwiek kieruje rzeczywistymi zmianami infrastruktury.

Dane wyjściowe są celowo płaskie — jeden blok zasobu na obiekt, jeden plik na typ, bez modułów. W praktyce, prawdopodobnie będziesz chciał refaktoryzować to w strukturę modułów, wykorzystać funkcje HCL, takie jak for_each i locals, aby zmniejszyć powtarzalność, zamienić rzeczy takie jak adresy URL instancji i wspólne ustawienia na zmienne dla Twojego środowiska i zorganizować zasoby w sposób, który ma sens dla Twojego zespołu. jamformer daje Ci surowy materiał, aby to robić; jak go kształtujesz, zależy od Ciebie. Ta praca kształtowania to miejsce, gdzie większość rzeczywistego uczenia się Terraform faktycznie się odbywa — i to cały powód, dla którego jamformer istnieje w tej formie.

Z tym na uwadze, oto przepływ pracy, który byśmy rekomendowali.

Te same polecenia, które nauczyliśmy się w artykule wprowadzającym, mają zastosowanie tutaj:

cd generated
terraform plan       # Przejrzyj plan importu, sprawdź błędy dostawcy

Spodziewaj się różnic w twoim pierwszym planie. Normalne jest widzenie różnic między tym, co generuje Terraform, a tym, co jest faktycznie w instancji Jamf. Niektóre atrybuty mogą wykazywać wartości, które nie odpowiadają temu, co widzisz w konsoli, niektóre opcjonalne pola mogą mieć wartości domyślne, które dostawca wypełnia, które różnią się od żywej konfiguracji, a niektóre zasoby mogą mieć błędy walidacji z powodu pól tylko do zapisu, które dostawca nie potrafi odczytać. To są osobliwości na poziomie dostawcy, a nie błędy w jamformer, i będą wymagać ręcznej uwagi.

Pracuj przez dane wyjściowe planu, napraw wszelkie błędy i dostosuj atrybuty, dopóki nie będziesz zadowolony z tego, co Terraform raportuje. Ten proces przeglądu to miejsce, gdzie będziesz się uczyć najlepiej o tym, jak dostawca reprezentuje zasoby — i to jest ważny krok, zanim przekazujesz kontrolę Terraform.

Gdy plan wygląda czysty:

terraform apply      # Importuj zasoby do stanu (zostaniesz poproszony o potwierdzenie)

Uruchomienie terraform apply tutaj importuje istniejące zasoby w stan Terraform. To nie zmienia nic w Jamf — to tylko mówi Terraform "te zasoby już istnieją i oto jak wyglądają."

Po pomyślnym zastosowaniu, bloki importu zrobiły swoją pracę. Możesz je usunąć:

rm *_import.tf

Następnie uruchom terraform plan ponownie. Idealnie widzisz brak zmian. Jeśli pojawią się różnice, są to przypadki, w których domyślne dostawcy nie całkiem pasują do tego, co jest faktycznie w Jamf — dostosuj wygenerowany HCL, dopóki nie uzyskasz czystego planu.

W tym punkcie masz projekt Terraform, który reprezentuje twoje środowisko Jamf. Zatwierdź go do Git i jesteś gotowy do rozpoczęcia rzeczywistej pracy: udoskonalenia konfiguracji, organizowania jej, aby odpowiadała przepływowi pracy Twojego zespołu, i stopniowego przesuwania się w kierunku wprowadzania zmian poprzez pull requesty, przegląd kodu i terraform apply zamiast konsoli.

Rzeczy, które warto pamiętać

Domyślnie jamformer pobiera pakiety z Cloud Distribution Point. Dla dużych środowisk z wieloma pakietami może to chwilę potrwać. Użyj -skip-package-downloads, aby pominąć ten krok i obsługiwać pakiety oddzielnie.

Skanowanie sekretów odbywa się automatycznie po generacji. Jeśli wolisz obsługiwać zarządzanie tajemnicami sam lub pracujesz w środowisku bezgłownym, użyj -skip-secret-scan, aby je pominąć. Nawet jeśli pomijasz wbudowany skan, zdecydowanie rekomendujemy uruchomienie pewnej formy wykrywania sekretów przed zatwierdzeniem danych wyjściowych do Git.

Tryb kompaktowy (-compact) jest czysto kosmetyczny — zmienia kształt HCL, ale nie to, co robi Terraform. Jeśli nie masz pewności, czy go chcesz, zacznij bez niego i spróbuj go przy drugim uruchomieniu. Możesz również użyć -compact-include i -compact-exclude, aby kierować określone typy zasobów, pozostawiając inne płaskie.

Wygenerowany provider.tf zawiera ograniczenie minimalnej wersji (>= X.Y.Z) na podstawie wersji dostawcy, którą Terraform pobrał. Jeśli wolisz przypiąć dokładną wersję, użyj -provider-version 1.2.3.

Jamf Protect i Jamf Platform wymagają Terraform 1.14+ dla obsługi terraform query. jamformer pobiera to automatycznie, ale warto wiedzieć, jeśli dostarczasz własny plik binarny Terraform za pośrednictwem -terraform-path.

Co dalej

Jeśli śledziłeś całą tę serię, widziałeś teraz, jak napisać Terraform dla Jamf od podstaw, jak zarządzać konfiguracją Jamf Protect i Jamf Platform jako kodzie z dedykowanym dostawcą, a teraz, jak wprowadzić istniejące środowisko pod zarządzanie Terraform bez rozpoczynania od nowa. Więcej mają przyjść — będziemy obejmować dodatkowe tematy w przyszłych artykułach, gdy dostawcy i narzędzia będą się rozwijać.

Aktywnie pracujemy nad jamformer i zbieramy opinię. Jeśli go spróbujesz, chcielibyśmy wiedzieć, co działa, a co nie. Otwórz problem w repozytorium GitHub lub skontaktuj się na Jamf Nation.

Referencje