Um laboratório prático que reconstrói, do zero e em Python, o fluxo completo de governança de identidade do SailPoint Identity Security Cloud (ISC) — da fonte autoritativa (RH) até o provisionamento no Active Directory — sem depender de um tenant corporativo.
O SailPoint ISC é uma plataforma de IAM (Identity & Access Management) que orquestra o ciclo de vida das identidades de uma empresa: ela lê quem são as pessoas em uma fonte autoritativa (ex.: RH/Protheus), monta a Identity de cada uma e, quando um acesso é aprovado, provisiona esse acesso nos sistemas-alvo (ex.: Active Directory).
Este repositório recria esse fluxo inteiro localmente, peça por peça, para estudo e demonstração de habilidades de integração. Cada componente do SailPoint tem aqui um equivalente construído à mão em Python/PowerShell — o que permite entender o que acontece por baixo dos panos de uma plataforma de IAM.
Construído passo a passo como treinamento prático de IAM + APIs REST + Webhooks + automação com PowerShell.
flowchart TD
RH["RH / Authoritative Source<br/><code>passo1_authoritative_source_api.py</code>"]
AGG["Aggregation — motor do ISC<br/><code>passo2_aggregation.py</code>"]
ISC["Event Trigger do ISC<br/><code>passo3_event_sender.py</code>"]
WH["Webhook Listener<br/><code>passo3_webhook_listener.py</code>"]
REQ["Access Request + Approval<br/><code>passo5_access_request_api.py</code>"]
SOD{"Política de SoD?<br/><code>passo6_sod_policy.py</code>"}
PONTE["Ponte / IQService<br/><code>passo4_iqservice_bridge.py</code>"]
PS["Script no Target System<br/><code>passo4_provision_ad.ps1</code>"]
AD[("Active Directory<br/>ad_provisionamento.log")]
BLOCK["Bloqueada / Rejeitada<br/>(nada provisionado)"]
RH -->|"GET (lê a verdade)"| AGG
ISC -->|"POST · Event Trigger"| WH
WH --> PONTE
REQ -->|"gestor aprova"| SOD
SOD -->|"sem conflito"| PONTE
SOD -->|"conflito"| BLOCK
PONTE -->|"subprocess"| PS
PS -->|"provisiona / desativa"| AD
O laboratório cobre as duas metades do IGA: Administration (ler a fonte e provisionar —
caminhos RH → Aggregation e Webhook → Ponte) e Governance (o acesso só é provisionado
após aprovação e desde que não viole a política de SoD — caminho Access Request → SoD).
- Construção de APIs REST com FastAPI (rotas
GETePOST, validação com Pydantic, status HTTP, documentação automática via Swagger). - Consumo de APIs com
requests, incluindo tratamento de erros de conexão e timeouts. - Arquitetura orientada a eventos (webhooks): inverter a lógica de "perguntar" para "ser notificado".
- Integração entre linguagens: ponte Python → PowerShell via
subprocess, capturando saída e contornandoExecutionPolicy. - Modelagem de dados com objetos aninhados (uma Identity dentro de um evento).
- Workflow de governança (IGA): solicitação de acesso → aprovação → provisionamento, com trilha de auditoria (quem pediu, quem aprovou, quando e por quê).
- Enforcement de políticas: Segregation of Duties (SoD) bloqueando combinações de acessos conflitantes, mesmo sobre a decisão do aprovador.
- Autenticação de API como em produção: fluxo OAuth2 (client_credentials) com Bearer token, no mesmo formato do tenant real do ISC.
- Boas práticas: ambiente virtual isolado,
requirements.txtcomo contrato de versões, segredos e artefatos fora do versionamento. - Tradução de conceitos de IAM/IGA (Authoritative Source, Aggregation, Event Trigger, IQService, Target System, Access Request, Approval, SoD) para código funcional.
| Conceito SailPoint (ISC) | O que é na vida real | Como simulamos aqui |
|---|---|---|
| Authoritative Source | Fonte da verdade das pessoas (RH/Protheus) | API FastAPI que devolve dados de funcionários (PASSO 1) |
| Identity | A identidade única de uma pessoa dentro do ISC | O objeto JSON que o ISC monta a partir do RH |
| Aggregation | ISC "puxa" os dados da fonte para criar/atualizar Identities | Script Python que faz GET na API do RH (PASSO 2) |
| Event Trigger | Evento do ISC que dispara uma ação externa (HTTP POST) | JSON que o "ISC" envia ao nosso Webhook (PASSO 3) |
| Webhook Listener | Endpoint que recebe o Event Trigger | Rota POST na nossa API FastAPI (PASSO 3) |
| IQService | Conector que executa ações no Windows/AD | Ponte Python → script PowerShell (PASSO 4) |
| Target System | Sistema onde o acesso é provisionado (ex.: AD) | Active Directory simulado via PowerShell (PASSO 4) |
| Access Profile / Entitlement | Pacote de acessos concedidos a uma Identity | O grupo/papel que o PowerShell aplica no AD |
| Access Request / Approval | Pedido de acesso aprovado por um gestor antes de conceder | API de solicitações com aprovação e auditoria (PASSO 5) |
| Segregation of Duties (SoD) | Política que impede combinações de acessos com risco/fraude | Motor que bloqueia pares conflitantes na aprovação (PASSO 6) |
| API Authentication | OAuth2 (client_credentials) + Bearer token para chamar o ISC | Mock do ISC com /oauth/token e endpoints /v3 (PASSO 7) |
- Python 3.13 — linguagem principal
- FastAPI 0.115 — framework das APIs REST (RH e Webhook)
- Uvicorn 0.34 — servidor ASGI que coloca as APIs no ar
- Requests 2.32 — cliente HTTP (simula o motor do ISC consumindo/disparando)
- python-multipart — suporte a formulários (fluxo OAuth2 do PASSO 7)
- PowerShell — executa a ação no Target System (Active Directory)
SailPoint_ISC_Lab/
├── passo1_authoritative_source_api.py # Authoritative Source: API REST que devolve as Identities (GET)
├── passo2_aggregation.py # Aggregation: motor do ISC consumindo a RH API
├── passo3_webhook_listener.py # Webhook Listener: recebe o Event Trigger (POST) e aciona a ponte
├── passo3_event_sender.py # Simula o ISC disparando o Event Trigger
├── passo4_iqservice_bridge.py # IQService: ponte Python -> PowerShell (subprocess)
├── passo4_provision_ad.ps1 # Target System (AD) simulado: registra a ação
├── passo5_access_request_api.py # IGA: solicitação de acesso + aprovação + auditoria
├── passo5_access_request_demo.py # Simula o fluxo pedido -> aprovação/rejeição -> auditoria
├── passo6_sod_policy.py # IGA: política de Segregation of Duties (SoD)
├── passo6_sod_demo.py # Simula a SoD bloqueando uma combinação tóxica
├── passo7_isc_mock_api.py # Mock do ISC real: OAuth2 + endpoints /v3 protegidos
├── passo7_isc_client.py # Cliente que autentica (Bearer) e consome, como em produção
├── docs/
│ └── POC_offboarding.md # Roteiro de POC para propor automação na empresa
├── requirements.txt # Contrato de versões das dependências
├── .gitignore # Ignora .venv, __pycache__, *.log, segredos
├── LICENSE # Licença MIT
└── README.md
# Criar o ambiente virtual isolado
py -m venv .venv
# Liberar scripts SÓ para esta sessão do PowerShell (não altera a máquina)
Set-ExecutionPolicy -Scope Process -ExecutionPolicy RemoteSigned
# Ativar o ambiente -> o prompt passa a exibir "(.venv)"
.\.venv\Scripts\Activate.ps1
# Instalar as dependências
pip install -r requirements.txtDica:
Set-ExecutionPolicy -Scope Processvale apenas para a janela atual — todo terminal novo precisa rodá-lo de novo antes doActivate.ps1. Para um comando pontual sem ativar nada, chame o Python interno:.\.venv\Scripts\python.exe <arquivo>.py.
# Terminal 1 — Webhook Listener (já aciona a ponte para o PowerShell)
uvicorn passo3_webhook_listener:app --reload --port 8001
# Terminal 2 — simula o ISC aprovando um acesso e disparando o evento
python passo3_event_sender.pyResultado: o Terminal 1 mostra o evento recebido e a resposta do PowerShell; o arquivo
ad_provisionamento.log registra o provisionamento — a "prova física" da ação no AD.
PASSOS 1–4 = Administration (ler a fonte e provisionar). PASSOS 5–6 = Governance (aprovação e política de SoD). PASSO 7 = integração como em produção (OAuth2).
Índice de ordem de aprendizado — o prefixo passoN_ no nome de cada arquivo já indica a
sequência; a tabela abaixo agrupa os arquivos de cada passo e resume o papel de cada um:
| Ordem | Arquivo(s) principal(is) | Papel |
|---|---|---|
| 1 | passo1_authoritative_source_api.py |
Fonte da verdade (RH) — API REST |
| 2 | passo2_aggregation.py |
Motor do ISC consumindo a fonte |
| 3 | passo3_webhook_listener.py · passo3_event_sender.py |
Event Trigger / Webhook |
| 4 | passo4_iqservice_bridge.py · passo4_provision_ad.ps1 |
Ponte Python → PowerShell (AD) |
| 5 | passo5_access_request_api.py · passo5_access_request_demo.py |
IGA: solicitação + aprovação + auditoria |
| 6 | passo6_sod_policy.py · passo6_sod_demo.py |
IGA: Segregation of Duties |
| 7 | passo7_isc_mock_api.py · passo7_isc_client.py |
OAuth2/Bearer como em produção |
PASSO 1 — Authoritative Source (RH API)
Objetivo: subir a API REST que é a fonte da verdade das pessoas (o "Protheus") e devolver as Identities em JSON via GET.
uvicorn passo1_authoritative_source_api:app --reload| URL | O que valida | Esperado |
|---|---|---|
| http://127.0.0.1:8000/funcionarios | Aggregation completa (lista todos) | JSON com os 3 funcionários |
| http://127.0.0.1:8000/funcionarios/1001 | Buscar uma Identity | JSON só da Ana Souza |
| http://127.0.0.1:8000/funcionarios/9999 | Tratamento de erro | Erro 404 com mensagem amigável |
| http://127.0.0.1:8000/docs | Documentação automática | Swagger interativo |
PASSO 2 — Aggregation (motor do ISC)
Objetivo: fazer um GET na RH API e decidir, pelo campo status, criar/atualizar ou
desativar cada Identity. Demonstra os dois lados de uma integração rodando ao mesmo tempo.
# Terminal 1
uvicorn passo1_authoritative_source_api:app --reload
# Terminal 2
python passo2_aggregation.pyEsperado: Ana e Bruno como CRIAR/ATUALIZAR Identity (ativos) e Carla como
DESATIVAR Identity (inativa).
Teste de robustez: pare a API e rode o PASSO 2 — deve aparecer a mensagem amigável de falha de conexão em vez de um stack trace.
PASSO 3 — Event Trigger / Webhook Listener
Objetivo: receber um POST (o Event Trigger do ISC) em vez de responder GET. Inverte a lógica: a API fica esperando ser chamada e age quando o evento chega.
# Terminal 1
uvicorn passo3_webhook_listener:app --reload --port 8001
# Terminal 2
python passo3_event_sender.pyEsperado: Terminal 2 recebe Status HTTP 200 + ACK; Terminal 1 mostra o bloco
EVENTO RECEBIDO DO ISC. Alternativa: testar pelo Swagger em http://127.0.0.1:8001/docs.
PASSO 4 — Ponte Python → PowerShell (IQService)
Objetivo: transformar a ordem recebida no webhook em ação real. A ponte executa o
passo4_provision_ad.ps1, que simula o AD registrando a ação em ad_provisionamento.log.
# Testar a ponte isoladamente
.\.venv\Scripts\python.exe passo4_iqservice_bridge.pyEsperado: returncode: 0, mensagem PROVISIONADO no AD: ... e o log atualizado. No fluxo
completo (PASSO 3), o webhook já chama a ponte automaticamente.
A ponte chama o PowerShell com
-ExecutionPolicy Bypass, então o script roda sem depender da política da sessão. Em produção, basta trocar a simulação pelos cmdlets reais (New-ADUser,Add-ADGroupMember) já comentados no.ps1.
PASSO 5 — IGA: Access Request + Approval workflow
Objetivo: adicionar o portão de governança. O acesso só é provisionado após aprovação, e tudo fica registrado (trilha de auditoria: quem pediu, quem decidiu, quando e por quê). Reaproveita a ponte do PASSO 4 para provisionar quando aprovado.
# Terminal 1
uvicorn passo5_access_request_api:app --reload --port 8002
# Terminal 2
python passo5_access_request_demo.pyEndpoints: POST /solicitacoes (pedir), GET /solicitacoes (auditoria),
POST /solicitacoes/{id}/aprovar (aprova e provisiona), POST /solicitacoes/{id}/rejeitar.
Esperado: a solicitação aprovada vira provisionamento no AD (returncode 0); a rejeitada
não toca no AD. Aprovar/rejeitar uma solicitação já decidida retorna 409 Conflict.
PASSO 6 — IGA: Segregation of Duties (SoD)
Objetivo: impedir que uma pessoa acumule acessos conflitantes (ex.: criar e aprovar
pagamentos). A política é verificada na aprovação do PASSO 5 e prevalece sobre a decisão do
gestor (controle preventivo). As políticas ficam em passo6_sod_policy.py.
# Terminal 1
uvicorn passo5_access_request_api:app --reload --port 8002
# Terminal 2
python passo6_sod_demo.pyEsperado: o primeiro acesso (AD-Pagamentos-Criar) é concedido; o segundo
(AD-Pagamentos-Aprovar) é bloqueado com 409 pela política SoD-Pagamentos, e nada é
provisionado. A solicitação fica com status bloqueada_sod na auditoria.
PASSO 7 — Conectando como em produção (OAuth2 + Bearer)
Objetivo: falar com o ISC do jeito real — autenticando via OAuth2 (client_credentials)
e usando Bearer token nas chamadas /v3. O mock imita o tenant; o cliente usa o mesmo
código que apontaria para um ISC de verdade (basta trocar BASE_URL e as credenciais).
# Terminal 1
uvicorn passo7_isc_mock_api:app --reload --port 8003
# Terminal 2
python passo7_isc_client.pyEsperado: autentica (recebe token), lista identities, cria um access request PENDING
e, ao chamar sem token, recebe 401/403 (segurança). O SDK oficial sailpoint (Python) faz
esse mesmo fluxo por baixo dos panos.
Sugestões para fixar os conceitos. Antes de rodar cada um, tente prever o resultado — é o que faz o aprendizado grudar. (As APIs precisam estar no ar conforme cada passo.)
- Trocar a pessoa: no
passo3_event_sender.py, mude oeventopara o Bruno Lima (id 1002, grupoAD-Grupo-TI) e rode. Confira a nova linha noad_provisionamento.log. - Desprovisionar: mude
"acao"para"desprovisionar"e rode. O log deve registrarDESPROVISIONADO. - Quebrar de propósito: remova o campo
access_profiledo evento e rode. OStatus HTTPdeve ser 422 (Pydantic recusando), e nada deve ser escrito no log.
- Rejeitar um pedido: crie uma solicitação (
POST /solicitacoes) e usePOST /solicitacoes/{id}/rejeitar. Confirme que o status virarejeitadae que o AD não foi tocado. - Decidir duas vezes: aprove uma solicitação e tente aprová-la de novo. Você deve receber
409 Conflict. Por que isso é importante em governança? - Auditoria: após várias decisões, chame
GET /solicitacoese identifique, para cada uma, quem decidiu e quando.
- Inverter a ordem: no
passo6_sod_demo.py, peça primeiroAD-Pagamentos-Aprovare depoisAD-Pagamentos-Criar. A SoD ainda bloqueia? (Deve bloquear — a política é simétrica.) - Criar sua própria política: em
passo6_sod_policy.py, adicione uma nova regra aoSOD_POLICIES(ex.:AD-Grupo-FinanceiroxAD-Grupo-Auditoria) e demonstre o bloqueio. - Acesso não-conflitante: solicite e aprove um acesso que não participa de nenhuma SoD (ex.:
AD-Grupo-TI). Confirme que ele é concedido normalmente.
Quando terminar, me mostre os resultados (ou os erros) — posso comentar o "gabarito" de cada um.
| Sintoma | Causa provável | Correção |
|---|---|---|
| "a execução de scripts foi desabilitada neste sistema" | Terminal novo sem liberar ExecutionPolicy | Rode Set-ExecutionPolicy -Scope Process -ExecutionPolicy RemoteSigned |
| "não consegui conectar na RH API" (PASSO 2) | API do PASSO 1 fora do ar | Suba uvicorn passo1_authoritative_source_api:app --reload |
| "não consegui conectar no Webhook Listener" (PASSO 3) | Webhook do PASSO 3 fora do ar | Suba uvicorn passo3_webhook_listener:app --reload --port 8001 |
| "passo3_event_sender.py não é reconhecido como cmdlet" | Faltou chamar o Python (rodou o .py direto) | Use python passo3_event_sender.py (não use .\arquivo.py) |
uvicorn/python "não reconhecido" |
.venv não ativado |
Ative o .venv ou use .\.venv\Scripts\python.exe |
| Webhook não inicia: "address already in use" | Porta 8001/8002 já ocupada | Pare o processo antigo ou use outra porta (--port 8003) |
Aprovação retorna 409 Conflict |
Solicitação já decidida ou violação de SoD | Comportamento esperado — confira o corpo da resposta (motivo) |
Chamada /v3 retorna 401/403 (PASSO 7) |
Token ausente, inválido ou expirado | Autentique em /oauth/token e envie Authorization: Bearer <token> |
Administration (concluído):
- PASSO 1 — Authoritative Source (RH API)
- PASSO 2 — Aggregation (motor do ISC)
- PASSO 3 — Event Trigger / Webhook Listener
- PASSO 4 — Ponte com PowerShell (IQService → Target System)
Governance / IGA (concluído):
- PASSO 5 — Access Request + Approval workflow (com trilha de auditoria)
- PASSO 6 — Segregation of Duties (SoD)
Integração como em produção (concluído):
- PASSO 7 — Autenticação OAuth2 (Bearer) e chamadas no estilo
/v3do ISC
Próximas evoluções possíveis:
- Access Certification — revisão periódica em que o gestor confirma/revoga acessos
- RBAC / Roles — agrupar entitlements em papéis por cargo
- Integrar o SDK oficial
sailpoint(Python) contra um tenant/sandbox real - Provisionar em um Active Directory real (descomentar os cmdlets do
.ps1) - Testes automatizados (pytest) e CI
Bruno Inácio — Especialista em Automação de Testes (Sênior), com mais de 7 anos em automação e 15 anos em QA, atuando em sistemas bancários, logísticos e de streaming. Forte base em testes de API, CI/CD, Python, Robot Framework, Selenium e cloud (AWS/Azure), expandindo a atuação para integração de sistemas e IAM (Identity & Access Management).
Este laboratório nasceu da curiosidade de entender, na prática, como plataformas de IAM orquestram identidades e acessos — aplicando minha experiência em testes de API e automação para construir uma integração ponta a ponta, e não apenas validá-la.
📍 Rio de Janeiro, Brasil · 📧 [email protected]
Distribuído sob a Licença MIT — você pode estudar, usar e adaptar o código, desde que mantenha o aviso de copyright. Veja o arquivo LICENSE para os termos completos.
© 2026 Bruno Inácio · Licenciado sob a Licença MIT