v2.0.0 · Passo 3

Perfis de carga: DL_TECH_VULNERABILIDADE_V3 e DL_TECH_CMDB_V2

Novos perfis de carga do APEX para alimentar as colunas Tier-1 criadas no capítulo 11 — sem sobrescrever DL_TECH_VULNERABILIDADE_V2/DL_TECH_CMDB_V1, que continuam servindo a v1.3.0 em produção.

Status: mapeamento confirmado contra export real, perfis ainda não criados

O mapeamento abaixo foi conferido campo a campo contra um export real de Tenable/ServiceNow (arquivos em ampmInsights_V1_Cliente/Artefatos/, só linhas AM...) — não é suposição. O que falta é a parte que não é scriptável: criar os dois perfis de carga de fato no App Builder (Shared Components → Data Load Definitions), seguindo o roteiro da seção 4.

1. Por que perfis novos, não sobrescrever os antigos

Mesma regra já usada na v1.3.0 (ver capítulo 10): não alterar DL_TECH_VULNERABILIDADE_V2/DL_TECH_CMDB_V1 até o fluxo novo estar validado, para não quebrar a carga que já roda em produção no cliente. Os perfis novos são adicionais às colunas de sempre — não removem nenhum mapeamento existente.

2. RAW_JSON continua pendente (de propósito)

Este passo não popula RAW_JSON. O motivo: o Data Load do APEX só leva pra tabela as colunas que ele mapeia — os campos Tier 2/3 do export (que nunca ganharam coluna tipada) não chegam nem perto da tabela por este caminho. Popular RAW_JSON de verdade (a linha completa do export, todas as ~99/41 colunas) depende da tabela de staging (próximo item da Fase 1 no TASKS.md) — lá sim a linha inteira do CSV existe antes de qualquer filtro de coluna, e um `JSON_OBJECT(*)` sobre o staging resolve isso corretamente.

3. Mapeamento — DL_TECH_CMDB_V2 (12 colunas novas)

Coluna de origem exatamente como aparece no export ServiceNow real:

Coluna no export ServiceNowColuna destino (v2.0.0)Observação
install_statusINSTALL_STATUStexto direto
life_cycle_stage_statusLIFE_CYCLE_STAGE_STATUStexto direto
assigned_to (ou assigned, se assigned_to vier vazio)ASSIGNED_TOnos ativos AMPM amostrados, os dois vinham vazios com frequência — não é bug, é lacuna do cadastro de origem
attestation_scoreATTESTATION_SCOREnumérico direto
attestation_statusATTESTATION_STATUStexto direto (ex.: "Ainda não revisada")
attestedATTESTED_FLAGvem como Verdadeiro(a)/Falso(a) — mesma convenção já usada em SOX/COFRE/TENABLE/SIEM no capítulo 10; converter para 1/0
attested_byATTESTED_BYtexto direto
u_fim_do_suporteU_FIM_DO_SUPORTEformato confirmado: DD-MM-YYYY (ex.: 01-07-2029) — configurar a máscara de data do Data Load Wizard como DD-MM-YYYY
locationLOCATIONtexto direto
asset_tagASSET_TAGtexto direto
u_server_roleU_SERVER_ROLEtexto direto

4. Mapeamento — DL_TECH_VULNERABILIDADE_V3 (23 colunas novas)

Coluna no export TenableColuna destino (v2.0.0)Observação
definition.cveDEFINITION_CVElista separada por vírgula, texto direto
definition.descriptionDEFINITION_DESCRIPTIONtexto direto (CLOB)
definition.solutionDEFINITION_SOLUTIONtexto direto (CLOB)
definition.synopsisDEFINITION_SYNOPSIStexto direto
software_vulnsSOFTWARE_VULNStexto bruto (CLOB) — não fazer parsing agora, formato não é JSON válido (ver gap analysis seção 2.4)
definition.cvss3.base_scoreDEFINITION_CVSS3_BASE_SCOREnumérico direto
definition.cvss3.base_vectorDEFINITION_CVSS3_BASE_VECTORtexto direto
definition.cpeDEFINITION_CPEtexto direto
definition.epss.scoreDEFINITION_EPSS_SCOREnumérico direto
definition.vpr.drivers_on_cisa_kevCISA_KEV_FLAGconfirmado: vem como texto true/false (não aninhado) — converter para 1/0
definition.exploited_by_malwareEXPLOITED_BY_MALWARE_FLAGconfirmado: texto true/false — converter para 1/0
definition.exploited_by_nessusEXPLOITED_BY_NESSUS_FLAGconfirmado: texto true/false — converter para 1/0
portPORTnumérico direto
asset.operating_systemASSET_OPERATING_SYSTEMtexto direto; asset.operating_systems (plural) tem o mesmo conteúdo nos exemplos vistos — usar o singular como principal
last_fixedLAST_FIXEDdata/timestamp direto
time_to_fixTIME_TO_FIXnumérico direto
vuln_sla_dateVULN_SLA_DATEdata/timestamp direto
definition.patch_publishedPATCH_PUBLISHEDcorreção: o nome real no export tem o prefixo definition., diferente do que constava antes
definition.vulnerability_publishedVULNERABILITY_PUBLISHEDcorreção: idem, prefixo definition.
sourceSOURCE_SCANtexto direto
scan.idSCAN_IDtexto direto
scan.targetSCAN_TARGETtexto direto

5. Como criar os perfis — e por que não é um script SQL

Por que isto não vira um .sql como os Passos 1 e 2

As definições de carga (DL_TECH_CMDB_V1 e as duas de vulnerabilidades) já existem hoje dentro de sql/02_ampminsights_apex_app.sql, criadas via wwv_flow_imp_shared.create_data_profile/.create_data_profile_col/ .create_load_table — a API interna que o próprio export/import do APEX usa. Escrever essas chamadas à mão, fora do contexto de um import completo (com os IDs que só o APEX gera corretamente), arrisca corromper os Shared Components da Application 100. Por isso este passo é feito uma vez no App Builder e depois capturado automaticamente num novo export completo (seção 7) — o cliente nunca toca em Data Load Definitions manualmente, só importa esse arquivo, exatamente como já faz hoje em cada release.

Investigado e descartado: não existe atalho via SQL pra adicionar colunas

Cogitamos usar o pacote público APEX_DATA_LOADING pra adicionar as colunas novas via script, em vez de formulário por formulário. Confirmado contra o dicionário de dados (all_synonyms/all_arguments, owner real APEX_240200.WWV_FLOW_DATA_LOADING_API): esse pacote só tem GET_FILE_PROFILE e LOAD_DATA — os dois servem pra executar uma carga usando uma Data Load Definition que já existe, não pra criar/editar colunas de um perfil. Não tem CREATE_COLUMN_DEFINITION nem equivalente. Conclusão: adicionar colunas num Data Profile só dá pra fazer pela UI do App Builder (como já vínhamos fazendo) ou pela API interna wwv_flow_imp_shared (descartada por risco, ver nota da seção anterior). Não vale reabrir essa investigação.

Passo a passo confirmado tela a tela — sem adivinhação

A versão anterior deste capítulo sugeria "subir um arquivo de amostra para detectar colunas automaticamente" — essa tela não existe neste wizard, era um chute meu, não confirmado contra o ambiente real. O roteiro abaixo segue exatamente as telas reais, uma a uma. Onde uma tela ainda não foi vista/confirmada, isso está marcado explicitamente — não vou documentar o que não vi.

  1. App Builder → Application 100 → Shared Components → Data Load Definitions.
  2. Clique no botão verde Create (canto superior direito).
  3. Tela "Create Data Load - Method": marque "As copy of an existing Data Load Definition" (não "From scratch") → Next.
  4. Tela "Create Data Load - Application": no campo Copy From Application, selecione "100 ampminsights" (a própria aplicação) → Next.
  5. Tela "Create Data Load - As Copy": aparece uma tabela com as 3 definições que já existem (DL_TECH_CMDB_V1, DL_TECH_VULNERABILIDADES, DL_TECH_VULNERABILIDADE_V2), cada uma com um campo To Name e um dropdown Action (No/Yes/Copy and Subscribe). Faça, nesta mesma tela, as duas cópias de uma vez:
    • Linha DL_TECH_CMDB_V1: mude Action para Yes; no campo To Name, apague "Copy of DL_TECH_CMDB_V1" e escreva DL_TECH_CMDB_V2.
    • Linha DL_TECH_VULNERABILIDADE_V2: mude Action para Yes; no campo To Name, escreva DL_TECH_VULNERABILIDADE_V3.
    • Linha DL_TECH_VULNERABILIDADES: deixe Action = No (essa não faz parte do v2.0.0).
  6. Clique em Copy Data Load Definition (canto inferior direito).
Pegadinha confirmada: o campo "To Name" da tela de cópia é ignorado

