diff --git a/PowerShell/Snippets/Clone-Repos.ps1 b/PowerShell/Snippets/Clone-Repos.ps1 index 1b637fb..b7f4f86 100644 --- a/PowerShell/Snippets/Clone-Repos.ps1 +++ b/PowerShell/Snippets/Clone-Repos.ps1 @@ -1,16 +1,24 @@ Param( [string]$destinationFolder = ".", - [string]$org = "x00" + [string]$org = "123", + [array]$projects = ( + "Modules" ) -# Make sure you have the Azure CLI installed and logged in via az login or az devops login + +# Make sure you have the Azure CLI installed (az extension add --name azure-devops) and logged in via az login or az devops login +# If you face /_apis authentication issues make sure to login via az login --allow-no-subscriptions + az devops configure --defaults organization=https://dev.azure.com/$org -$projects = az devops project list --organization=https://dev.azure.com/$org | ConvertFrom-Json -$repos = az repos list | ConvertFrom-Json +# $projects = az devops project list --organization=https://dev.azure.com/$org | ConvertFrom-Json -foreach ($project in $projects.value) { - $repos = az repos list --project $($project.name) | ConvertFrom-Json +foreach ($project in $projects) { + $repos = az repos list --project $project | ConvertFrom-Json foreach ($repo in $repos) { - Write-Output "Repository [$($repo.name)] in project [$($project.name)]" - git clone $($repo.remoteUrl) $destinationFolder/$($project.name)/$($repo.name) + Write-Output "Repository [$($repo.name)] in project [$($project)]" + If(!(test-path -PathType container $destinationFolder)) + { + New-Item -ItemType Directory -Path $destinationFolder + } + git clone $($repo.remoteUrl) $destinationFolder/$($project)/$($repo.name) } } diff --git a/PowerShell/Snippets/Create-SP.ps1 b/PowerShell/Snippets/Create-SP.ps1 new file mode 100644 index 0000000..dba6b72 --- /dev/null +++ b/PowerShell/Snippets/Create-SP.ps1 @@ -0,0 +1,16 @@ +Param( + [string]$spRole = "Contributor", + [string]$spScope = "/subscriptions/$subscriptionId" +) + +# PowerShell +$spName = (Get-Random -SetSeed 1234 -Minimum 100000 -Maximum 999999).ToString() + "-sp" +$sp = New-AzADServicePrincipal -DisplayName $spName +New-AzRoleAssignment -RoleDefinitionName $spRole -ServicePrincipalName $sp.ApplicationId -Scope $spScope + +# Azure CLI +spName=$(shuf -i 100000-999999 -n 1)-sp +sp=$(az ad sp create-for-rbac --name $spName --role $spRole --scopes $spScope) +echo $sp | jq -r .appId +echo $sp | jq -r .password +echo $sp | jq -r .tenant diff --git a/PowerShell/Snippets/Get-AllActions.ps1 b/PowerShell/Snippets/Get-AllActions.ps1 new file mode 100644 index 0000000..6f882c6 --- /dev/null +++ b/PowerShell/Snippets/Get-AllActions.ps1 @@ -0,0 +1,2 @@ +$actions = Get-AzProviderOperation -OperationSearchString '*' +$actions | Where-Object {$_.Operation -like '*read*'} | Select-Object Operation | Export-Csv -Path 'Get-AllActions.csv' -NoTypeInformation -Force diff --git a/PowerShell/Snippets/Get-RBACDetails b/PowerShell/Snippets/Get-RBACDetails new file mode 100644 index 0000000..124eba2 --- /dev/null +++ b/PowerShell/Snippets/Get-RBACDetails @@ -0,0 +1,44 @@ +# Login to Azure +Connect-AzAccount + +<# +Function to fetch RBAC details recursively from Management Group to Resource Groups and export to CSV +0. Create empty array to store RBAC details +1. Fetch Management Group info and RBAC assignments +2. Fetch Subscriptions and RBAC assignments under the Management Group +3. Fetch Resource Groups and RBAC assignments under the Subscription + + +#> + +Function Get-RBACDetails { + [CmdletBinding()] + param ( + [Parameter(Mandatory=$true)] + [string]$ManagementGroup + ) + $RBACDetails = @() + $MGInfo = Get-AzManagementGroup -GroupName $ManagementGroup + $MGRBAC = Get-AzManagementGroupRoleAssignment -GroupId $ManagementGroup + $MGInfo | Add-Member -MemberType NoteProperty -Name "Type" -Value "Management Group" -Force + $MGInfo | Add-Member -MemberType NoteProperty -Name "RoleAssignment" -Value $MGRBAC -Force + $RBACDetails += $MGInfo + $Subscriptions = Get-AzManagementGroupSubscriptions -GroupId $ManagementGroup + foreach ($Subscription in $Subscriptions) { + $SubRBAC = Get-AzRoleAssignment -Scope $Subscription.Id + $Subscription | Add-Member -MemberType NoteProperty -Name "Type" -Value "Subscription" -Force + $Subscription | Add-Member -MemberType NoteProperty -Name "RoleAssignment" -Value $SubRBAC -Force + $RBACDetails += $Subscription + $ResourceGroups = Get-AzResourceGroup -SubscriptionId $Subscription.Id + foreach ($ResourceGroup in $ResourceGroups) { + $RGInfo = Get-AzResourceGroup -Name $ResourceGroup.ResourceGroupName + $RGRBAC = Get-AzRoleAssignment -Scope $ResourceGroup.ResourceId + $RGInfo | Add-Member -MemberType NoteProperty -Name "Type" -Value "Resource Group" -Force + $RGInfo | Add-Member -MemberType NoteProperty -Name "RoleAssignment" -Value $RGRBAC -Force + $RBACDetails += $RGInfo + } + } + $RBACDetails | Export-Csv -Path "RBACDetails.csv" -NoTypeInformation +} + +Get-RBACDetails -ManagementGroup "root" diff --git a/PowerShell/Snippets/RBAC.ps1 b/PowerShell/Snippets/RBAC.ps1 new file mode 100644 index 0000000..a84cd3f --- /dev/null +++ b/PowerShell/Snippets/RBAC.ps1 @@ -0,0 +1,69 @@ +# Login to Azure +Connect-AzAccount + +# Function to fetch RBAC details recursively from Management Group to Resource Groups +function Get-RBACHierarchy { + param ( + [string]$ManagementGroupId + ) + + # Fetch Management Group info and RBAC assignments + $mgInfo = Get-AzManagementGroup -GroupId $ManagementGroupId + $mgRBAC = Get-AzRoleAssignment -Scope "/providers/Microsoft.Management/managementGroups/$ManagementGroupId" + + # Print Management Group and RBAC info + Write-Host "Management Group: $($mgInfo.DisplayName)" + foreach ($role in $mgRBAC) { + Write-Host "`tRole: $($role.RoleDefinitionName) - Assigned to: $($role.SignInName)" + } + + # Fetch Subscriptions under the Management Group + $subscriptions = Get-AzSubscription -ManagementGroup $ManagementGroupId + + foreach ($subscription in $subscriptions) { + # Print Subscription info and fetch its RBAC assignments + Write-Host "`tSubscription: $($subscription.Name)" + $subRBAC = Get-AzRoleAssignment -Scope $subscription.Id + + foreach ($role in $subRBAC) { + Write-Host "`t`tRole: $($role.RoleDefinitionName) - Assigned to: $($role.SignInName)" + } + + # Fetch Resource Groups under the Subscription + $resourceGroups = Get-AzResourceGroup -SubscriptionId $subscription.Id + foreach ($rg in $resourceGroups) { + # Print Resource Group info and fetch its RBAC assignments + Write-Host "`t`tResource Group: $($rg.ResourceGroupName)" + $rgRBAC = Get-AzRoleAssignment -ResourceGroupName $rg.ResourceGroupName + + foreach ($role in $rgRBAC) { + Write-Host "`t`t`tRole: $($role.RoleDefinitionName) - Assigned to: $($role.SignInName)" + } + } + } +} + +# Start fetching from the root management group (replace 'root' with your root management group ID if different) +Get-RBACHierarchy -ManagementGroupId "root" + + +function Get-RBACDetails { + param ( + [Parameter(Mandatory=$true)] + [string]$Scope + ) + $rbacDetails = @() + $roleAssignments = Get-AzRoleAssignment -Scope $Scope + foreach ($roleAssignment in $roleAssignments) { + $rbacDetails += [PSCustomObject]@{ + "Scope" = $roleAssignment.Scope + "RoleDefinitionName" = $roleAssignment.RoleDefinitionName + "PrincipalType" = $roleAssignment.PrincipalType + "PrincipalId" = $roleAssignment.PrincipalId + "ObjectId" = $roleAssignment.ObjectId + "ObjectType" = $roleAssignment.ObjectType + "CanDelegate" = $roleAssignment.CanDelegate + } + } + $rbacDetails +} diff --git a/graphql/gh cli graphql.ps1 b/graphql/gh cli graphql.ps1 new file mode 100644 index 0000000..82e4497 --- /dev/null +++ b/graphql/gh cli graphql.ps1 @@ -0,0 +1,207 @@ +gh alias set prs 'api graphql --paginate -f filter="type:pr state:open review-requested:myusername $1" -f query=" +query($filter: String!){ + search(query: $filter, type: ISSUE, first: 100) { + issueCount + pageInfo { + endCursor + startCursor + } + edges { + node { + ... on PullRequest { + url + } + } + } + } +} +" --jq ".data.search.edges[].node.url"' + +gh search prs --review-requested=Azure/avm-core-team-technical-bicep + +gh alias set issues 'api graphql --paginate -f filter="type:issue state:open $1" -f query=" +query($filter: String!){ + search(query: $filter, type: ISSUE, first: 100) { + issueCount + pageInfo { + endCursor + startCursor + } + edges { + node { + ... on Issue { + url + } + } + } + } +} +" --jq ".data.search.edges[].node.url"' + +# show all issue +gh issues 'repo:Azure/terraform-azurerm-avm-res-keyvault-vault' + +gh alias set openprs 'api graphql --paginate -f filter="type:pr state:open $1" -f query=" +query($filter: String!){ + search(query: $filter, type: ISSUE, first: 100) { + issueCount + pageInfo { + endCursor + startCursor + } + edges { + node { + ... on PullRequest { + url + } + } + } + } +} +" --jq ".data.search.edges[].node.url"' + +# show all open pull requests +gh openprs 'repo:Azure/terraform-azurerm-avm-res-keyvault-vault' + +# Get list of all repositories for a user +repos=$(curl -H "Accept: application/vnd.github.v3+json" "https://api.github.com/users/Azure/repos") + +# Loop over each repository and check if it starts with 'terraform-azurerm-avm' +echo $repos | jq -r '.[] | select(.name | startswith("terraform-azurerm-avm")) | .name' + +$page = 1 +$allRepos = @() + +do { + $repos = Invoke-RestMethod -Uri "https://api.github.com/users/Azure/repos?page=$page&per_page=100" + if ($repos.Count -eq 0) { + break + } + $allRepos += $repos + $page++ +} while ($true) +$tfrepos = $allRepos | Where-Object { $_.name -like "terraform-azurerm-avm*" } | ForEach-Object { $_.name } +$allIssues = @() + +# list issues and PRs +foreach ($repo in $tfrepos) +{ + Write-Host "Fetching issues for $repo" + $issues = gh issue list -R "Azure/$repo" --json number,title,url | ConvertFrom-Json + foreach ($issue in $issues) { + $issue | Add-Member -NotePropertyName "repo" -NotePropertyValue $repo + } + $allIssues += $issues +} +$allIssues | ConvertTo-Json + +# list PRs + +$allPRs = @() +foreach ($repo in $tfrepos) +{ + Write-Host "Fetching PRs for $repo" + $prs = gh pr list -R "Azure/$repo" --json number,title,url | ConvertFrom-Json + foreach ($pr in $prs) { + $pr | Add-Member -NotePropertyName "repo" -NotePropertyValue $repo + } + $allPRs += $prs +} +$allPRs | ConvertTo-Json + +# list PRs sorted by title + +$allPRs | Select-Object title,url | Sort-Object title + +# list PRs starting with 'chore' + +$allPRs | Select-Object title,url | Sort-Object title | Where-Object { $_.title -like "chore*" } + +# approve all PRs + +foreach ($pr in $allPRs) +{ + Write-Host "Approving PR $pr.title" + gh pr review $pr.number -R --approve +} + +$allItems = @() +Write-Host "Fetching issues and PRs for $($tfrepos.Count) repos" +foreach ($repo in $tfrepos) +{ + Write-Host "Fetching issues and PRs for $repo" + + # Fetch issues + $issues = gh issue list -R "Azure/$repo" --json number,title,url | ConvertFrom-Json + foreach ($issue in $issues) { + $issue | Add-Member -NotePropertyName "repo" -NotePropertyValue $repo + $issue | Add-Member -NotePropertyName "type" -NotePropertyValue "issue" + } + $allItems += $issues + + # Fetch PRs + $prs = gh pr list -R "Azure/$repo" --json number,title,url | ConvertFrom-Json + foreach ($pr in $prs) { + $pr | Add-Member -NotePropertyName "repo" -NotePropertyValue $repo + $pr | Add-Member -NotePropertyName "type" -NotePropertyValue "pr" + } + $allItems += $prs +} + +$allItems | ConvertTo-Json + +# list PRs starting with 'chore' + +$allItems | Where-Object { $_.title -like "chore*" -and $_.type -eq "pr" } | Select-Object title,url + +# approve all PRs starting with 'chore' + +foreach ($pr in $allItems | Where-Object { $_.title -like "chore*" -and $_.type -eq "pr" }) +{ + Write-Host "Approving PR $($pr.title) on repo $($pr.repo)" + # gh pr review $pr.number -R "Azure/$($pr.repo)" --approve +} + + +$page = 1 +$allIssues = @() + +do { + $repos = Invoke-RestMethod -Uri "https://api.github.com/users/Azure/repos?page=$page&per_page=100" + if ($repos.Count -eq 0) { break } + $page++ + $tfrepos = $repos | Where-Object { $_.name -like "terraform-azurerm-avm*" } | ForEach-Object { $_.name } + foreach ($repo in $tfrepos) { + $allIssues += gh issue list -R "Azure/$repo" --json title,url,number | ConvertFrom-Json + } +} while ($repos.Count -gt 0) + +$allIssues | ConvertTo-Json + +# APi + +$apiEndpoint = "https://api.github.com/repos/Azure/Azure-Verified-Modules/projects" + +# Send a GET request to the API endpoint +$projects = Invoke-RestMethod -Method Get -Uri $apiEndpoint -Headers @{ + "Authorization" = "Bearer token" + "Accept" = "application/vnd.github.inertia-preview+json" +} + +# Print the ID of each project +foreach ($project in $projects) { + Write-Output "Project: $($project.name), ID: $($project.id)" +} + +# cancel all workflows + +# Get the running workflow runs +$runs = gh run list --repo segraef/bicep-registry-modules --json databaseId,status | ConvertFrom-Json + +# Loop over the runs and cancel each one that's in progress +foreach ($run in $runs) { + if ($run.status -eq 'in_progress') { + gh run cancel $run.databaseId --repo segraef/bicep-registry-modules + } +} +