Tsim Google Cov Neeg Siv los ntawm PowerShell ntawm API

Nyob zoo!

Kab lus no yuav piav qhia txog kev siv PowerShell kev cuam tshuam nrog Google API los tswj cov neeg siv G Suite.

Peb siv ntau qhov kev pabcuam sab hauv thiab huab thoob plaws lub koom haum. Rau feem ntau, kev tso cai hauv lawv los rau Google lossis Active Directory, ntawm qhov uas peb tsis tuaj yeem tuav ib qho kev hloov pauv; raws li, thaum tus neeg ua haujlwm tshiab tawm, koj yuav tsum tsim / ua kom muaj tus account hauv ob lub tshuab no. Txhawm rau kom ua tiav cov txheej txheem, peb txiav txim siab sau tsab ntawv uas sau cov ntaub ntawv thiab xa mus rau ob qho kev pabcuam.

Tso Cai

Thaum kos cov kev xav tau, peb txiav txim siab siv tib neeg cov thawj coj tiag tiag rau kev tso cai; qhov no ua kom yooj yim rau kev soj ntsuam ntawm kev ua thaum muaj xwm txheej los yog txhob txwm hloov pauv loj.

Google APIs siv OAuth 2.0 raws tu qauv rau authentication thiab tso cai. Cov ntaub ntawv siv thiab cov lus piav qhia ntxaws ntxiv tuaj yeem pom ntawm no: Siv OAuth 2.0 kom nkag mus rau Google APIs.

Kuv xaiv tsab ntawv uas siv rau kev tso cai hauv daim ntawv thov desktop. Kuj tseem muaj kev xaiv los siv tus as-qhauj kev pabcuam, uas tsis tas yuav tsum muaj kev txav mus los ntawm tus neeg siv.

Daim duab hauv qab no yog cov lus piav qhia ntawm cov xwm txheej xaiv los ntawm Google nplooj ntawv.

Tsim Google Cov Neeg Siv los ntawm PowerShell ntawm API

  1. Ua ntej, peb xa tus neeg siv mus rau nplooj ntawv Google Account authentication, qhia txog GET tsis:
    • siv id
    • thaj chaw uas daim ntawv thov xav tau nkag mus
    • qhov chaw nyob uas tus neeg siv yuav raug xa rov qab tom qab ua tiav cov txheej txheem
    • txoj kev peb yuav hloov kho lub token
    • Kev ruaj ntseg Code
    • pov thawj code kis hom ntawv

  2. Tom qab kev tso cai tiav lawm, tus neeg siv yuav raug xa mus rau nplooj ntawv teev tseg hauv thawj qhov kev thov, nrog rau qhov yuam kev lossis kev tso cai code dhau los ntawm GET tsis.
  3. Daim ntawv thov (script) yuav tsum tau txais cov kev txwv no thiab, yog tias tau txais cov cai, ua cov lus thov hauv qab no kom tau txais tokens
  4. Yog tias qhov kev thov yog lawm, Google API rov qab los:
    • Access token uas peb tuaj yeem thov
    • Lub sijhawm siv tau ntawm lub cim no
    • Refresh token yuav tsum tau ua kom tshiab Access token.

Ua ntej koj yuav tsum mus rau Google API console: Daim ntawv pov thawj - Google API Console, xaiv daim ntawv thov uas xav tau thiab hauv ntu Daim Ntawv Pov Thawj tsim tus neeg siv OAuth tus cim. Muaj (los yog tom qab ntawd, nyob rau hauv cov khoom ntawm tus tsim identifier) ​​​​koj yuav tsum qhia kom meej cov chaw nyob uas redirection tso cai. Nyob rau hauv peb cov ntaub ntawv, cov no yuav yog ob peb localhost nkag nrog txawv ports (saib hauv qab).

Txhawm rau ua kom yooj yim dua rau kev nyeem cov ntawv algorithm, koj tuaj yeem tso saib thawj cov kauj ruam hauv kev ua haujlwm cais uas yuav rov qab nkag mus thiab rov ua dua tshiab tokens rau daim ntawv thov:

$client_secret = 'Our Client Secret'
$client_id = 'Our Client ID'
function Get-GoogleAuthToken {
  if (-not [System.Net.HttpListener]::IsSupported) {
    "HttpListener is not supported."
    exit 1
  }
  $codeverifier = -join ((65..90) + (97..122) + (48..57) + 45 + 46 + 95 + 126 |Get-Random -Count 60| % {[char]$_})
  $hasher = new-object System.Security.Cryptography.SHA256Managed
  $hashByteArray = $hasher.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($codeverifier))
  $base64 = ((([System.Convert]::ToBase64String($hashByteArray)).replace('=','')).replace('+','-')).replace('/','_')
  $ports = @(10600,15084,39700,42847,65387,32079)
  $port = $ports[(get-random -Minimum 0 -maximum 5)]
  Write-Host "Start browser..."
  Start-Process "https://accounts.google.com/o/oauth2/v2/auth?code_challenge_method=S256&code_challenge=$base64&access_type=offline&client_id=$client_id&redirect_uri=http://localhost:$port&response_type=code&scope=https://www.googleapis.com/auth/admin.directory.user https://www.googleapis.com/auth/admin.directory.group"
  $listener = New-Object System.Net.HttpListener
  $listener.Prefixes.Add("http://localhost:"+$port+'/')
  try {$listener.Start()} catch {
    "Unable to start listener."
    exit 1
  }
  while (($code -eq $null)) {
    $context = $listener.GetContext()
    Write-Host "Connection accepted" -f 'mag'
    $url = $context.Request.RawUrl
    $code = $url.split('?')[1].split('=')[1].split('&')[0]
    if ($url.split('?')[1].split('=')[0] -eq 'error') {
      Write-Host "Error!"$code -f 'red'
      $buffer = [System.Text.Encoding]::UTF8.GetBytes("Error!"+$code)
      $context.Response.ContentLength64 = $buffer.Length
      $context.Response.OutputStream.Write($buffer, 0, $buffer.Length)
      $context.Response.OutputStream.Close()
      $listener.Stop()
      exit 1
    }
    $buffer = [System.Text.Encoding]::UTF8.GetBytes("Now you can close this browser tab.")
    $context.Response.ContentLength64 = $buffer.Length
    $context.Response.OutputStream.Write($buffer, 0, $buffer.Length)
    $context.Response.OutputStream.Close()
    $listener.Stop()
  }
  Return Invoke-RestMethod -Method Post -Uri "https://www.googleapis.com/oauth2/v4/token" -Body @{
    code = $code
    client_id = $client_id
    client_secret = $client_secret
    redirect_uri = 'http://localhost:'+$port
    grant_type = 'authorization_code'
    code_verifier   = $codeverifier
  }
  $code = $null

Peb teeb tus Client ID thiab Client Secret tau txais nyob rau hauv OAuth tus neeg siv tus cim cov khoom, thiab tus lej pov thawj yog ib txoj hlua ntawm 43 txog 128 tus cim uas yuav tsum tau tsim los ntawm cov cim uas tsis muaj npe: [AZ] / [az] / [0-9] / "-" / "." / "_" / "~".

Cov lej no yuav raug xa rov qab. Nws tshem tawm qhov tsis txaus ntseeg uas tus neeg tawm tsam tuaj yeem cuam tshuam cov lus teb rov qab los ua kev hloov pauv tom qab tus neeg siv tso cai.
Koj tuaj yeem xa tus lej pov thawj hauv qhov kev thov tam sim no hauv cov ntawv ntshiab (uas ua rau nws tsis muaj nuj nqis - qhov no tsuas yog tsim rau cov tshuab uas tsis txhawb SHA256), lossis los ntawm kev tsim cov hash siv SHA256 algorithm, uas yuav tsum tau encoded hauv BASE64Url ( txawv. los ntawm Base64 los ntawm ob lub ntsiab lus) thiab tshem tawm cov cim kab xaus: = .

Tom ntej no, peb yuav tsum pib mloog http ntawm lub tshuab hauv zos kom tau txais cov lus teb tom qab kev tso cai, uas yuav raug xa rov qab raws li kev xa rov qab.

Cov haujlwm tswj hwm tau ua tiav ntawm tus neeg rau zaub mov tshwj xeeb, peb tsis tuaj yeem txiav txim siab qhov ua tau tias ntau tus thawj coj yuav khiav cov ntawv nyob rau tib lub sijhawm, yog li nws yuav xaiv qhov chaw nres nkoj rau tus neeg siv tam sim no, tab sis kuv tau teev cov chaw nres nkoj ua ntej vim lawv kuj yuav tsum tau ntxiv raws li kev ntseeg siab hauv API console.

access_type=offline txhais tau hais tias daim ntawv thov tuaj yeem hloov kho lub token tas sij hawm ntawm nws tus kheej yam tsis muaj kev sib cuam tshuam nrog tus browser,
response_type=cov teeb tsa cov qauv ntawm yuav ua li cas tus lej yuav raug xa rov qab (ib qho kev siv rau txoj kev tso cai qub, thaum tus neeg siv tau theej cov cai los ntawm browser mus rau hauv tsab ntawv),
muaj qhia txog qhov thiab hom kev nkag. Lawv yuav tsum tau muab cais los ntawm qhov chaw lossis %20 (raws li URL Encoding). Daim ntawv teev cov chaw nkag nrog hom tuaj yeem pom ntawm no: OAuth 2.0 Scopes rau Google APIs.

Tom qab tau txais cov cai tso cai, daim ntawv thov yuav rov qab cov lus nyob ze rau qhov browser, nres mloog ntawm qhov chaw nres nkoj thiab xa POST thov kom tau txais lub token. Peb qhia rau hauv nws yav dhau los id thiab zais cia los ntawm console API, qhov chaw nyob uas tus neeg siv yuav raug xa rov qab thiab grant_type raws li cov txheej txheem tshwj xeeb.

Hauv kev teb, peb yuav tau txais Access token, nws lub sijhawm siv tau hauv vib nas this, thiab Refresh token, uas peb tuaj yeem hloov kho Access token.

Daim ntawv thov yuav tsum khaws cov tokens hauv qhov chaw ruaj ntseg nrog lub neej ntev, yog li kom txog thaum peb tshem tawm qhov kev nkag tau txais, daim ntawv thov yuav tsis xa rov qab cov token tshiab. Thaum kawg, kuv tau ntxiv qhov kev thov kom tshem tawm lub token; yog tias daim ntawv thov tsis ua tiav tiav thiab lub token rov qab tsis tau rov qab, nws yuav pib txheej txheem dua (peb suav tias nws tsis zoo rau khaws cov token hauv zos ntawm lub davhlau ya nyob twg, thiab peb tsis 'tsis xav ua kom nyuaj nrog cryptography lossis qhib browser nquag).

do {
  $token_result = Get-GoogleAuthToken
  $token = $token_result.access_token
  if ($token_result.refresh_token -eq $null) {
    Write-Host ("Session is not destroyed. Revoking token...")
    Invoke-WebRequest -Uri ("https://accounts.google.com/o/oauth2/revoke?token="+$token)
  }
} while ($token_result.refresh_token -eq $null)
$refresh_token = $token_result.refresh_token
$minute = ([int]("{0:mm}" -f ([timespan]::fromseconds($token_result.expires_in))))+((Get-date).Minute)-2
if ($minute -lt 0) {$minute += 60}
elseif ($minute -gt 59) {$minute -=60}
$token_expire = @{
  hour = ([int]("{0:hh}" -f ([timespan]::fromseconds($token_result.expires_in))))+((Get-date).Hour)
  minute = $minute
}

Raws li koj twb pom lawm, thaum tshem tawm lub token, Invoke-WebRequest yog siv. Tsis zoo li Invoke-RestMethod, nws tsis xa rov qab cov ntaub ntawv tau txais hauv hom siv tau thiab qhia cov xwm txheej ntawm kev thov.

Tom ntej no, tsab ntawv hais kom koj nkag mus rau tus neeg siv lub npe thiab lub xeem, tsim tus ID nkag mus + email.

Thov

Cov kev thov tom ntej no yuav yog - ua ntej ntawm tag nrho cov, koj yuav tsum xyuas seb tus neeg siv nrog tib tus ID nkag mus twb muaj nyob rau hauv thiaj li yuav tau txais kev txiav txim siab ntawm kev tsim ib qho tshiab los yog ua kom muaj qhov tam sim no.

Kuv txiav txim siab los siv tag nrho cov lus thov hauv ib qho kev ua haujlwm nrog kev xaiv, siv qhov hloov pauv:

function GoogleQuery {
  param (
    $type,
    $query
  )
  switch ($type) {
    "SearchAccount" {
      Return Invoke-RestMethod -Method Get -Uri "https://www.googleapis.com/admin/directory/v1/users" -Headers @{Authorization = "Bearer "+(Get-GoogleToken)} -Body @{
        domain = 'rocketguys.com'
        query  = "email:$query"
      }
    }
    "UpdateAccount" {
      $body = @{
        name  = @{
          givenName = $query['givenName']
          familyName = $query['familyName']
        }
        suspended = 'false'
        password = $query['password']
        changePasswordAtNextLogin = 'true'
        phones = @(@{
          primary = 'true'
          value = $query['phone']
          type = "mobile"
        })
        orgUnitPath = $query['orgunit']
      }
      Return Invoke-RestMethod -Method Put -Uri ("https://www.googleapis.com/admin/directory/v1/users/"+$query['email']) -Headers @{Authorization = "Bearer "+(Get-GoogleToken)} -Body (ConvertTo-Json $body) -ContentType 'application/json; charset=utf-8'
    }
    
    "CreateAccount" {
      $body = @{
        primaryEmail = $query['email']
        name  = @{
          givenName = $query['givenName']
          familyName = $query['familyName']
        }
        suspended = 'false'
        password = $query['password']
        changePasswordAtNextLogin = 'true'
        phones = @(@{
          primary = 'true'
          value = $query['phone']
          type = "mobile"
        })
        orgUnitPath = $query['orgunit']
      }
      Return Invoke-RestMethod -Method Post -Uri "https://www.googleapis.com/admin/directory/v1/users" -Headers @{Authorization = "Bearer "+(Get-GoogleToken)} -Body (ConvertTo-Json $body) -ContentType 'application/json; charset=utf-8'
    }
    "AddMember" {
      $body = @{
        userKey = $query['email']
      }
      $ifrequest = Invoke-RestMethod -Method Get -Uri "https://www.googleapis.com/admin/directory/v1/groups" -Headers @{Authorization = "Bearer "+(Get-GoogleToken)} -Body $body
      $array = @()
      foreach ($group in $ifrequest.groups) {$array += $group.email}
      if ($array -notcontains $query['groupkey']) {
        $body = @{
          email = $query['email']
          role = "MEMBER"
        }
        Return Invoke-RestMethod -Method Post -Uri ("https://www.googleapis.com/admin/directory/v1/groups/"+$query['groupkey']+"/members") -Headers @{Authorization = "Bearer "+(Get-GoogleToken)} -Body (ConvertTo-Json $body) -ContentType 'application/json; charset=utf-8'
      } else {
        Return ($query['email']+" now is a member of "+$query['groupkey'])
      }
    }
  }
}

Hauv txhua qhov kev thov, koj yuav tsum xa Daim Ntawv Tso Cai header uas muaj hom token thiab Access token nws tus kheej. Tam sim no, hom token yog ib txwm Bearer. Vim peb yuav tsum tau kuaj xyuas tias lub token tsis tas sijhawm thiab hloov kho nws tom qab ib teev txij li lub sijhawm nws tau tshaj tawm, kuv tau teev qhov kev thov rau lwm txoj haujlwm uas xa rov qab rau Access token. Tib daim code yog nyob rau ntawm qhov pib ntawm tsab ntawv thaum tau txais thawj Access token:

function Get-GoogleToken {
  if (((Get-date).Hour -gt $token_expire.hour) -or (((Get-date).Hour -ge $token_expire.hour) -and ((Get-date).Minute -gt $token_expire.minute))) {
  Write-Host "Token Expired. Refreshing..."
    $request = (Invoke-RestMethod -Method Post -Uri "https://www.googleapis.com/oauth2/v4/token" -ContentType 'application/x-www-form-urlencoded' -Body @{
      client_id = $client_id
      client_secret = $client_secret
      refresh_token = $refresh_token
      grant_type = 'refresh_token'
    })
    $token = $request.access_token
    $minute = ([int]("{0:mm}" -f ([timespan]::fromseconds($request.expires_in))))+((Get-date).Minute)-2
    if ($minute -lt 0) {$minute += 60}
    elseif ($minute -gt 59) {$minute -=60}
    $script:token_expire = @{
      hour = ([int]("{0:hh}" -f ([timespan]::fromseconds($request.expires_in))))+((Get-date).Hour)
      minute = $minute
    }
  }
  return $token
}

Tshawb xyuas tus ID nkag mus rau muaj nyob:

function Check_Google {
  $query = (GoogleQuery 'SearchAccount' $username)
  if ($query.users -ne $null) {
    $user = $query.users[0]
    Write-Host $user.name.fullName' - '$user.PrimaryEmail' - suspended: '$user.Suspended
    $GAresult = $user
  }
  if ($GAresult) {
      $return = $GAresult
  } else {$return = 'gg'}
  return $return
}

Tus email: $ query thov yuav nug API kom nrhiav tus neeg siv nrog email raws nraim, suav nrog cov npe. Koj tseem tuaj yeem siv wildcard: =, :, :{PREFIX}*.

Txhawm rau kom tau txais cov ntaub ntawv, siv txoj kev thov GET, txhawm rau ntxig cov ntaub ntawv (tsim ib tus as-qhauj lossis ntxiv cov tswvcuab rau ib pawg) - POST, hloov kho cov ntaub ntawv uas twb muaj lawm - PUT, tshem tawm cov ntaub ntawv (piv txwv li, tus tswvcuab los ntawm ib pawg) - DELETE.

Tsab ntawv tseem yuav nug tus lej xov tooj (ib txoj hlua tsis raug cai) thiab rau kev suav nrog hauv pawg faib hauv cheeb tsam. Nws txiav txim siab seb lub koom haum twg tus neeg siv yuav tsum muaj raws li xaiv Active Directory OU thiab tuaj nrog tus password:

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"

Thiab ces nws pib manipulate tus account:

$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
}

