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.
DL_TECH_CMDB_V2 (27 colunas) e DL_TECH_VULNERABILIDADE_V3 (40
colunas) confirmados no App Builder, tela a tela, sem nenhum passo adivinhado. Falta: testar um
upload real através dos dois (seção 6 — a query de validação retorna "no data found" até isso
acontecer, é esperado) e gerar o export completo novo da Application 100 (seção 7).
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 ServiceNow | Coluna destino (v2.0.0) | Observação |
|---|---|---|
install_status | INSTALL_STATUS | texto direto |
life_cycle_stage_status | LIFE_CYCLE_STAGE_STATUS | texto direto |
assigned_to (ou assigned, se assigned_to vier vazio) | ASSIGNED_TO | nos ativos AMPM amostrados, os dois vinham vazios com frequência — não é bug, é lacuna do cadastro de origem |
attestation_score | ATTESTATION_SCORE | numérico direto |
attestation_status | ATTESTATION_STATUS | texto direto (ex.: "Ainda não revisada") |
attested | ATTESTED_FLAG | vem como Verdadeiro(a)/Falso(a) — mesma convenção já usada em SOX/COFRE/TENABLE/SIEM no capítulo 10; converter para 1/0 |
attested_by | ATTESTED_BY | texto direto |
u_fim_do_suporte | U_FIM_DO_SUPORTE | formato confirmado: DD-MM-YYYY (ex.: 01-07-2029) — configurar a máscara de data do Data Load Wizard como DD-MM-YYYY |
location | LOCATION | texto direto |
asset_tag | ASSET_TAG | texto direto |
u_server_role | U_SERVER_ROLE | texto direto |
4. Mapeamento — DL_TECH_VULNERABILIDADE_V3 (23 colunas novas)
| Coluna no export Tenable | Coluna destino (v2.0.0) | Observação |
|---|---|---|
definition.cve | DEFINITION_CVE | lista separada por vírgula, texto direto |
definition.description | DEFINITION_DESCRIPTION | texto direto (CLOB) |
definition.solution | DEFINITION_SOLUTION | texto direto (CLOB) |
definition.synopsis | DEFINITION_SYNOPSIS | texto direto |
software_vulns | SOFTWARE_VULNS | texto bruto (CLOB) — não fazer parsing agora, formato não é JSON válido (ver gap analysis seção 2.4) |
definition.cvss3.base_score | DEFINITION_CVSS3_BASE_SCORE | numérico direto |
definition.cvss3.base_vector | DEFINITION_CVSS3_BASE_VECTOR | texto direto |
definition.cpe | DEFINITION_CPE | texto direto |
definition.epss.score | DEFINITION_EPSS_SCORE | numérico direto |
definition.vpr.drivers_on_cisa_kev | CISA_KEV_FLAG | confirmado: vem como texto true/false (não aninhado) — converter para 1/0 |
definition.exploited_by_malware | EXPLOITED_BY_MALWARE_FLAG | confirmado: texto true/false — converter para 1/0 |
definition.exploited_by_nessus | EXPLOITED_BY_NESSUS_FLAG | confirmado: texto true/false — converter para 1/0 |
port | PORT | numérico direto |
asset.operating_system | ASSET_OPERATING_SYSTEM | texto direto; asset.operating_systems (plural) tem o mesmo conteúdo nos exemplos vistos — usar o singular como principal |
last_fixed | LAST_FIXED | data/timestamp direto |
time_to_fix | TIME_TO_FIX | numérico direto |
vuln_sla_date | VULN_SLA_DATE | data/timestamp direto |
definition.patch_published | PATCH_PUBLISHED | correção: o nome real no export tem o prefixo definition., diferente do que constava antes |
definition.vulnerability_published | VULNERABILITY_PUBLISHED | correção: idem, prefixo definition. |
source | SOURCE_SCAN | texto direto |
scan.id | SCAN_ID | texto direto |
scan.target | SCAN_TARGET | texto direto |
5. Como criar os perfis — e por que não é um script SQL
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.
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.
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.
- App Builder → Application 100 → Shared Components → Data Load Definitions.
- Clique no botão verde Create (canto superior direito).
- Tela "Create Data Load - Method": marque "As copy of an existing Data Load Definition" (não "From scratch") → Next.
- Tela "Create Data Load - Application": no campo Copy From Application, selecione "100 ampminsights" (a própria aplicação) → Next.
- 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 escrevaDL_TECH_CMDB_V2. - Linha
DL_TECH_VULNERABILIDADE_V2: mude Action para Yes; no campo To Name, escrevaDL_TECH_VULNERABILIDADE_V3. - Linha
DL_TECH_VULNERABILIDADES: deixe Action = No (essa não faz parte do v2.0.0).
- Linha
- Clique em Copy Data Load Definition (canto inferior direito).
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.
- 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 copiar | Target Name (tabela destino) | O que fazer |
|---|---|---|
Copy of DL_TECH_CMDB_V1 | TB_26AI_TECH_CMDB | ✅ renomear para DL_TECH_CMDB_V2 |
Copy of DL_TECH_VULNERABILIDADES | TB_26AI_TECH | ❌ apagar — é a tabela legada (DL_TECH_VULNERABILIDADES alimenta TB_26AI_TECH, não TB_26AI_TECH_V2) |
Copy of DL_TECH_VULNERABILIDADE_V2 | TB_26AI_TECH_V2 | ✅ renomear para DL_TECH_VULNERABILIDADE_V3 |
- Abra a cópia indesejada (
Copy of DL_TECH_VULNERABILIDADES) → botão Delete (topo da tela). - Abra
Copy of DL_TECH_CMDB_V1→ campo Name (e Static ID, que atualiza junto): troque paraDL_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. - 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).
- Abra
DL_TECH_CMDB_V2→ Edit Data Profile (confirma: mostraXLSX, 16 colunas — as originais, intactas). - 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 praDL_TECH_CMDB_V2por organização (não é obrigatório funcionalmente). - 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 (deixarName), Selector (mesmo texto do Name), Value Transformation (deixarNone— ver nota abaixo).
| Name | Data Type | Length |
|---|---|---|
INSTALL_STATUS | Varchar2 | 100 |
LIFE_CYCLE_STAGE_STATUS | Varchar2 | 100 |
ASSIGNED_TO | Varchar2 | 255 |
ATTESTATION_SCORE | Number | — |
ATTESTATION_STATUS | Varchar2 | 100 |
ATTESTED_BY | Varchar2 | 255 |
LOCATION | Varchar2 | 255 |
ASSET_TAG | Varchar2 | 100 |
U_SERVER_ROLE | Varchar2 | 255 |
ATTESTED_FLAG | Varchar2 | 10 |
U_FIM_DO_SUPORTE | Date | — (Format mask DD-MM-YYYY, Has Time Zone desligado) |
Confirmado: total final 27 colunas (16 originais + 11 novas).
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.
| Name | Data Type | Length / Config |
|---|---|---|
DEFINITION_CVE | Varchar2 | 4000 |
DEFINITION_DESCRIPTION | Clob | — |
DEFINITION_SOLUTION | Clob | — |
DEFINITION_SYNOPSIS | Varchar2 | 4000 |
SOFTWARE_VULNS | Clob | — |
DEFINITION_CVSS3_BASE_SCORE | Number | — |
DEFINITION_CVSS3_BASE_VECTOR | Varchar2 | 255 |
DEFINITION_CPE | Varchar2 | 4000 |
DEFINITION_EPSS_SCORE | Number | — |
CISA_KEV_FLAG | Number | — (true/false→1/0 manual no Excel) |
EXPLOITED_BY_MALWARE_FLAG | Number | — (idem) |
EXPLOITED_BY_NESSUS_FLAG | Number | — (idem) |
PORT | Number | — |
ASSET_OPERATING_SYSTEM | Varchar2 | 255 |
LAST_FIXED | Timestamp with time zone | má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_FIX | Number | — |
VULN_SLA_DATE | Timestamp with time zone | mesma máscara/config acima |
PATCH_PUBLISHED | Timestamp with time zone | mesma máscara/config acima |
VULNERABILITY_PUBLISHED | Timestamp with time zone | mesma máscara/config acima |
SOURCE_SCAN | Varchar2 | 100 |
SCAN_ID | Varchar2 | 255 |
SCAN_TARGET | Varchar2 | 255 |
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:
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.
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.