Apesar de preencher "To Name" com os nomes certos na tela "As Copy", as cópias nasceram com o nome padrão (Copy of DL_TECH_CMDB_V1, Copy of DL_TECH_VULNERABILIDADES, Copy of DL_TECH_VULNERABILIDADE_V2) — as três, mesmo a que estava marcada No. Não tem problema: renomeia e apaga depois, direto na lista (próximos passos). Não perca tempo tentando fazer o "To Name" funcionar na hora da cópia.

  1. De volta à lista Data Load Definitions, mude pra visão em tabela (ícone ao lado da grade) pra ver os nomes completos e a coluna Target Name de cada cópia — assim dá pra confirmar qual é qual antes de mexer (compare com a tabela abaixo).
Nome logo após copiarTarget Name (tabela destino)O que fazer
Copy of DL_TECH_CMDB_V1TB_26AI_TECH_CMDB✅ renomear para DL_TECH_CMDB_V2
Copy of DL_TECH_VULNERABILIDADESTB_26AI_TECH❌ apagar — é a tabela legada (DL_TECH_VULNERABILIDADES alimenta TB_26AI_TECH, não TB_26AI_TECH_V2)
Copy of DL_TECH_VULNERABILIDADE_V2TB_26AI_TECH_V2✅ renomear para DL_TECH_VULNERABILIDADE_V3
  1. Abra a cópia indesejada (Copy of DL_TECH_VULNERABILIDADES) → botão Delete (topo da tela).
  2. Abra Copy of DL_TECH_CMDB_V1 → campo Name (e Static ID, que atualiza junto): troque para DL_TECH_CMDB_V2 → Apply Changes. Todos os outros campos (Target Type, Table Owner, Table Name, Loading Method, Commit Interval, Error Handling, Data Profile com as 16 colunas originais) ficam exatamente como vieram da cópia — não mexer.
  3. Abra Copy of DL_TECH_VULNERABILIDADE_V2 → mesmo processo: Name/Static ID → DL_TECH_VULNERABILIDADE_V3 → Apply Changes.

Confirmado: a lista final tem 5 definições — as 3 originais intactas (DL_TECH_CMDB_V1, DL_TECH_VULNERABILIDADES, DL_TECH_VULNERABILIDADE_V2) + as 2 novas já renomeadas (DL_TECH_CMDB_V2 → TB_26AI_TECH_CMDB, DL_TECH_VULNERABILIDADE_V3 → TB_26AI_TECH_V2).

  1. Abra DL_TECH_CMDB_V2 → Edit Data Profile (confirma: mostra XLSX, 16 colunas — as originais, intactas).
  2. No topo da tela do Data Profile ("Settings"), o campo Name ainda mostra Copy of DL_TECH_CMDB_V1 (é um objeto separado da Data Load Definition, o rename da etapa 9 não alcança aqui) — troca pra DL_TECH_CMDB_V2 por organização (não é obrigatório funcionalmente).
  3. Pra cada coluna nova: botão verde Add Column → preenche o formulário → Create. Campos confirmados do formulário: Column Type (deixar Data), Name, Data Type, Length (só aparece pra Varchar2), Selector Type (deixar Name), Selector (mesmo texto do Name), Value Transformation (deixar None — ver nota abaixo).
NameData TypeLength
INSTALL_STATUSVarchar2100
LIFE_CYCLE_STAGE_STATUSVarchar2100
ASSIGNED_TOVarchar2255
ATTESTATION_SCORENumber—
ATTESTATION_STATUSVarchar2100
ATTESTED_BYVarchar2255
LOCATIONVarchar2255
ASSET_TAGVarchar2100
U_SERVER_ROLEVarchar2255
ATTESTED_FLAGVarchar210
U_FIM_DO_SUPORTEDate— (Format mask DD-MM-YYYY, Has Time Zone desligado)

Confirmado: total final 27 colunas (16 originais + 11 novas).

ATTESTED_FLAG: sem Value Transformation — conversão é manual no Excel

