Pular para o conteúdo principal

Otimize Custos e Segurança: Auditoria Fácil de Usuários e Licenças no Azure DevOps

Por que criei este script de auditoria para o Azure DevOps?

Em meu trabalho diário com equipes que utilizam o Azure DevOps, percebi que muitos gestores e administradores enfrentam um desafio comum: controlar quem realmente está usando o ambiente, qual tipo de licença está ativa e, principalmente, quando foi a última vez que cada usuário acessou a plataforma.

Em ambientes com múltiplas organizações e centenas de usuários, controlar quem realmente utiliza repositórios, pipelines e boards pode gerar uma economia significativa.

Tudo isso de forma segura, sem modificar nada no ambiente, garantindo que a auditoria seja apenas informativa.

Essa auditoria é essencial para manter a segurança, controlar custos e garantir conformidade.

Pensando nisso, criei um script de auditoria que:

O que o script verifica?

Para cada usuário com licença Basic, o script checa:

  1. Commits em repositórios Git

  2. Execução de builds no Azure Pipelines

  3. Atividades nos Boards (work items modificados)

Se o usuário não tiver usado nenhum desses recursos nos últimos 30 dias, o script sugere o rebaixamento para a licença gratuita Stakeholder.

Pré-requisitos

  • Permissões adequadas para gerar Personal Access Token (PAT) com escopo de leitura em User Entitlements

  • PowerShell instalado na máquina

  • Módulo ImportExcel instalado (para exportação em Excel)

1. Gerar o Personal Access Token (PAT)

Para que o script funcione, você precisa de um Personal Access Token (PAT) com permissão de leitura para acessar as informações dos usuários da sua organização no Azure DevOps.

Acesse o Azure DevOps e faça login:
No canto superior direito, clique na sua foto de perfil e depois em “Security” (Segurança).
Em “Personal Access Tokens”, clique em “+ New Token” (Novo Token).

Preencha as informações:
Name: Auditoria DevOps
Organization: Selecione a organização desejada
Expiration: Escolha um prazo seguro (ex: 30 ou 90 dias)
Scopes (Escopos):
Marque apenas: Read & execute em "User Entitlements"
(Dentro da opção "Organization")

Clique em “Create”.
⚠️ Copie o PAT imediatamente e armazene em local seguro. Você não poderá visualizá-lo novamente.

Recomendações de segurança:

  • Use tokens com o menor escopo necessário.

  • Nunca compartilhe seu PAT.

  • Se possível, crie um token apenas para auditorias, com expiração curta.

  • Você pode gerar um token para cada organização se não tiver acesso global com o mesmo PAT.

2. Script PowerShell para auditoria

⚠️ Importante: O script não altera nada no ambiente — ele apenas lê e gera um relatório informativo.

===========================================================

# CONFIGURAÇÕES

$organizations = @("contoso", "outraOrg")  # substitua pelos nomes de suas organizações

$pat = "SEU_PAT_AQUI"                      # Token com acesso necessário


$authHeader = @{

    Authorization = ("Basic {0}" -f [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$pat")))

}


# Define a partir de quando considerar atividade (últimos 30 dias)

$cutoff = (Get-Date).AddDays(-30)


function Invoke-AzDo {

    param($Uri)

    try {

        return Invoke-RestMethod -Uri $Uri -Headers $authHeader -ErrorAction Stop

    } catch {

        return $null

    }

}


$report = @()


foreach ($org in $organizations) {

    Write-Host "n Checando organização: $org" -ForegroundColor Cyan


    # Obtem usuários Basic

    $uriUsers = "https://vsaex.dev.azure.com/$org/_apis/userentitlements?top=1000&api-version=7.1-preview.1"

    $resUsers = Invoke-AzDo $uriUsers

    if (-not $resUsers) { Write-Warning "Erro ao obter usuários de $org"; continue }


    $basicUsers = $resUsers.value | Where-Object { $_.accessLevel.licenseDisplayName -eq "Basic" }


    foreach ($u in $basicUsers) {

        $email = $u.user.mailAddress

        $name = $u.user.displayName


        Write-Host "→ Usuário: $name"


        $active = $false


        # 1. Verifica commits

        $uriRepos = "https://dev.azure.com/$org/_apis/projects?api-version=7.1"

        $projects = Invoke-AzDo $uriRepos

        foreach ($p in $projects.value) {

            $uriGit = "https://dev.azure.com/$org/$($p.name)/_apis/git/repositories?api-version=7.1"

            $repos = Invoke-AzDo $uriGit

            foreach ($r in $repos.value) {

                $uriCommits = "https://dev.azure.com/$org/$($p.name)/_apis/git/repositories/$($r.id)/commits?searchCriteria.author=$email&$top=1&api-version=7.1"

                $comm = Invoke-AzDo $uriCommits

                if ($comm.value -and [datetime]$comm.value[0].author.date -ge $cutoff) { $active = $true }

                if ($active) { break }

            }

            if ($active) { break }

        }


        # 2. Verifica builds

        if (-not $active) {

            foreach ($p in $projects.value) {

                $uriBuilds = "https://dev.azure.com/$org/$($p.name)/_apis/build/builds?requestedFor=$email&$top=1&api-version=7.1"

                $b = Invoke-AzDo $uriBuilds

                if ($b.value -and [datetime]$b.value[0].queueTime -ge $cutoff) {

                    $active = $true; break

                }

            }

        }


        # 3. Verifica boards (work items modifications)

        if (-not $active) {

            foreach ($p in $projects.value) {

                $uriWork = "https://dev.azure.com/$org/$($p.name)/_apis/wit/activitylogs?user=$email&$top=1&startDateTime=$($cutoff.ToString("o"))&api-version=7.1"

                $w = Invoke-AzDo $uriWork

                if ($w.value) {

                    $active = $true; break

                }

            }

        }


        # Sugestão de ação

        $action = if ($active) { "Manter Basic" } else { "Rebaixar para Stakeholder" }


        $report += [PSCustomObject]@{

            Organizacao       = $org

            Nome              = $name

            Email             = $email

            Licenca           = "Basic"

            AtivoUltimos30d   = $active

            AcaoSugerida      = $action

        }

    }

}


# Exporta resultado

$out = Join-Path (Get-Location).Path "Auditoria_Basic_Atividade.csv"

$report | Sort-Object Organizacao, Nome | Export-Csv -Path $out -NoTypeInformation -Encoding UTF8


Write-Host "n Relatório gerado: $out" -ForegroundColor Green

===============================================================

Exemplo de Resultado

Abaixo, um exemplo real do relatório gerado pelo script:


Neste cenário, enquanto João segue ativo e justifica sua licença Basic, a usuária Ana não apresentou nenhuma atividade relevante nos últimos 30 dias — o que sugere a possibilidade de rebaixamento para Stakeholder, liberando a licença para outro colaborador ou reduzindo custos.

Por que isso importa?

Em grandes organizações, é comum que licenças fiquem esquecidas — principalmente quando há rotatividade, mudanças de time ou paralisação de projetos.

Licenças Basic são pagas. Já a Stakeholder é 100% gratuita. Ou seja, identificar esses usuários inativos permite economizar de forma inteligente, sem prejudicar a produtividade.

Ao repetir essa auditoria periodicamente, você terá controle total e proativo sobre o uso real das licenças no Azure DevOps.






 

Comentários

Postagens mais visitadas deste blog

Microsoft Authenticator agora suporta Passkeys: Como ativar e testar

 A autenticação de dois fatores (MFA) sempre foi uma das melhores práticas para proteger contas online. Agora, a Microsoft deu um passo além ao adicionar suporte nativo para Passkeys no Microsoft Authenticator . Essa atualização, lançada em janeiro de 2025, permite que os usuários façam login sem precisar de senhas tradicionais, utilizando métodos resistentes a phishing e mais convenientes, como biometria ou PIN. Neste artigo, vamos explorar o que são Passkeys, os benefícios desse novo recurso e como ativá-lo e testá-lo no Microsoft Authenticator . O que são Passkeys? As Passkeys são um método moderno de autenticação baseado no padrão FIDO2/WebAuthn , que permite que os usuários façam login de maneira segura sem precisar inserir senhas. Em vez disso, eles usam biometria (impressão digital ou reconhecimento facial), um PIN ou outro fator local para validar a identidade. Principais benefícios das Passkeys - Resistência a phishing: Como não há senhas para serem roubadas, ataques d...

Mudança no Processo de Exclusão de Usuário no Microsoft 365

 A Microsoft fez uma atualização importante no processo de exclusão de usuários no Microsoft 365 . Agora, ao excluir um usuário, os delegados (pessoas que têm acesso à caixa de correio e aos arquivos) terão apenas 30 dias para acessar o OneDrive do usuário excluído. O que muda? Prazo reduzido : O tempo de acesso aos arquivos foi limitado a 30 dias após a exclusão do usuário, o que significa que os dados ficam acessíveis por um período mais curto. Impacto nos Delegados : Antes, os delegados podiam acessar os dados por mais tempo. Agora, a Microsoft reduziu esse prazo para evitar o armazenamento prolongado de dados de usuários excluídos. Ação Rápida Necessária : Caso seja necessário manter os arquivos por mais tempo, a organização deve tomar providências para transferir ou arquivar esses dados antes que o acesso expire. Por que isso é importante? Essa mudança reflete um esforço da Microsoft para alinhar a gestão de dados com práticas de segurança mais rígidas, incentivando as empre...

Microsoft está removendo as permissões "Todos, exceto usuários externos" no OneDrive

 Já encontrou arquivos no OneDrive acessíveis para toda a sua organização, mesmo sem ter compartilhado intencionalmente? Isso acontece por conta da permissão "Todos, exceto usuários externos" (EEEU) , que permite o acesso interno sem restrições. Mas isso está prestes a mudar. - A partir de 10 de abril de 2025 , a Microsoft removerá a permissão EEEU dos sites raiz do OneDrive e das bibliotecas de documentos padrão, reduzindo o risco de compartilhamento acidental de dados. - Se seus aplicativos, processos ou usuários dependem dessa permissão, eles perderão o acesso assim que a alteração for aplicada. - No entanto, permissões diretas de arquivos e pastas não serão afetadas – quem já tem acesso explícito continuará com permissão. Muitas organizações deixam conteúdos abertos para todos os usuários internos sem perceber. Apesar de parecer inofensivo, isso aumenta riscos de segurança e pode levar à exposição involuntária de dados. O que você deve fazer? ✅ Revisar as permissões ...