Google-felhasználók létrehozása a PowerShellből API-n keresztül
Hi!
Ez a cikk a PowerShell és a Google API közötti interakció megvalósítását írja le a G Suite-felhasználók manipulálására.
Számos belső és felhőszolgáltatást használunk a szervezeten belül. A bennük lévő jogosultság többnyire a Google-hoz vagy az Active Directoryhoz tartozik, amelyek között nem tudunk replikát karbantartani, ennek megfelelően új alkalmazott távozásakor ebben a két rendszerben kell fiókot létrehozni/engedélyezni. A folyamat automatizálása érdekében úgy döntöttünk, hogy írunk egy szkriptet, amely információkat gyűjt és elküldi mindkét szolgáltatásnak.
Meghatalmazás
A követelmények kidolgozásakor úgy döntöttünk, hogy valódi emberi adminisztrátorokat használunk az engedélyezéshez, ami leegyszerűsíti a műveletek elemzését véletlen vagy szándékos jelentős változtatások esetén.
A Google API-k az OAuth 2.0 protokollt használják a hitelesítéshez és engedélyezéshez. A felhasználási esetek és a részletesebb leírások itt találhatók: Az OAuth 2.0 használata a Google API-k eléréséhez.
Azt a szkriptet választottam, amelyet az asztali alkalmazások hitelesítésére használnak. Lehetőség van szolgáltatásfiók használatára is, amely nem igényel felesleges mozgást a felhasználótól.
Az alábbi kép a kiválasztott forgatókönyv sematikus leírása a Google oldaláról.
Először a felhasználót a Google Fiók hitelesítési oldalára küldjük, megadva a GET paramétereket:
pályázati azonosító
területek, amelyekhez az alkalmazásnak hozzá kell férnie
az a cím, amelyre a felhasználó az eljárás befejezése után át lesz irányítva
ahogyan frissítjük a tokent
Biztonsági kód
ellenőrző kód átviteli formátuma
Az engedélyezés befejezése után a felhasználó az első kérésben megadott oldalra kerül a GET paraméterek által átadott hiba vagy engedélyezési kóddal.
Az alkalmazásnak (szkriptnek) meg kell kapnia ezeket a paramétereket, és ha megkapta a kódot, akkor a következő kérést kell végrehajtania a tokenek beszerzéséhez
Ha a kérés helyes, a Google API a következőket adja vissza:
Hozzáférési token, amellyel kéréseket tudunk benyújtani
Ennek a tokennek az érvényességi ideje
Frissítési token szükséges a hozzáférési token frissítéséhez.
Először a Google API-konzolra kell lépnie: Hitelesítési adatok – Google API-konzol, válassza ki a kívánt alkalmazást, és a Hitelesítési adatok részben hozzon létre egy ügyfél OAuth-azonosítót. Ott (vagy később, a létrehozott azonosító tulajdonságaiban) meg kell adnia azokat a címeket, amelyekre az átirányítás megengedett. Esetünkben ez több localhost bejegyzés lesz különböző portokkal (lásd alább).
A szkriptalgoritmus kényelmesebb olvasásának érdekében megjelenítheti az első lépéseket egy külön függvényben, amely hozzáférési és frissítési tokeneket ad vissza az alkalmazáshoz:
Beállítjuk az OAuth-kliens azonosító tulajdonságaiban kapott ügyfélazonosítót és ügyféltitkot, a kódellenőrző pedig egy 43-128 karakterből álló karakterlánc, amelyet véletlenszerűen kell előállítani nem fenntartott karakterekből: [AZ] / [az] / [0-9 ] / "-" / "." / "_" / "~".
Ez a kód ezután újra elküldésre kerül. Megszünteti azt a sebezhetőséget, amelyben a támadó elkaphat egy átirányításként visszaküldött választ a felhasználó engedélyezése után.
Az aktuális kérésben kódellenőrzőt küldhet szöveges formában (ami értelmetlenné teszi - ez csak az SHA256-ot nem támogató rendszerekre alkalmas), vagy az SHA256 algoritmussal hash létrehozásával, amelyet BASE64Url-ben kell kódolni (eltérő a Base64-ből két táblázatkarakterrel) és eltávolítjuk a karaktersorvégződéseket: =.
Ezután el kell kezdenünk hallgatni a http-t a helyi gépen, hogy az engedélyezés után választ kapjunk, amelyet átirányításként adunk vissza.
Az adminisztrációs feladatokat egy speciális szerveren hajtják végre, nem zárhatjuk ki annak lehetőségét, hogy a szkriptet egyszerre több rendszergazda is lefuttassa, így véletlenszerűen választ ki egy portot az aktuális felhasználó számára, de előre meghatározott portokat adtam meg, mert ezeket is megbízhatóként kell hozzáadni az API-konzolhoz.
access_type=offline azt jelenti, hogy az alkalmazás képes önállóan frissíteni egy lejárt tokent anélkül, hogy a felhasználó interakcióba lépne a böngészővel, válasz_típus=kód beállítja a kód visszaküldésének formátumát (hivatkozás a régi engedélyezési módra, amikor a felhasználó a kódot a böngészőből a szkriptbe másolta), hatálya a hozzáférés hatókörét és típusát jelzi. Ezeket szóközzel vagy %20-al kell elválasztani (az URL-kódolás szerint). A hozzáférési területek listája típusokkal itt tekinthető meg: OAuth 2.0 hatókörei a Google API-khoz.
Az engedélyezési kód kézhezvétele után az alkalmazás bezárási üzenetet küld a böngészőnek, leállítja a port figyelését, és egy POST kérést küld a token beszerzéséhez. Megjelöljük benne a korábban megadott azonosítót és titkot a konzol API-ból, a címet, ahová a felhasználó átirányítja, valamint a protokoll specifikációjának megfelelő grant_type-ot.
Válaszul kapunk egy Access tokent, annak érvényességi idejét másodpercben, valamint egy Refresh tokent, amellyel frissíthetjük az Access tokent.
Az alkalmazásnak biztonságos helyen, hosszú szavatossági idővel kell tárolnia a tokeneket, így amíg a kapott hozzáférést nem vonjuk vissza, az alkalmazás nem adja vissza a frissítési tokent. A végén hozzáadtam egy kérelmet a token visszavonására; ha az alkalmazás nem fejeződött be sikeresen, és a frissítési token nem érkezett vissza, akkor újraindítja az eljárást (nem tartottuk biztonságosnak a tokenek helyi tárolását a terminálon, és nem nem akarom bonyolítani a dolgokat a kriptográfiával, vagy gyakran megnyitni a böngészőt).
Amint azt már észrevette, egy token visszavonásakor az Invoke-WebRequest használatos. Az Invoke-RestMethoddal ellentétben nem használható formátumban adja vissza a kapott adatokat, és a kérés állapotát mutatja.
Ezután a szkript arra kéri, hogy adja meg a felhasználó vezeték- és utónevét, ezzel bejelentkezési + e-mail címet generál.
kérelmek
A következő kérések a következők lesznek - mindenekelőtt ellenőriznie kell, hogy létezik-e már azonos bejelentkezési névvel rendelkező felhasználó, hogy döntést hozzon egy új létrehozásáról vagy a jelenlegi engedélyezéséről.
Úgy döntöttem, hogy az összes kérést egy funkció formátumában valósítom meg egy kiválasztással, a kapcsoló segítségével:
Minden kérelemben el kell küldenie egy engedélyezési fejlécet, amely tartalmazza a token típusát és magát a hozzáférési tokent. Jelenleg a token típusa mindig Bearer. Mert ellenőriznünk kell, hogy a token nem járt-e le, és frissítenünk kell a kiadás pillanatától számított egy óra elteltével, megadtam egy kérést egy másik függvényre, amely hozzáférési tokent ad vissza. Ugyanez a kódrészlet található a szkript elején, amikor megkapja az első hozzáférési tokent:
Az email:$query kérés arra kéri az API-t, hogy keressen egy felhasználót pontosan ezzel az e-mail-címmel, beleértve az álneveket is. Használhat helyettesítő karaktert is: =, :, :{PREFIX}*.
Adatok beszerzéséhez használja a GET kérési módszert, adatok beszúrásához (fiók létrehozása vagy tag felvétele egy csoportba) - POST, meglévő adatok frissítése - PUT, rekord törlése (például egy tag egy csoportból) - TÖRÖL.
A szkript egy telefonszámot (egy érvényesítetlen karakterláncot) és egy regionális terjesztési csoportba való felvételt is kér. A kiválasztott Active Directory szervezeti egység alapján eldönti, hogy a felhasználónak melyik szervezeti egységgel kell rendelkeznie, és kiad egy jelszót:
do {
$phone = Read-Host "Телефон в формате +7хххххххх"
} while (-not $phone)
do {
$moscow = Read-Host "В Московский офис? (y/n) "
} while (-not (($moscow -eq 'y') -or ($moscow -eq 'n')))
$orgunit = '/'
if ($OU -like "*OU=Delivery,OU=Users,OU=ROOT,DC=rocket,DC=local") {
Write-host "Будет создана в /Team delivery"
$orgunit = "/Team delivery"
}
$Password = -join ( 48..57 + 65..90 + 97..122 | Get-Random -Count 12 | % {[char]$_})+"*Ba"
Aztán elkezdi manipulálni a fiókot:
$query = @{
email = $email
givenName = $firstname
familyName = $lastname
password = $password
phone = $phone
orgunit = $orgunit
}
if ($GMailExist) {
Write-Host "Запускаем изменение аккаунта" -f mag
(GoogleQuery 'UpdateAccount' $query) | fl
write-host "Не забудь проверить группы у включенного $Username в Google."
} else {
Write-Host "Запускаем создание аккаунта" -f mag
(GoogleQuery 'CreateAccount' $query) | fl
}
if ($moscow -eq "y"){
write-host "Добавляем в группу moscowoffice"
$query = @{
groupkey = '[email protected]'
email = $email
}
(GoogleQuery 'AddMember' $query) | fl
}
A fiókfrissítés és a fiók létrehozásának függvényei hasonló szintaxisúak, nem minden további mezőt kell kitölteni, a telefonszámokat tartalmazó részben meg kell adni egy tömböt, amely legfeljebb egy rekordot tartalmazhat a számmal és annak típusával.
Annak érdekében, hogy ne kapjon hibaüzenetet, amikor egy felhasználót adunk hozzá egy csoporthoz, először ellenőrizhetjük, hogy tagja-e már ennek a csoportnak, ha lekérjük a csoporttagok listáját vagy összetételét magától a felhasználótól.
Egy adott felhasználó csoporttagságának lekérdezése nem lesz rekurzív, és csak a közvetlen tagságot mutatja. Sikeres lesz egy felhasználó felvétele egy olyan szülőcsoportba, amelynek már van gyermekcsoportja, amelynek a felhasználó tagja.
Következtetés
Nincs más hátra, mint elküldeni a felhasználónak az új fiók jelszavát. Ezt SMS-ben tesszük, és az általános információkat instrukciókkal és bejelentkezéssel egy személyes e-mailre küldjük, amelyet a telefonszámmal együtt a toborzási osztály biztosított. Alternatív megoldásként pénzt takaríthat meg, és elküldheti jelszavát egy titkos távirati chatre, ami szintén a második tényezőnek tekinthető (a MacBookok kivételek lesznek).
Köszönöm, hogy a végéig elolvastad. Örömmel fogadok javaslatokat a cikkírás stílusának javítására, és kívánom, hogy kevesebb hibát észleljen a szkriptek írásakor =)
Azon linkek listája, amelyek tematikusan hasznosak lehetnek, vagy egyszerűen válaszolhatnak a kérdésekre: