PowerShell dla początkujących

jakiś czas temu przygotowałem wraz z Microsoft szkolenie na MVA – Microsoft Virtual Academy. MVA został zlikwidowany i long-story-short – szkolenia przepadły. moje wypłakiwanie się przyniosło sqtek i jeden z czytelników odezwał się, iż ma backup. dziękuję ci Piotrze w imieniu swoim oraz przyszłych oglądających (:

udało mi się również skontaktować z Microsoft i otrzymać pozwolenie na publikację! dziękuję!

tu znajdziesz PowerShell dla początkujących

nie jestem wprawnym youtuberem, ale mam nadzieję, że opublikowałem prawidłowo. na razie pierwsza część, jak wszystko będzie ok – są jeszcze dwie (:

eN.

konsola PS7 nie przyjmuje wpisywania

na wczorajszym WGUiSW miałem przyjemność poopowiadać trochę o różnicach pomiędzy PS 5 a 7. krótki 'Snack’ więc nie chciałem targać całego lapka, przygotowałem wszystko na AVD i połączyłem się przez przeglądarkę.

… i tu zaskoczenie. z jakiegoś niewyjaśnionego powodu konsola PS7 nie akceptuje klawiszy przy takim połączeniu. konsola PS5 działa normalnie. co ciekawe – nawet uruchomienie pwsh wewnątrz konsoli PS5 nie pomoga. szczęśliwie dostałem szybkie wsparcie z sali (to chyba Zbyszek? dzięki!) i pomogła sztuczka, którą wykorzystuje się przy podobnym problemie przy konsoli Hyper-V:

uruchomić pwsh z parameterm 'noninteractive'

parametr ten wyłącza wszelkie funkcje interaktywne typu 'read-host’. co zmienia w takim scenariuszu? – drugi w-files. nie potrafię wyjaśnić mechanizmu, ani który blokuje, ani czemu non-interactive pomogło. ale warto pamiętać.

eN.

jak znaleźć zasób po IP?

w jaki sposób ludzie zgłaszają problemy, chyba nie trzeba nikomu mówić. wydawałoby się, że zgłoszenia typu 'komputer mi niedziała’ powinny być domeną enduserowego ciemnogrodu… ale niestety rzeczywistość pokazuje, że w tej krainie mieszka również rzesza IT. klasycznym przykładem dnia codziennego są zgłoszenia, w których dostaję tylko adres IP. ba! zdarza się, że dev przysyła tylko publiczny URI aplikacji i trzeba szukać… /:

życie. trzeba sobie radzić. a ponieważ mam nowe hobby, nowy język – KQL, postanowiłem coś wydziargać, co pomoże mi szybciej lokalizować zasoby, na podstawie IP.

najpierw przeszukanie sieci:

Search-AzGraph -Query "resources 
    | where type =~ 'microsoft.network/virtualNetworks' and properties.addressSpace.addressPrefixes contains '$netIP'
    | join kind=inner (resourceContainers 
    | where type =~ 'microsoft.resources/subscriptions' 
    | project subscriptionId,subscriptionName=name) on subscriptionId
    | project subscriptionName,resourceGroup,name,addressSpace = properties.addressSpace.addressPrefixes
" | Format-List

i wyszukiwanie NICs – czyli VMek, Private Endpoints i co tam jeszcze ma sieciówkę:

Search-AzGraph -Query "resources
    | where type =~ 'Microsoft.Network/networkInterfaces' and properties.ipConfigurations[0].properties.privateIPAddress contains '$IP'
    | extend sName = tostring(properties.ipConfigurations[0].properties.subnet.id)
    | extend type = iff(isnull(properties.virtualMachine),properties.ipConfigurations[0].name,'virtualMachine')
    | join kind=inner (resourceContainers
        | where type =~ 'microsoft.resources/subscriptions'
        | project subscriptionId,subscriptionName=name) on subscriptionId
    | project subscriptionName, resourceGroup,vNet = extract('virtualNetworks/(.+?)/',1,sName),subnetName = extract('subnets/(.+?)$',1,sName),name,privateIp = properties.ipConfigurations[0].properties.privateIPAddress,type
" | Format-List

jasna sprawa całość trzeba powiązać jakąś logiką i manipulacjami na IP – i tu już magia PS się przydaje (: całość do pobrania na GH i na pewno będzie się rozwijać, bo często potrzebuję…

PS. życie jest złośliwe. SQLa nigdy nie lubiłem, a oczywiście KQL jest jego kuzynem – szczęśliwie dużo bardziej uporządkowanym. jak ogarnę wszystkie typy joinów będę mógł uznać, że jest nieźle. niewątpliwym strzałem w kolano jest case-sensitivity przy podawaniu nazw atrybutów (kolumn)… do tego PowerShell korzysta z PascalCase a ARM z camelCase co powoduje lekką schizmę podczas pisania /:

niemniej dwa elementy KQL/Graph powodują, że po prostu nie da się bez nich zrobić czegoś sensownego: bezkontextowość i czas wykonania.

eN.

graphAPI czy PowerShell?

duża część mojej pracy to PowerShell – ponieważ częściej trzeba coś wykonać hurtem, a nie dla pojedynczego zasobu. różnego rodzaju raporty, wyszukiwanie, automatyzacje etc – wszystko to działa na dużych liczbach. commandlety Az, tak ogólnie mówiąc, są makabryczne – zawieszają się, mają niespójne atrybuty zwracanych obiektów, jest ich kosmicznie dużo i ogólnie – sprawiają problemy…

…ale największym problemem jest ich kontekstowość i wydajność. aby wykonać jakąś operację, najpierw trzeba ustawić kontekst, który wymusza ograniczenie danej operacji do konkretnej subskrypcji. a często zapytanie musi ograniczać wręcz do konkretnej Resource Group.

Microsoft Graph wymaga natomiast wiedzy developerskiej i korzysta z REST API do wykonywania zapytań, a więc mało przyjazne dla skryptera… tylko czy aby na pewno?

niekoniecznie! jest moduł Az.ResourceGraph, który nie wiem czemu, ale nie jest instalowany wraz z resztą modułów Az.*. trzeba go po prostu zainstalować jako 'standalone’, dodatkowo. dzięki niemu można nadal pisać w PowerShell’u równocześnie korzystając z dobrodziejstw, jakie daje Graph… czyli co konkretnie?

można się rozwodzić o tym jak wspaniałym wynalazkiem jest Graph, jak cudownie odzwierciedla rzeczywistość i jak miażdży relacyjne bazy danych [których nigdy nie lubiłem… no może nie samych baz, ale SQL jest pasqdny i prymitywny ]… o czym oczywiście warto poczytać – ale można po prostu 'dotknąć’ i przekonać się samemu.

no więc dotknijmy. taki scenariusz:

jak poustawiane mają opcje update’ów VMki?

teoria do tego zadania jest tutaj, i w klasycznym PowerShell algorytm jest prosty:

  • wylistuj wszystkie subskrypcje
  • dla każdej z nich wylistuj parametry patchowania dla wszystkich VMek.

dodam do tego pomiar czasu, który będzie odpowiedzią na pytanie czy warto korzystać z Microsoft Graph:

Measure-Command { Get-AzSubscription|%{
>> $sub=$_.name;
>> $c = set-azcontext -SubscriptionObject $_;
>> get-azvm | select @{L='sub';E={$sub}}, resourcegroupname,name, `
>> @{L='ostype';E={$_.StorageProfile.OsDisk.OsType}}, `
>> @{L='patchmode';E={
>> if($_.StorageProfile.OsDisk.OsType -eq 'linux') {
>> $_.OSProfile.LinuxConfiguration.PatchSettings.PatchMode
>> } else {
>> $_.OSProfile.WindowsConfiguration.PatchSettings.PatchMode
>> }
>> }
>> }
>> } | export-csv c:\temp\patching.csv -nti -Encoding utf8
>> }

wynik:

TotalMinutes : 23.4296124083333
TotalSeconds : 1405.7767445

teraz zróbmy taki sam test, ale korzystając z zapytania MSGraph:

measure-command {(Search-AzGraph -Query "resources | where type =~ 'microsoft.compute/virtualmachines' | extend os = properties.storageProfile.osDisk.osType | extend patchMode = iff(properties.storageProfile.osDisk.osType=~'windows',properties.osProfile.windowsConfiguration.patchSettings.patchMode,properties.osProfile.linuxConfiguration.patchSettings.patchMode) | join kind=inner (resourceContainers | where type =~ 'microsoft.resources/subscriptions' | project subscriptionId,subscriptionName=name) on subscriptionId | project name,subscriptionName,resourceGroup,os,patchMode").getenumerator()|export-csv -Encoding utf8 -nti C:\temp\patchingGAPI.csv}

wynik:

TotalMinutes : 0.0394362883333333
TotalSeconds : 2.3661773

23 min vs 2.3 sec… komentarz wydaje się być zbędny….

interesuje was ten temat? napisać coś o wadach i zrobić jakiś wstęp do wykorzystania w skryptach?

PS. commandlety Az są w trakcie przypisywania na Microsoft Graph ze starszej wersji… to też dodatkowa niestabilność i sporadyczne różnice w wynikach. ot taka błahostka: czy jakieś polecenie get, kiedy nie znajdzie danego zasobu, zwróci błąd czy $null? … i logika skryptów idzie w …las.

eN.

AD Connect – staging with PowerShell

z jakiegoś powodu wszystkie arty pokazują jak włączyć/wyłączyć staging mode z interfejsu. nie udało mi się znaleźć… więc wypełniam lukę…

najpierw trochę teorii

  • flaga 'staging’ jest ustawieniem globalnym
  • ustawienia można odczytać przy pomocy Get-ADSyncGlobalSettings. przy czym obiekt, który jest zwracany ma poziom ogólny a same ustawienia są jako tablica parametrów. aby zobaczyć te ustawienia, pełne polecenie może wyglądać np. tak:
(Get-ADSyncGlobalSettings).Parameters | select name, scope, value
  • nie ma polecenia, które per se ustawia wartość konkretnego ustawienia
  • a więc algorytm jest prosty:
    • pobierz tablicę ustawień
    • dokonaj w niej zmianę
    • pchnij tablice jako 'zestaw nowych ustawień’

i dla 'stage’ to będzie:

$gs = Get-ADSyncGlobalSettings
$gs.parameters['Microsoft.Synchronize.StagingMode'].value = $true
Set-ADSyncGlobalSettings -GlobalSettings $gs

eN.

Locked Shields 2o22

LockedShieldsLogomake peace not war

jestem pacyfistą totalnym. mimo to kiedy dostałem zaproszenie do wzięcia udziału w Locked Shield 2o22 – nie wahałem się. LS to inicjatywa NATO CCDCoE.. jak widać wojsko wyprzedza IT w skrótowcach (; CCDOCoE to „Cooperative Cyber Defence Centre of Excellence”. w całej inicjatywie chodzi o połączenie sił wojskowych z cywilnymi i wspólną walkę w ramach symulowanego [zmasowanego] ataq hackerskiego na środowisko. oficjalne informacje można znaleźć na stronach ccdcoe.

w tym roq w ćwiczeniu brały udział 32 kraje, w tym 24 BlueTeam – czyli te 'broniące się’. Połączonym zespołem ćwiczebnym dowodził oficer NCBC DKWOC – jak mówiłem, że wojsko w skrótowcach bije IT na głowę. to skrót od „Narodowe Centrum Bezpieczeństwa Cyberprzestrzeni – Dowództwo Komponentu Wojsk Obrony Cyberprzestrzeni”, oficjalna informacja NCBC o LS22 tutaj. Polska w tym roq występowała ramię w ramię z Litwą, a ja miałem przyjemność wspierać Polsko-Litewską Unię Blue Team w zakresie [głównie] ochrony AD.

o co chodzi w ćwiczeniu?

ćwiczenie to duże środowisko, składające się w wielu usług, emulujące duży biznes, wykorzystujący przeróżne systemy operacyjne, aplikacje chmurowe i onpremisowe. środowisko jest skompromitowane, jest w nim wiele luk, dziur, furtek a wręcz otwartych na oścież bram. zadaniem Blue Team jest zabezpieczanie całego środowiska na bieżąco, szybka reakcja na błędy, utrzymywanie usług w stanie działania. w tym czasie Red Team [w tym roq Estonia] wykorzystuje wszelkiego rodzaju luki aby dostawać się do środowiska i psuć co się da. całość zaprojektowana jest tak, aby możliwie bardzo przypominać realną pracę, czyli z systemów normalnie korzystają użytkownicy, zgłaszają tickety etc. punkty dostaje się oczywiście za utrzymywanie usług tak aby działały.

w przeciwieństwie do 'normalnego’ środowiska, nie jest to administracja 'pasywna’ typu: 'a założę sobie GPO i będzie dobrze’. propagacja GPO trwa, a tutaj wszystko musiało być natychmiast i cały czas trzeba sprawdzać czy ktoś już nie wjechał i nie poprzestawiał opcji. dla mnie więc ćwiczenie było rodzajem hackathonu PowerShell, podczas którego sklejałem skrypty monitorujące cały szereg ustawień na kontrolerach domeny i reagujące na zmiany, natychmiast przywracając odpowiednie wartości – czy to ACL na przeróżnych obiektach, weryfiqjące wartości rejestru, czy to dbających o konta i grupy. na czekanie – czasu nie ma.

po co mi ta wojna?

pomimo, że jestem pacyfistą, zdaję sobie sprawę z wagi wojska – zwłaszcza w takim okresie jak obecny. mam nadzieję nigdy nie brać udziału w prawdziwej wojnie, jednak lepiej być przygotowanym. skoro umiem coś z tego IT, to dobrze umieć używać swoją wiedzę również w przypadkach zagrożenia. cały event dał mi naprawdę dużo:

  • ćwiczenie trwa dwa dni podczas których cały czas trzeba być aktywnym i w pełnym sqpieniu. dobre na sprawdzenie swoich możliwości 'pracy pod ciężką presją’ – głównie czasu.
  • choć AD znam bardzo dobrze, włączając aspekty bezpieczeństwa – wykonywałem wiele audytów – to jednak bardzo dużo się dowiedziałem nowych rzeczy. teraz jestem w stanie sięgnąć dużo głębiej i otworzyły mi się oczy jak złożone można wymyśleć wektory ataq i jak zagmatwanie poukrywane. niewątpliwie moje audyty będą dużo pełniejsze.
  • dodałbym pewnie social i czynnik ludzki, ale ten został mocno stępiony przez covida, grypy i inne wynalazki i LS w tym roq był w pełni zdalnie. niestety więc nie miałem okazji fizycznie poznać całej brygady – ale i tak dobrze było popracować w takiej atmosferze – zaangażowanie współuczestników jest olbrzymie, więc jest to duża radocha 'wspólnego celu’.

jak nam poszło?

średnia zdobytych punktów to 43,5k przez wszystkie 24 zespoły. nasz Polsko-Litewski batalion natrzaskał 61,3k punktów plasując się na drugim miejscu. z niewielką przewagą, chyba poniżej 1k, wygrała Finlandia. było blisko! o włos. domenę udało się zabezpieczyć a skrypty robiły taką robotę, że nikomu się na DCki nie udało wjechać (= na 3cim miejscu uplasował się organizator tegorocznego eventu czyli Estonia.

dzięki wszystkim współuczestnikom! liczę na możliwość udziału za rok – i oby dało się fizycznie spotkać. z relacji weteranów, atmosfera w war roomie, kiedy cała ekipa siedzi razem i może się komunikować bezpośrednio, jest dodatkową korbą. ale i tak było całkiem emocjonująco.

eN.

 

ukryta diagnostyka Azure

storyline

od około roq mamy regularny desynch w ramach ARM. efekt jest taki, że zasoby tworzony z portalu nie są widoczne przy dostępie z PowerShell – i odwrotnie. czasem nie widzą się wzajemnie – np. zakłada się Encryption Disk Set, po czym przy próbie zaszyfrowania nie ma go… czyli jest ale nie ma.  znikają Storage Account’y, KeyVault’y, sieci… zasoby są widoczne jednym kanałem, ale niedostępne innym. kończy się różnie – czasem po kilq godzinach jest ok, a czasem trzeba eskalować do wsparcia. co ciekawe – po wielu eskalacjach i obietnicach, że coś tam zostało zrobione i teraz będzie dobrze – nadal się powtarza, a wsparcie twierdzi, że taki problem nie występuje u innych klientów O_o’ to trochę dziwne – biorąc pod uwagę, że nie mówię o małym środowisq, sprawa dotyczy setek subskrypcji rozsianych po całym świecie, więc jak to możliwe, żeby problem dotykał tylko nasze środowiska??

ukryta diagnostyka

jest pewien rodzaj diagnostyki, na który trafiłem podczas zakładania jednego z ticketów i czasem sprawdzam nią status, jest tam też mechanizm, który próbuje dokonać synchronizacji… z różnym efektem – zazwyczaj nic to nie daje, ale kilka razy pomogło. ścieżka jest nieco skomplikowana – więc jeśli ktoś wie, czy można dotrzeć do tej diagnostyki łatwiejszym sposobem, to będę wdzięczny za info:

  • z portalu Azure -> Help and Support -> create new request
  • następnie:
    • Summary: cokolwiek
    • Issue Type: Technical
    • Subscription: wskazać tą, gdzie widzimy problem
    • Service: bez różnicy
    • Service Type: Virtual Network
    • Resource: wybrać RG gdzie jest problem
    • Problem type: Management
    • Problem Subtype: Cannot update resources due to failed state

po wybraniu tych opcji (i chyba tylko tych) odpalają się dwie diagnostyki – jedna dotycząca zasobów a druga konkretnie sieci. przykładowy efekt, który oglądam dość regularnie:

już nawet przestałem się denerwować… kilqdniowe opóźnienia w deploymencie stają się regułą. znajomy porzucił mi ostatnio taki zakurzony filmik

eN.

 

nazwy licencji i planów w o365

scenariusz

przy pracy z licencjami pojawia się wiele problemów. niektóre z nich to:

  • odwzorowanie nazw SKU na nazwy potoczne – np. SKU 'Deskless’ to w interfejsie 'MICROSOFT STAFFHUB’. dość często są one trudne do rozszyfrowania lub wręcz mylące.
  • jakie plany zawiera dana licencja? przykładowo – klient posiada licencję 'o365 E1′ – czy zawiera ona service plan AAD P1?

jest oczywiście wiele podobnych scenariuszy podczas audytów czy planowania konkretnych funkcjonalności czy np. migracji zarządzania licencjami do GBL. odpowiedzi na te pytania dostarcza [a w każdym razie powinna] strona ze spisem: https://docs.microsoft.com/en-us/azure/active-directory/enterprise-users/licensing-service-plan-reference . co więcej – jest na niej link do CSV z zamieszczoną tabelą… do czego już tylko krok do napisania sobie prostego skryptu pomagającego w zadanych scenariuszach.

UWAGA jak się przekonałem tej stronie nie można w pełni ufać – jest na niej dużo błędów i niespójności, najradykalniejszy przypadek jaki znalazłem to licencja M365 Business Premium, które wedle tabeli zawiera 24 plany, a w rzeczywistości, listując SKU – jest ich ponad 4o. błąd zgłoszony i mam nadzieję, że poprawią.

dla tych, którzy szukają rozwiązania

napisałem krótki skrypt, który zasysa tabelę w postaci CSV i pozwala na odpytania się kilka podstawowych rzeczy:

  • rozwiązywanie nazw technicznych SKU na 'displayName’ [i odwrotnie] dla licencji i planów
  • listowanie planów w licencji
  • listowanie licencji zawierającej dany plan

przykłady

C:\ :))o- .\get-ServicePlanInfo.ps1 -resolveName deskless
Microsoft StaffHub

C:\ :))o- .\get-ServicePlanInfo.ps1 -resolveName 'MICROSOFT 365 BUSINESS standard'
O365_BUSINESS_PREMIUM

dla tych, którzy szukają nauki

na co warto zwrócić uwagę w kodzie, to wykorzystanie ParameterSetName. są 4 różne operacje/bloki, wykonywane zależnie od wybrania jednego z 4 ParameterSetName:

[CmdletBinding(DefaultParameterSetName='default')]
param (
    #resolve Service Plan or License name
    [Parameter(ParameterSetName='resolveNames',mandatory=$true,position=0)]
        [string]$resolveName,
    #display all licenses containing given SP
    [Parameter(ParameterSetName='listLicenses',mandatory=$true,position=0)]
        [string]$showProducts,
    #show SPs for given license type
    [Parameter(ParameterSetName='listServicePlans',mandatory=$true,position=0)]
        [string]$productName    
)
zazwyczaj logikę kodu opiera się dalej na switchu, zależnie od wykorzystanego PSN:
switch($PSCmdlet.ParameterSetName) {....}
ale postanowiłem to uprościć… w zamian, napisałem 4 funkcje, które mają nazwy identyczne z PSN:
function resolveNames {...}
function listLicenses {...}
function listServicePlans {...}
function default {...}
dzięki temu, zamiast switcha, wystarczy że uruchomię funkcję o nazwie PSN:
$run = "$($PSCmdlet.ParameterSetName) -name '$([string]$PSBoundParameters.Values)'"
Invoke-Expression $run
ładne, nie? (=
eN.

lista subskrypcji z właścicielami

scenariusz

Enterprise Agreement i dużo subskrypcji. potrzebna lista wszystkich subskrypcji wraz z ich właścicielami. moje konto nie ma uprawnień do wszystkich subskrypcji więc korzystam z przygotowanego AppID dla konta monitorującego. powinno niby być proste…

  • po pierwsze trzeba zdefiniować, co się rozumie przez właściciela. mogą to być osoby, które mają nadane uprawnienie 'owner’ w IAM, ale w przypadq subskrypcji bardziej logicznym wydaje się znalezienie ’Account Administrator’ subskrypcji – czyli konta, które ją zakładało.
  • po drugie, trzeba mieć konto, które będzie miało odpowiednie uprawnienia i mam takie konto – w opisywanym scenariuszu chodzi o tożsamość aplikacyjną… i tu się zaczynają schody – ale to opiszę w części praktycznej.
  • po trzecie – jak mamy już prereq to trzeba wymyślić jak to przygotować

schody

Microsoft przepisuje narzędzia na Microsoft Graph, ze starego GraphAPI. a że wszystko u mnie PowerShellem stoi, ostatnimi czasy obserwuję wiele czerwonych wykwitów, a co gorsza – skrypty zaczęły się wieszać. sqpiając się jednak na zadaniu…

najpierw chciałem wylistować wszystkich, którzy mają uprawnienie 'owner’ w IAM. okazuje się, że był bug w commadlecie get-AzRoleAssignment: jeśli używa się tożsamości Aplikacji, zwracany jest błąd:

Exception of type 'Microsoft.Rest.Azure.CloudException' was thrown

błąd został poprawiony w ostatniej wersji, update commadletów, działa!… ale czy aby na pewno? co prawda błąd już nie wyskakuje i wszystkie subskrypcje się listują… ale nie ma SignInName ani DisplayName!

$s=Get-AzSubscription -SubscriptionName 'w-files'
Get-AzRoleAssignment -Scope "/subscriptions/$($s.id)"|? RoleDefinitionName -eq owner

RoleAssignmentName : e740d3e4-7809-4104-876c-8ce2a27edbf9
RoleAssignmentId : /subscriptions/01234567-3223-3223-2332-012345678901/providers/Microsoft.Authorization/roleAssignme
nts/e740d3e4-7809-4104-876c-8ce2a27edbf9
Scope : /subscriptions/01234567-3223-3223-2332-012345678901
DisplayName :
SignInName :
RoleDefinitionName : Owner
RoleDefinitionId : 8e3af657-a8ff-443c-a75c-2fe8c4bcb635
ObjectId : 76543210-3223-3223-2332-109876543210
ObjectType : Unknown
CanDelegate : False
Description :
ConditionVersion :
Condition :

obejściem problemu może być wykorzystanie az cli… ma pasqdną składnię, ale ma swoje zalety.

az role assignment list --subscription 01234567-3223-3223-2332-012345678901 --role owner

niedługo należy się spodziewać problemów:

The underlying Active Directory Graph API will be replaced by Microsoft Graph API in a future version of Azure CLI. Please carefully review all breaking changes introduced during this migration: https://docs.microsoft.com/cli/azure/microsoft-graph-migration

a teraz 'bardziej prawidłowy’ scenariusz, czyli listing 'account manager’. tu dla odmiany sytuacja jest odwrotna, ponieważ az cli nagle rzyga błędem:

az role assignment list --subscription 01234567-3223-3223-2332-012345678901 --include-classic-administrators

Insufficient privileges to complete the operation.

natomiast z PowerShell hula:

Get-AzRoleAssignment -Scope "/subscriptions/$($s.id)" -IncludeClassicAdministrators|? RoleDefinitionName -match 'AccountAdministrator'


RoleAssignmentName :
RoleAssignmentId :
Scope : /subscriptions/01234567-3223-3223-2332-012345678901
DisplayName : nexor@w-files.pl
SignInName : nexor@w-files.pl
RoleDefinitionName : ServiceAdministrator;AccountAdministrator
RoleDefinitionId :
ObjectId :
ObjectType : Microsoft.Authorization/classicAdministrators
CanDelegate : False
Description :
ConditionVersion :
Condition :

jedyny sensowny komentarz, jaki mi przychodzi do głowy, to starobabcine 'masz ci babo placek’. w każdym razie teraz to już bułka z masłem:

Get-AzSubscription|%{$sub=$_;Get-AzRoleAssignment -Scope "/subscriptions/$($sub.id)" -IncludeClassicAdministrators|? RoleDefinitionName -match 'AccountAdministrator'|select @{L='subscirption name';E={$sub.name}},@{L='subscription ID';E={$sub.id}},@{L='subscirption state';E={$sub.state}},@{L='owner signin name';E={$_.SignInName}},@{L='owner display name';E={$_.DisplayName}} } | export-csv -nti subscriptionList.csv

eN.

 

RSS
Follow by Email
LinkedIn
Share
Reddit