Den här artikeln kommer att beskriva implementeringen av PowerShell-interaktion med Googles API för att manipulera G Suite-användare.
Vi använder flera interna och molntjänster över hela organisationen. För det mesta kommer auktoriseringen i dem ner på Google eller Active Directory, mellan vilka vi inte kan upprätthålla en replik; följaktligen, när en ny anställd slutar, måste du skapa/aktivera ett konto i dessa två system. För att automatisera processen bestämde vi oss för att skriva ett skript som samlar in information och skickar den till båda tjänsterna.
Bemyndigande
När vi utarbetade kraven bestämde vi oss för att använda riktiga mänskliga administratörer för auktorisering, detta förenklar analysen av åtgärder vid oavsiktliga eller avsiktliga stora förändringar.
Jag valde skriptet som används för auktorisering i skrivbordsapplikationer. Det finns också en möjlighet att använda ett tjänstekonto, vilket inte kräver onödiga rörelser från användaren.
Bilden nedan är en schematisk beskrivning av det valda scenariot från Google-sidan.
Först skickar vi användaren till sidan för Google-kontoautentisering och anger GET-parametrar:
ansöknings-ID
områden som applikationen behöver åtkomst till
adressen som användaren kommer att omdirigeras till efter att ha slutfört proceduren
hur vi kommer att uppdatera token
Säkerhetskod
överföringsformat för verifieringskod
Efter att auktoriseringen är slutförd kommer användaren att omdirigeras till sidan som anges i den första begäran, med ett fel eller auktoriseringskod som skickas av GET-parametrar
Applikationen (skriptet) kommer att behöva ta emot dessa parametrar och, om den får koden, göra följande begäran för att få tokens
Om begäran är korrekt returnerar Googles API:
Åtkomsttoken som vi kan göra förfrågningar med
Giltighetsperioden för denna token
Uppdatera token krävs för att uppdatera åtkomsttoken.
Först måste du gå till Google API-konsolen: Användaruppgifter – Google API-konsol, välj önskat program och skapa en klient-OAuth-identifierare i avsnittet Inloggningsuppgifter. Där (eller senare, i egenskaperna för den skapade identifieraren) måste du ange adresserna till vilka omdirigering är tillåten. I vårt fall kommer dessa att vara flera lokala värdposter med olika portar (se nedan).
För att göra det bekvämare att läsa skriptalgoritmen kan du visa de första stegen i en separat funktion som kommer att returnera Access och uppdatera tokens för applikationen:
Vi ställer in klient-ID och klienthemlighet som erhållits i OAuth-klientidentifierarens egenskaper, och kodverifieraren är en sträng på 43 till 128 tecken som måste genereras slumpmässigt från oreserverade tecken: [AZ] / [az] / [0-9 ] / "-" / "." / "_" / "~".
Denna kod kommer sedan att sändas igen. Det eliminerar sårbarheten där en angripare kan fånga upp ett svar som returneras som en omdirigering efter användarauktorisering.
Du kan skicka en kodverifierare i den aktuella förfrågan i klartext (vilket gör det meningslöst - detta är endast lämpligt för system som inte stöder SHA256), eller genom att skapa en hash med SHA256-algoritmen, som måste kodas i BASE64Url (avvikande från Base64 med två tabelltecken) och ta bort teckenradsändelserna: =.
Därefter måste vi börja lyssna på http på den lokala maskinen för att få ett svar efter auktorisering, som kommer att returneras som en omdirigering.
Administrativa uppgifter utförs på en speciell server, vi kan inte utesluta möjligheten att flera administratörer kommer att köra skriptet samtidigt, så det kommer slumpmässigt välja en port för den aktuella användaren, men jag angav fördefinierade portar eftersom de måste också läggas till som betrodda i API-konsolen.
access_type=offline betyder att applikationen kan uppdatera en utgången token på egen hand utan användarinteraktion med webbläsaren, response_type=kod ställer in formatet för hur koden kommer att returneras (en referens till den gamla auktoriseringsmetoden, när användaren kopierade koden från webbläsaren till skriptet), omfattning anger omfattning och typ av åtkomst. De måste separeras med mellanslag eller %20 (enligt URL-kodning). En lista över åtkomstområden med typer kan ses här: OAuth 2.0 Scopes för Google API:er.
Efter att ha mottagit auktoriseringskoden kommer applikationen att returnera ett stängningsmeddelande till webbläsaren, sluta lyssna på porten och skicka en POST-förfrågan för att erhålla token. Vi anger i den det tidigare angivna ID:t och hemligheten från konsolens API, adressen till vilken användaren kommer att omdirigeras och grant_type i enlighet med protokollspecifikationen.
Som svar kommer vi att få en Access-token, dess giltighetstid i sekunder och en Refresh-token, med vilken vi kan uppdatera Access-token.
Applikationen måste förvara tokens på en säker plats med lång hållbarhetstid, så tills vi återkallar den mottagna åtkomsten kommer applikationen inte att returnera uppdateringstoken. I slutet lade jag till en begäran om att återkalla token; om applikationen inte slutfördes framgångsrikt och uppdateringstoken inte returnerades kommer den att starta proceduren igen (vi ansåg att det var osäkert att lagra tokens lokalt på terminalen, och vi gör det vill inte komplicera saker med kryptografi eller öppna webbläsaren ofta).
Som du redan märkt, när du återkallar en token, används Invoke-WebRequest. Till skillnad från Invoke-RestMethod returnerar den inte mottagna data i ett användbart format och visar status för begäran.
Därefter ber skriptet dig att ange användarens för- och efternamn, vilket genererar en inloggning + e-post.
förfrågningar
Nästa förfrågningar blir - först och främst måste du kontrollera om en användare med samma inloggning redan finns för att få ett beslut om att skapa en ny eller aktivera den nuvarande.
Jag bestämde mig för att implementera alla förfrågningar i formatet av en funktion med ett urval, med hjälp av switch:
I varje begäran måste du skicka en auktoriseringsrubrik som innehåller tokentypen och själva åtkomsttokenen. För närvarande är tokentypen alltid Bärare. Därför att vi måste kontrollera att token inte har gått ut och uppdatera den efter en timme från det att den utfärdades, jag angav en begäran om en annan funktion som returnerar en Access-token. Samma kodbit finns i början av skriptet när du tar emot den första åtkomsttoken:
Email:$query-begäran kommer att be API:et leta efter en användare med exakt den e-postadressen, inklusive alias. Du kan också använda jokertecken: =, :, :{PREFIX}*.
För att erhålla data, använd metoden GET-begäran, för att infoga data (skapa ett konto eller lägga till en medlem i en grupp) - POST, för att uppdatera befintliga data - PUT, för att radera en post (till exempel en medlem från en grupp) - RADERA.
Skriptet kommer också att fråga efter ett telefonnummer (en ovaliderad sträng) och för inkludering i en regional distributionsgrupp. Den bestämmer vilken organisationsenhet användaren ska ha baserat på den valda Active Directory OU-enheten och kommer med ett lösenord:
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"
Och sedan börjar han manipulera kontot:
$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
}
Funktionerna för att uppdatera och skapa ett konto har en liknande syntax; inte alla ytterligare fält krävs; i avsnittet med telefonnummer måste du ange en array som kan innehålla upp till en post med numret och dess typ.
För att inte få ett felmeddelande när du lägger till en användare i en grupp kan vi först kontrollera om han redan är medlem i denna grupp genom att få en lista över gruppmedlemmar eller sammansättning från användaren själv.
Att fråga efter gruppmedlemskap för en specifik användare kommer inte att vara rekursivt och visar bara direkt medlemskap. Att inkludera en användare i en överordnad grupp som redan har en underordnad grupp som användaren är medlem i kommer att lyckas.
Slutsats
Allt som återstår är att skicka användaren lösenordet för det nya kontot. Vi gör detta via SMS, och skickar allmän information med instruktioner och inloggning till ett personligt mejl, som tillsammans med ett telefonnummer lämnats av rekryteringsavdelningen. Som ett alternativ kan du spara pengar och skicka ditt lösenord till en hemlig telegramchatt, vilket också kan betraktas som den andra faktorn (MacBooks kommer att vara ett undantag).
Tack för att du läste till slutet. Jag kommer gärna se förslag för att förbättra stilen att skriva artiklar och önskar att du ska få färre fel när du skriver manus =)
Lista över länkar som kan vara tematiskt användbara eller helt enkelt svara på frågor: