PT EN
Voltar ao site

Notebook (Jupyter) — Guia do Administrador

Dar Python aos analistas costumava significar instalar ambientes locais, distribuir credenciais por e-mail e perder o controle de onde os dados vão parar. Com o ambiente de Notebook do DATTA, cada analista ganha um Jupyter completo dentro da própria plataforma — mesma identidade, mesmo visual, acesso pronto às fontes de dados — e você mantém as credenciais e o isolamento sob controle central. Este guia cobre como habilitar o ambiente, o modelo de segurança das credenciais e o diagnóstico dos problemas mais comuns.

Público: administração e operação. Para o uso do notebook pelo analista, veja o Guia do Notebook e o


O que o analista recebe

  • Jupyter Lab completo (notebook + terminal), acessível em InvestigaçãoNotebook, sem nenhuma instalação local.
  • Ambiente individual e isolado por usuário, criado sob demanda pelo JupyterHub.
  • Conectores prontos para as fontes da plataforma — Neo4j, OpenSearch, Trino, cache da plataforma, MinIO e Spark Connect — com as credenciais de dados já injetadas no ambiente.
  • Identidade única: não existe login separado. Quem está autenticado no DATTA entra no Notebook automaticamente.

Como a identidade viaja

O portal do Notebook pede à plataforma um cookie de sessão HttpOnly (datta_jwt), restrito ao caminho /jupyter. O autenticador do JupyterHub valida esse token (HS256, HS384 ou HS512), exige o perfil ANALISTA ou ADMIN e cria o usuário do hub a partir do e-mail normalizado — @ e . viram -. O endpoint que emite esse cookie está descrito na referência de API.

O tráfego de /jupyter/ vai direto ao proxy público do JupyterHub, na porta 8000; ele não passa pelo proxy de entrada da plataforma, que mantém uma rota equivalente apenas como contingência interna. Vale a atenção ao endereço interno correto: é jupyterhub-proxy-public:8000 — não existe um endereço chamado apenas jupyterhub. A variável de configuração JUPYTER_URL e o padrão usado pelo Copilot apontam para o proxy público.


Como habilitar em produção

1. Imagem do ambiente individual

A imagem jupyter-datta é construída a partir de docker/jupyter-datta/ (base quay.io/jupyter/minimal-notebook, mais os drivers de Neo4j, OpenSearch, Trino, cache da plataforma e MinIO, o Spark Connect e o tema DATTA). Ela é identificada pelo último commit que alterou essa pasta (SHA curto de 7 caracteres), desacoplada do SHA do release Java: um release que não toca o Notebook não reconstrói a imagem nem a troca nos ambientes já abertos, e git show <tag> mostra exatamente o que está no ar.

Você não calcula nem fixa essa tag à mão. O instalador e o script de release derivam a tag, constroem e publicam a imagem só quando ela ainda não existe no registro (a construção leva ~10 min e 3 GB) e passam a tag ao chart (jupyter.singleuser.image.tag) a cada implantação. Para construir ou reconstruir fora do release:

bash
./scripts/datta-build-jupyter.sh            # tag derivada do git
./scripts/datta-build-jupyter.sh --force    # reconstrói mesmo existindo

Chamado de fora do servidor com o registro do on-prem, o script constrói no servidor, a partir do commit publicado no GitHub — o registro só aceita conexão de dentro do cluster, e o commit precisa estar publicado.

A imagem passa por varredura de vulnerabilidades antes de ser publicada; um resultado HIGH/CRITICAL com correção disponível bloqueia o push.

O Spark do notebook é só cliente: a imagem traz o cliente Spark Connect 4.2.0, sem a distribuição Java embutida. Duas consequências práticas:

  • a versão tem de ser a mesma do servidor Spark Connect (k8s/jupyter/spark-connect.yml) — cliente e servidor falam o mesmo protocolo dentro de uma linha maior, então subir um sem o outro derrubaria a conexão sc://;
  • não há Spark local dentro do notebook: uma sessão criada com master("local") não existe mais. O caminho é datta_clients.spark, que conecta ao servidor. Isso tira da imagem 2 GB de bibliotecas Java que vinham com falhas críticas impossíveis de corrigir isoladamente — elas viajam dentro do pacote do Spark, e é o pacote que deixou de vir.

Nunca use um latest flutuante.

Com jupyter.prepull.enabled: true (o padrão da instalação), cada máquina do cluster baixa a imagem logo após a implantação. Sem isso, a primeira abertura do Notebook em cada máquina paga o download inteiro dentro do tempo limite de criação do ambiente — a tela fica minutos em "Iniciando…" ou falha.

2. Configuração da instalação

values-onprem-local.yaml traz jupyter.enabled: true. As credenciais (jupyter.serviceToken, as chaves de MinIO e os demais segredos) vêm do arquivo .env — ou do release atual, por contingência — e são injetadas pelo script de release.

3. Implantação

Rode ./scripts/datta-release.sh (release uniforme). Ele sobe o hub, o proxy, os endereços internos, o cofre dedicado jupyter-user-secrets e a regra de roteamento de /jupyter/.


Modelo de segurança das credenciais

O ambiente de Notebook executa código arbitrário do analista. Por isso ele recebe credenciais de um cofre dedicado (jupyter-user-secrets), nunca o cofre de segredos da plataforma inteiro (datta-secrets).

O cofre dedicado contém somente o escopo "Dados + MinIO", e cada valor é de um usuário próprio, de menor privilégio (auditoria de 2026-09-04):

  • NEO4J_PASSWORD — do usuário jupyter_reader (papel reader: só leitura em todo banco), criado pelo job de inicialização do Neo4j. Nunca a senha do superusuário neo4j.
  • MINIO_ACCESS_KEY = jupyter e MINIO_SECRET_KEY — usuário com a política datta-jupyter: leitura nos buckets de warehouse e documentos, leitura e escrita só no bucket de staging. Nunca as chaves root.
  • OpenSearch: sem credencial enquanto o plugin de segurança estiver desligado; quando for ligado, um usuário de leitura entra aqui como OPENSEARCH_PASSWORD.

As senhas dos dois usuários são geradas e preservadas no cofre da plataforma (JUPYTER_NEO4J_PASSWORD, JUPYTER_MINIO_PASSWORD) e chegam ao ambiente do notebook por referência a essas duas chaves específicas, nunca ao cofre inteiro. O cofre dedicado passa a guardar apenas o nome do usuário MinIO.

Por que isso importa: o cofre da plataforma carrega JWT_SECRET, DATTA_VAULT_MASTER_KEY, GEMINI_API_KEY, DATTA_INTERNAL_TOKEN, ADMIN_DEFAULT_PASSWORD e outros. Um analista leria qualquer um deles com um os.environ de dentro de uma célula — expor o cofre inteiro seria vazamento de segredos da plataforma.

Duas decisões complementam o isolamento:

  • Cofre estreito injetado por bloco, não chave a chave. O criador de ambientes não consegue mesclar listas de variáveis de ambiente: uma referência por chave apagaria a lista de variáveis que ele mesmo define. Por isso o cofre é estreito e injetado inteiro.
  • Sem token de infraestrutura. O ambiente individual sobe sem montar automaticamente o token de conta de serviço do cluster — de dentro do notebook não há credencial de administração da infraestrutura.

Copilot cria notebooks (recurso opcional)

O Copilot do chat consegue criar notebooks .dattanb prontos no ambiente do usuário, usando a Contents API do Jupyter. Isso exige um service token do JupyterHub, registrado no hub com o escopo access:servers — um token do DATTA não é um token válido do JupyterHub.

  • O token vem de JUPYTER_SERVICE_TOKEN, gerado pelo setup-datta.sh e persistido no .env.
  • Sem ele, o hub não registra o serviço e a criação de notebook pelo Copilot fica desativada com aviso amigável — todo o restante do Notebook funciona normalmente.
  • O script de release preserva jupyter.serviceToken entre releases, então a habilitação não se perde a cada implantação.

Diagnóstico rápido

SintomaCausa provávelAção
"Notebook indisponível" (estado de erro, com o código HTTP quando houver)o hub não respondeu — pode estar reiniciando ou estar com jupyter.enabled=false; do navegador as duas causas são indistinguíveisAguarde alguns segundos e recarregue a página (F5); se persistir, confirme jupyter.enabled: true na configuração da instalação e verifique a saúde do hub pelo console da plataforma
"Verificando…" que nunca terminaJá corrigido: a tela tinha saídas sem estado (sessão ausente, perfil sem acesso, cookie recusado, hub mudo) e nenhum tempo limiteA tela é uma máquina de estados: cada verificação tem tempo limite e toda saída pinta a barra (indisponível, sem sessão, sem permissão, parado, iniciando com percentual, ativo, erro com "Tentar de novo"); force a recarga do asset no navegador
Iframe vazio / "refused to connect"Política frame-ancestors do hub ou do ambiente individualJá tratado: o hub e os argumentos do criador de ambientes definem frame-ancestors 'self'
Erro de permissão em /home/jovyanO volume do diretório pessoal nasce com dono rootJá tratado: um passo de inicialização ajusta a propriedade para o usuário do notebook, e ele faz parte da instalação
Copilot não cria notebookJUPYTER_SERVICE_TOKEN ausenteDefina no .env e reimplante — recurso opcional, o Notebook segue funcionando sem ele
Notebook não conecta a Neo4j/OpenSearch/MinIOCredencial ausente no cofre dedicadoConfira que jupyter-user-secrets tem as quatro chaves de dados
"Iniciando…" por minutos na primeira aberturaA imagem (~3 GB) ainda não estava na máquinaAtive jupyter.prepull.enabled (padrão da instalação) — o aquecimento acontece logo após a implantação, não no primeiro clique
Ambiente não sobe e o hub registra imagem não encontradaA tag da imagem passada ao chart não existe no registroRode ./scripts/datta-build-jupyter.sh (constrói e publica a tag derivada do git) e reimplante

Para separar em qual porta o acesso para (hub, emissão do cookie, aceite do cookie pelo hub, criação do ambiente), siga o runbook Notebook — diagnóstico E0, que traz as quatro chamadas na ordem.


Para saber mais

  • Guia do Notebook — uso do notebook pelo analista. de notebooks.
  • Perfis e permissões — de onde vêm os perfis ANALISTA e ADMIN.