Cov haujlwm rau kev hloov kho thiab tsim ib tus account muaj cov syntax zoo sib xws; tsis yog txhua qhov chaw ntxiv yog yuav tsum tau; nyob rau hauv ntu nrog cov xov tooj, koj yuav tsum tau qhia ib qho array uas tuaj yeem muaj txog li ib cov ntaub ntawv nrog tus lej thiab nws hom.

Txhawm rau kom tsis txhob tau txais qhov yuam kev thaum ntxiv tus neeg siv rau ib pab pawg, peb tuaj yeem tshawb xyuas thawj zaug seb nws puas yog tus tswv cuab ntawm pab pawg no los ntawm kev tau txais ib daim ntawv teev npe ntawm pab pawg neeg lossis cov koom haum los ntawm tus neeg siv nws tus kheej.

Nug pab pawg neeg ntawm ib tus neeg siv tshwj xeeb yuav tsis rov ua dua thiab tsuas yog qhia kev ua tswv cuab ncaj qha xwb. Xws li tus neeg siv hauv pawg niam txiv uas twb muaj ib pab menyuam yaus uas tus neeg siv yog tus tswv cuab yuav ua tiav.

xaus

Txhua yam uas tseem tshuav yog xa tus neeg siv tus password rau tus account tshiab. Peb ua qhov no ntawm SMS, thiab xa cov ntaub ntawv dav dav nrog cov lus qhia thiab nkag mus rau tus kheej email, uas, nrog rau tus lej xov tooj, tau muab los ntawm chav haujlwm nrhiav neeg ua haujlwm. Raws li lwm txoj hauv kev, koj tuaj yeem txuag nyiaj thiab xa koj tus password rau kev sib tham hauv xov tooj tsis pub lwm tus paub, uas tuaj yeem suav tias yog qhov thib ob (MacBooks yuav yog qhov tshwj xeeb).

Ua tsaug rau koj nyeem kom tag. Kuv yuav zoo siab pom cov lus qhia rau kev txhim kho cov qauv ntawm kev sau ntawv thiab xav kom koj ntes tsawg dua qhov yuam kev thaum sau ntawv =)

Cov npe ntawm cov kev sib txuas uas tej zaum yuav muaj txiaj ntsig zoo lossis tsuas yog teb cov lus nug:

Tau qhov twg los: www.hab.com

Ntxiv ib saib