Pular para o conteúdo principal

Terminal e exec

Você pode abrir um shell interativo ou executar um comando avulso numa instância de aplicação em execução, pelo portal ou pela CLI. Não é preciso nenhum acesso ao Kubernetes: a plataforma abre a sessão por você, dentro do sandbox da instância, e grava e audita tudo.

Como abrir​

No portal​

Na página da aplicação, aba Terminal:

  1. Escolha a instância ou deixe Automática (primeira pronta).
  2. Clique em Abrir terminal. O aviso "Esta sessão é gravada" aparece antes da conexão.
  3. Digite exit ou clique em Encerrar para sair.

Na CLI​

# shell interativo
coda shell --app api

# comando avulso, sem shell; a CLI sai com o código do processo remoto
coda exec --app api -- uname -a
coda exec --app api -- sh -c 'exit 3'; echo $? # 3

# outra instância e terminal remoto
coda exec --app api --instance <id> -t -- top

No modo de comando avulso, o argv é executado diretamente, sem interpretação por shell, com até 32 argumentos e 4 KB no total. A sessão termina quando o processo termina.

Quem pode​

PapelAbrir sessõesVer a lista de sessõesReproduzir gravações
Owner, AdminSimTodasSim
DeveloperSim, fora dos ambientes protegidosSó as própriasNão
ViewerNãoNãoNão

Abrir sessões e ver a lista exigem, além disso, o papel Developer ou acima no projeto da aplicação, seja herdado da organização, seja por concessão direta ou de um time (um Member com concessão Developer no projeto também abre sessões). Se a concessão for revogada, as sessões abertas fecham com role_changed.

Com token de API, é preciso também o escopo exec:run.

Política da organização​

Owner e Admin definem a política em Configurações › Terminal:

OpçãoPadrãoEfeito
Terminal habilitado na organizaçãoLigadoDesligado, ninguém abre sessão (403 exec.disabled) e as abertas são encerradas
Permitir shell interativoLigadoDesligado, só comandos avulsos são aceitos (403 exec.shell_disabled)
Ambientes protegidosNenhumNesses ambientes, só Owner e Admin abrem sessão (403 exec.protected_environment para Developer)

A mesma página mostra, só para leitura, os limites do plano: se o terminal está incluído, as sessões simultâneas e a retenção das gravações. Cada mudança da política entra na auditoria.

Plano e limites​

ChaveStarterProBusinessEnterprise
Terminal incluídoexec.enabledSimSimSimSim
Sessões abertas ao mesmo tempo na organizaçãoexec.maxConcurrentSessions11030100
Retenção das gravaçõesexec.recordingRetentionDays7 dias30 dias90 dias365 dias
  • Sem exec.enabled, o pedido responde 403 plan.feature_unavailable. Se o plano deixar de incluir o terminal, as sessões abertas são encerradas em até 15 segundos; a política e as gravações ficam guardadas.
  • Acima de exec.maxConcurrentSessions, o pedido responde 422 quota.exceeded. Reduzir o limite não encerra sessões abertas.
  • O prazo de cada gravação é fixado quando a sessão termina. Uma mudança posterior da retenção vale só para as sessões encerradas depois.

Limites iguais para todos os planos, contra abuso:

LimiteValor
Sessões por usuário3 (429 com Retry-After na quarta)
Sessões por aplicação5
Inatividade (sem entrada nem saída)15 minutos
Duração máxima1 hora
Entrada do teclado64 KB/s

Onde o comando roda​

  • A sessão roda dentro do sandbox da instância (a mesma microVM), com o usuário da imagem, sem privilégios extras.
  • Só o contêiner da aplicação é alcançável. Os contêineres auxiliares da plataforma, como o agente do cofre, ficam fora de alcance.
  • A aplicação precisa ter instância em execução (409 exec.no_running_instance). Uma imagem sem /bin/sh (distroless, por exemplo) não abre shell (exec.no_shell); use o comando avulso com um binário da imagem.
  • Uma aplicação publicada antes desta funcionalidade pode pedir um novo deploy antes do primeiro terminal (exec.redeploy_required).

Encerramento​

A plataforma revalida as sessões abertas a cada 15 segundos e encerra a sessão quando algo muda. O motivo aparece no terminal e na aba Sessões:

MotivoQuando
exitedO processo terminou
client_closedVocê encerrou
idle_timeout15 minutos sem entrada nem saída
max_duration1 hora de sessão
role_changedSeu papel caiu abaixo de Developer, ou abaixo de Admin num ambiente protegido
policy_disabledO terminal foi desabilitado na organização
plan_disabledO plano deixou de incluir o terminal
organization_suspendedA organização foi suspensa
credential_revokedO token usado foi revogado ou expirou, ou suas sessões foram revogadas
instance_goneA instância deixou de existir
replica_lostA conexão com o servidor da plataforma foi perdida; abra outra sessão
killedA plataforma encerrou a sessão
no_shellA imagem não tem shell
ticket_expiredA conexão não foi concluída a tempo
errorErro inesperado

Gravação​

Toda sessão é gravada, com entrada e saída e os tempos relativos, no formato asciicast v2.

  • A gravação fica fora do banco de dados, cifrada, com chave própria por sessão.
  • O tamanho máximo é 10 MB por sessão. Acima disso, a sessão continua e a gravação é marcada como truncada.
  • Só Owner e Admin reproduzem gravações, na aba Sessões. Cada reprodução entra na auditoria.
  • Vencida a retenção, a gravação é apagada. A sessão e os eventos de auditoria continuam, com a indicação "gravação expirada".

Como a entrada também é gravada, evite digitar segredos no terminal. Use variáveis e segredos.

Auditoria​

EventoConteúdo
workload.exec.openedInstância, modo (shell ou command), terminal, canal e credencial
workload.exec.commandO argv do comando avulso (até 4 KB)
workload.exec.closedDuração, bytes, código de saída, motivo e se a gravação foi truncada
workload.exec.recording_viewedQuem reproduziu a gravação

A detecção de ameaças em tempo de execução vê o shell aberto dentro do contêiner. Durante uma sessão auditada, os alertas de shell e de processo interativo no mesmo pod aparecem ligados à sessão, como esperados e com severidade informativa. Outros alertas (como escrita em binário do sistema) mantêm a severidade, mesmo durante a sessão.

API​

Método e rotaO que faz
POST /api/v1/orgs/{orgId}/projects/{projectId}/environments/{environmentId}/applications/{appId}/exec-sessionsPede uma sessão (instance, mode, command, tty, cols, rows). Devolve um tíquete de uso único, válido por 30 segundos, e a URL wss://…/api/v1/exec/{tíquete}
GET .../exec-sessionsLista as sessões da aplicação
GET .../exec-sessions/{id}/recordingGravação em application/x-asciicast (Owner e Admin)
GET, PUT /api/v1/orgs/{orgId}/settings/execPolítica da organização (Owner e Admin, só login interativo, If-Match)

A conexão WebSocket só é aceita a partir do portal ou com o cabeçalho Authorization do mesmo usuário que pediu a sessão. Um tíquete sozinho não abre sessão.