Cogitei usar Value Transformation = Replace pra converter Verdadeiro(a)/Falso(a) em 1/0 automaticamente, mas o Replace só aceita um par busca/troca — não dá pra mapear dois valores diferentes numa coluna só. Verificando como as colunas booleanas que já existem (COFRE, SOX, TENABLE, SIEM, EDR, APPLIANCE, É_VIRTUAL) resolvem isso: nenhuma usa Value Transformation — a conversão sempre foi manual, feita na planilha Excel antes de subir (já documentado no capítulo 10). ATTESTED_FLAG segue a mesma regra: quem preparar a carga precisa converter a coluna attested de Verdadeiro(a)/Falso(a) pra 1/0 no Excel antes de subir. Nota também: essa coluna ficou como VARCHAR2(10) no banco (Passo 1), não NUMBER como as outras flags — uma inconsistência minha que não vale reabrir o Passo 1 pra corrigir, já que texto '1'/'0' funciona numa VARCHAR2 sem problema.

4.1 Mapeamento — DL_TECH_VULNERABILIDADE_V3 (repete o mesmo processo, 22 colunas)

Mesmo roteiro das etapas 11-13 acima, agora em DL_TECH_VULNERABILIDADE_V3 (perfil original tem 18 colunas — confirmado, bate exatamente com o capítulo 10). Os 3 campos-flag também seguem a regra de conversão manual no Excel (não usar Value Transformation), igual ATTESTED_FLAG acima.

NameData TypeLength / Config
DEFINITION_CVEVarchar24000
DEFINITION_DESCRIPTIONClob—
DEFINITION_SOLUTIONClob—
DEFINITION_SYNOPSISVarchar24000
SOFTWARE_VULNSClob—
DEFINITION_CVSS3_BASE_SCORENumber—
DEFINITION_CVSS3_BASE_VECTORVarchar2255
DEFINITION_CPEVarchar24000
DEFINITION_EPSS_SCORENumber—
CISA_KEV_FLAGNumber— (true/false→1/0 manual no Excel)
EXPLOITED_BY_MALWARE_FLAGNumber— (idem)
EXPLOITED_BY_NESSUS_FLAGNumber— (idem)
PORTNumber—
ASSET_OPERATING_SYSTEMVarchar2255
LAST_FIXEDTimestamp with time zonemáscara YYYY"-"MM"-"DD"T"HH24":"MI:SS.FF9TZR, Has Time Zone ligado — mesma config já usada em FIRST_OBSERVED/LAST_SEEN/RESURFACED_DATE do perfil original
TIME_TO_FIXNumber—
VULN_SLA_DATETimestamp with time zonemesma máscara/config acima
PATCH_PUBLISHEDTimestamp with time zonemesma máscara/config acima
VULNERABILITY_PUBLISHEDTimestamp with time zonemesma máscara/config acima
SOURCE_SCANVarchar2100
SCAN_IDVarchar2255
SCAN_TARGETVarchar2255

Esperado: total final 40 colunas (18 originais + 22 novas).

Os arquivos templates/sample_DL_TECH_CMDB_V2.xlsx e templates/sample_DL_TECH_VULNERABILIDADE_V3.xlsx servem como planilha de teste (só o cabeçalho — adicione 5-10 linhas de ativos AM... com dado real, já com os flags convertidos pra 1/0, antes de subir) pra validar a carga depois que os dois perfis estiverem prontos, na seção 6.

6. Como validar

Depois de rodar uma carga de teste pequena:

Confirma que os campos novos vieram preenchidos
SELECT asset_name, definition_cve, definition_cvss3_base_score,
       cisa_kev_flag, exploited_by_malware_flag
FROM V_26AI_TECH
WHERE definition_cve IS NOT NULL
FETCH FIRST 5 ROWS ONLY;

Se vier linha com DEFINITION_CVE preenchido e CISA_KEV_FLAG/ EXPLOITED_BY_MALWARE_FLAG como 1 ou 0 (nunca texto), os perfis estão funcionando.

7. Como isso chega ao cliente (sem ele tocar em App Builder)

Depois dos perfis criados e testados (seções 5 e 6), a captura definitiva é um novo export completo da Application 100 (App Builder → Application 100 → ícone de exportar/download → SQL Script) — isso gera um 02_ampminsights_apex_app.sql novo, com os dois perfis novos já embutidos com os IDs corretos gerados pelo próprio APEX. Esse arquivo substitui o atual no próximo release (mesmo fluxo já usado em toda entrega anterior — zip → bucket → PAR, ver o processo de release do projeto). O cliente só importa esse arquivo via App Builder → Import — um wizard guiado, não precisa entender Data Load Definitions.

Você faz isso uma vez; o cliente nunca faz

As seções 5-6 (criar e testar os perfis) são trabalho seu, num ambiente com acesso ao App Builder. O cliente recebe só o resultado — o export completo atualizado — e importa como já importa qualquer outra versão da aplicação.