Dê ao Relatório de Liquidação Apenas os Dados de que Ele Precisa

PostgreSQLBeginner
Pratique Agora

Introdução

A MarketLedger precisa de um relatório de liquidação para seus pequenos vendedores de mercado. O relatório deve ler os totais de ontem, não os endereços de e-mail dos clientes ou as referências bancárias, e não deve gravar pedidos. Sua política atual de criação de contas é mais ampla do que essa tarefa precisa.

Você restringirá essa política, obterá um login PostgreSQL temporário real por meio do OpenBao e salvará um relatório completo separado por tabulações usando a consulta fornecida. Você precisa de conhecimentos básicos de terminal e caminhos. As permissões SQL, os arquivos de credenciais e as opções relevantes dos comandos são explicados antes do uso; não é necessário programar em Python nem ter uma conta de nuvem.

Conheça a Loja e o Relatório de que Ela Precisa

Nesta etapa, você começará pelo negócio em funcionamento e por um relatório normal antes de alterar permissões. Use Terminal durante todo este laboratório. cd muda o diretório; um caminho absoluto funciona de qualquer local:

cd /home/labex/project/market-report

PostgreSQL é o banco de dados preparado. OpenBao é um serviço de segredos preparado que pode solicitar a esse banco a criação de um novo login por tempo limitado. São processos reais no contêiner deste laboratório. Não são um banco de dados hospedado nem uma implantação de segredos de produção.

O shop.py preparado é um pequeno cliente para o serviço da loja em funcionamento. Executá-lo não exige escrever Python. list mostra os pedidos de hoje:

python3 shop.py list

Inicialmente, espere uma lista vazia, []. Faça um pedido normal. --order identifica o pedido, --vendor identifica seu vendedor e --cents informa o valor como um número inteiro de centavos:

python3 shop.py place --order O201 --vendor V101 --cents 600

Espere um pedido pago armazenado para a data comercial sintética 2026-10-29. Se repetir o comando, o serviço recusa o ID duplicado; use list para ver o pedido existente em vez de excluí-lo ou sobrescrevê-lo.

A liquidação cobre a data anterior, 2026-10-28. O novo pedido de hoje não deve alterar os totais de ontem. cat exibe um arquivo de texto; inspecione o relatório preparado como exemplo funcional:

cat demo.tsv

Espere três linhas de vendedores:

vendor_id vendor_name paid_orders total_cents
V101 Birch Pantry 2 4700
V102 Elm Bakery 1 2000
V103 Maple Kitchen 1 2700

Os separadores são caracteres de tabulação, por isso o nome do arquivo termina em .tsv. Quatro pedidos pagos totalizam 9400 centavos. O pedido cancelado da Elm é excluído. A demonstração foi lida com um leitor preparado separado; copiá-la não demonstra que sua nova identidade de banco de dados consegue executar o relatório.

Uma view é uma consulta nomeada de banco de dados que expõe resultados selecionados. reporting.daily_settlement combina nomes de vendedores com totais de pedidos pagos e omite endereços de e-mail de clientes e referências bancárias. Os registros originais permanecem nas tabelas privadas public.orders e public.vendors. Aqui, reporting e public são nomes de schemas, que agrupam objetos do banco de dados; a palavra public não significa que todo papel deva ter acesso.

Você pode editar role.sql, registrar o papel OpenBao settlement-report, obter credenciais desse papel e criar seus arquivos de relatório e credenciais. Mantenha inalterados a loja, os registros originais do banco, o outro papel de relatório, a consulta fornecida, o arquivo de ambiente, o token de operador e o ambiente de execução preparado. Você não precisa de uma senha de administrador do banco de dados nem de um token root do OpenBao.

Para um erro comum No such file or directory, volte com o cd absoluto acima, use ls para conferir os nomes reais dos arquivos e tente novamente. Não reinicialize o ambiente para corrigir um erro de digitação.

Limite a Política de Criação de Contas à View de Liquidação

Nesta etapa, você removerá permissões de que o relatório não precisa. Comece em Terminal, em /home/labex/project/market-report.

Leia as instruções atuais de criação de contas:

cat role.sql

O OpenBao substitui três marcadores quando emite credenciais: {{name}} se torna um novo nome de usuário do banco, {{password}} se torna uma senha gerada e {{expiration}} se torna o horário de expiração da conta. Mantenha esses marcadores; não os substitua por seu próprio nome de usuário ou senha fixos.

CREATE ROLE ... WITH LOGIN cria um login PostgreSQL. VALID UNTIL limita até quando sua senha pode autenticar uma nova conexão. Não encerra todas as conexões que já estavam abertas. Você estudará a revogação explícita e a expiração natural de concessões no próximo laboratório guiado.

GRANT concede uma permissão. USAGE ON SCHEMA reporting permite localizar objetos nesse schema. SELECT ON reporting.daily_settlement permite ler essa única view. As permissões extras atuais em public permitem ler tabelas privadas e alterar pedidos; este relatório não precisa de nenhuma dessas capacidades.

A linha final ALTER ROLE ... SET log_statement = 'all' habilita a auditoria SQL nativa para cada novo login de relatório criado. Mantenha-a: as consultas feitas com essa identidade devem continuar atribuíveis. As instruções de gerenciamento para criação de contas, que contêm senhas, não são registradas por essa configuração por login. O log de auditoria preparado do OpenBao também aplica hash aos valores secretos.

Substitua o arquivo pelas instruções mais restritas abaixo. cat > role.sql redireciona o texto fornecido para esse arquivo. <<'ROLESQL' inicia um here-document; o marcador entre aspas preserva o texto incluído exatamente até a linha contendo apenas ROLESQL:

cat > role.sql <<'ROLESQL'
CREATE ROLE "{{name}}" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}';
GRANT USAGE ON SCHEMA reporting TO "{{name}}";
GRANT SELECT ON reporting.daily_settlement TO "{{name}}";
ALTER ROLE "{{name}}" SET log_statement = 'all';
ROLESQL

Leia o arquivo salvo:

cat role.sql

O papel tem um login gerado, um tempo de validade limitado para a senha, permissão de localização no schema e acesso de leitura a uma view. Não tem acesso a tabelas brutas, permissões de escrita ou atributos de administrador. Uma permissão de view é útil aqui porque a view fornecida omite intencionalmente os dados privados; uma view que expusesse esses campos privados não forneceria o mesmo limite.

Se o terminal esperar mais entrada porque você omitiu o marcador final, digite ROLESQL sozinho em uma linha. Se o arquivo salvo estiver incompleto, repita o bloco inteiro. Isso muda apenas seu arquivo de política, ainda não o banco de dados em execução.

Registre a Política com o Operador Restrito do OpenBao

Nesta etapa, você registrará sua política de contas sem usar uma identidade de administrador do serviço de segredos. Permaneça em Terminal.

Leia o arquivo de ambiente preparado antes de carregá-lo:

cat env.sh

source env.sh executa essas atribuições no shell atual deste terminal. export disponibiliza um valor aos comandos filhos. O arquivo adiciona a ferramenta preparada bao a PATH, a lista de busca de comandos do shell, e define os endereços locais do OpenBao e do PostgreSQL. $(cat ...) lê o token de operador preparado de seu arquivo privado; o token em si não é exibido. Essas configurações pertencem a esta sessão de terminal. Um novo terminal precisa carregá-las novamente:

source env.sh

Um token de operador do OpenBao autoriza solicitações ao serviço de segredos. Ele não é um nome de usuário ou senha PostgreSQL. Este token pode gerenciar e obter credenciais para settlement-report e revogar as concessões exatas desse papel. Não pode ler a conexão de gerenciamento do banco de dados nem gerenciar o relatório de inventário separado.

bao write grava a configuração no caminho OpenBao nomeado. db_name=market seleciona a conexão preparada do banco de dados. creation_statements=@role.sql lê seu arquivo SQL como o valor desse campo; @ é a sintaxe de entrada de arquivo do OpenBao. default_ttl=10m dá às novas concessões dez minutos por padrão, e max_ttl=15m limita sua configuração de validade. TTL é o tempo de vida. Use esses limites curtos para o relatório em vez de horas ou de uma conta sem limite:

bao write database/roles/settlement-report db_name=market creation_statements=@role.sql default_ttl=10m max_ttl=15m

Espere a confirmação de que os dados foram gravados em database/roles/settlement-report. Isso altera a política de criação; ainda não emitiu um login de banco de dados. Uma mudança de política afeta contas futuras. Não remove permissões de um login já emitido. Após qualquer alteração de política registrada, obtenha uma nova credencial e gere seu relatório novamente com ela. A verificação de conclusão exige que a identidade do relatório tenha sido emitida após o registro final de sua política. Não deixe ativo um login de relatório anterior com permissões excessivas; a recuperação condicional da próxima etapa mostra como encerrar sua concessão exata antes de substituir seu arquivo de credenciais.

A autoverificação de política lê a política registrada atual e exercita seu SQL em um ambiente PostgreSQL descartável de teste. Não emite uma concessão, não modifica o banco de dados em uso nem executa seu relatório real. sudo permite que esse verificador preparado inspecione configurações protegidas e execute sua conta comum isolada; seus comandos normais de OpenBao e banco de dados usam as identidades restritas:

sudo python3 /opt/labex-report/verify.py policy

Se informar uma permissão extra ou uma expiração ausente, corrija role.sql e registre-o novamente. Mantenha os marcadores e a cláusula de auditoria. Instruções de permissão equivalentes que implementem o limite declarado são aceitas; a verificação não exige um editor ou uma grafia SQL específica.

Obtenha um Login Temporário e Execute o Relatório Real

Nesta etapa, você usará uma identidade de banco de dados recém-emitida para produzir seu arquivo de liquidação. Comece na mesma sessão de Terminal, com env.sh carregado.

Uma resposta de credenciais contém três coisas diferentes: um ID de concessão que identifica esta emissão no OpenBao, um nome de usuário PostgreSQL gerado e sua senha. O token de operador da etapa anterior autorizou a emissão; ele não é uma dessas credenciais de banco de dados.

Mantenha os arquivos de credenciais privados. umask 077 faz os arquivos recém-criados serem legíveis e graváveis apenas por sua conta; não altera arquivos existentes:

umask 077

bao read solicita credenciais para o papel. -format=json escolhe uma saída JSON estruturada. > salva essa saída em lease.json, substituindo um arquivo existente com esse nome. Este comando realmente cria um novo login PostgreSQL e inicia o relógio de sua concessão; não o execute repetidamente apenas para inspecionar a mesma concessão:

bao read -format=json database/creds/settlement-report > lease.json

jq seleciona campos do JSON. -r exibe valores de string sem as aspas do JSON. Leia a identidade não secreta, o ID e a duração da concessão; não exiba a senha:

jq '.lease_id, .lease_duration, .data.username' lease.json

Espere um ID de concessão database/creds/settlement-report/..., uma duração de 600 segundos e um nome de usuário gerado. Seus sufixos aleatórios serão diferentes a cada vez.

O cliente PostgreSQL psql lê PGUSER e PGPASSWORD do ambiente. Substituições $(...) entre aspas definem esses valores a partir desta emissão. Esses valores permanecem nesta sessão de terminal e em seus comandos filhos:

export PGUSER="$(jq -r .data.username lease.json)"
export PGPASSWORD="$(jq -r .data.password lease.json)"

psql -X ignora personalizações de inicialização pessoais do psql, -v ON_ERROR_STOP=1 para em erros SQL e -c fornece um comando SQL. SELECT current_user pergunta ao PostgreSQL qual identidade esta conexão realmente usa:

psql -X -v ON_ERROR_STOP=1 -c 'SELECT current_user;'

Espere o mesmo nome de usuário gerado de lease.json, não o gravador da loja, o leitor da demonstração ou o administrador do banco de dados.

O report.sql preparado seleciona as quatro colunas públicas do relatório, ordena as linhas por ID de vendedor e as copia para a saída padrão como dados separados por tabulações com um cabeçalho. Mantenha a consulta inalterada. -f lê SQL desse arquivo, enquanto > salva apenas a saída do relatório:

psql -X -v ON_ERROR_STOP=1 -f report.sql > settlement.tsv

Leia seu resultado real:

cat settlement.tsv

Suas três linhas de vendedores devem corresponder ao exemplo de negócio anterior: Birch 2 / 4700, Elm 1 / 2000, Maple 1 / 2700. Nenhum e-mail de cliente ou referência bancária deve aparecer. O total continua sendo 9400 centavos porque o pedido O201 de hoje está fora da liquidação de ontem.

Se uma conexão posterior falhar com password authentication failed, a concessão de dez minutos pode ter expirado enquanto você lia. Isso é uma falha de credencial, não uma consulta de tabela negada. Repita o comando de emissão de credenciais uma vez, recarregue PGUSER e PGPASSWORD do novo arquivo e execute novamente os comandos de identidade e relatório. Um novo nome de usuário é esperado. Não edite o nome de usuário registrado nem estenda a expiração manualmente.

Há uma recuperação diferente caso você tenha alterado a política depois de já ter emitido credenciais. Essa conta anterior mantém suas permissões originais. Antes de substituir seu lease.json, execute bao lease revoke "$(jq -r .lease_id lease.json)". A substituição entre aspas fornece esse ID exato de concessão salvo; não é um nome de usuário do banco nem um prefixo de concessão. Nunca revogue o relatório de inventário nem um prefixo inteiro de concessões. Após encerrar a emissão anterior, solicite uma nova credencial, recarregue as duas variáveis do banco e gere o relatório novamente usando os comandos acima. Isso evita deixar um login antigo com permissões excessivas utilizável ao lado do novo login limitado.

Confirme que os Dados Privados e as Escritas Continuam Indisponíveis

Nesta etapa, você testará o limite da conta preservando a loja e seus dados originais. Use o mesmo Terminal com sua identidade PostgreSQL emitida.

A leitura a seguir deve falhar. SELECT * solicita todas as colunas; a política deve impedir esta conta de ler os pedidos brutos:

psql -X -v ON_ERROR_STOP=1 -c 'SELECT * FROM public.orders;'

Espere um erro PostgreSQL permission denied para o schema ou a tabela privados. $? é o status de saída do comando imediatamente anterior; echo o exibe. Leia-o imediatamente:

echo $?

Espere 1, uma consulta SQL recusada. Uma falha de conexão com status 2 não demonstra esse limite de permissão; use a recuperação de reemissão e recarga da etapa anterior se a concessão tiver expirado.

Agora tente uma escrita inofensiva aos dados: UPDATE ... WHERE false não corresponde a nenhuma linha, portanto não poderia alterar pedidos mesmo se a conta tivesse incorretamente permissões excessivas. Ainda assim, deve ser recusada por permissão insuficiente:

psql -X -v ON_ERROR_STOP=1 -c 'UPDATE public.orders SET amount_cents = 0 WHERE false;'
echo $?

Mais uma vez, espere um erro de permissão e status 1. A conta consegue ler a view pretendida, mas não consegue ler dados privados brutos nem gravar pedidos.

O cliente preparado da loja usa a identidade de escrita separada do serviço da loja, em vez de suas credenciais de relatório. Confirme que o pedido que você fez ainda está disponível:

python3 shop.py list

Execute a verificação de conclusão somente de leitura. Ela primeiro lê as evidências nativas existentes de emissão do OpenBao e de consultas PostgreSQL; depois verifica seu relatório real e os dados de negócio preservados. Não cria um login ausente nem gera o relatório por você:

sudo python3 /opt/labex-report/verify.py result

Agora você tem uma liquidação completa produzida com uma identidade real de banco de dados, limitada e emitida dinamicamente. O próximo laboratório independente começa com a política correta de permissões e se concentra em encerrar o acesso e observar falhas de novas conexões.

Resumo

Você registrou uma política limitada de criação de contas, obteve um novo login PostgreSQL por meio de um operador restrito do OpenBao e usou essa identidade para salvar uma liquidação real. Sua view expõe os totais de negócio necessários, enquanto tabelas privadas, escritas e privilégios de administrador permanecem fora do escopo do relatório.

O token de operador, o ID de concessão e as credenciais de banco de dados têm funções distintas. Este exercício ainda depende de componentes de gerenciamento preparados e confiáveis; contas temporárias não eliminam essa confiança inicial. O próximo laboratório examina a revogação exata de concessões, a expiração natural e a recuperação por meio de uma nova emissão.