Visão geral
A integração nativa enviava os eventos detection.opened diretamente para uma tabela do ServiceNow. Com os Feeds, você escolhe quais tickets serão entregues, e um pequeno script no ServiceNow transforma cada ticket em um registro de Incident.
Figura 1: Os dois modos de entrega. Ambos usam o mesmo JSON e o mesmo script de mapeamento.
Push (Webhook 2.0): quase em tempo real
A Plataforma Axur envia os tickets para um endpoint que você cria no ServiceNow. É a opção mais próxima da integração nativa, mas sua instância precisa aceitar chamadas de entrada.
Pull (polling): mais fácil de aprovar
O ServiceNow consulta o feed a cada X minutos. O tráfego é somente de saída, e a latência é igual ao intervalo do agendamento.
Pré-requisitos
Um usuário admin no ServiceNow (ou web_service_admin para Push), um usuário manager na Plataforma Axur para criar o feed e uma API Key da Plataforma Axur (para Pull).
Criar o feed na Plataforma Axur
Acesse one.axur.com/api-integrations → seção Feeds → Add feed → Skip templates.
Escolha o tipo Tickets.
Escolha o modo de entrega: Pull ou Push. Para Push, informe a URL do endpoint que você vai criar na etapa 6.
Em Event date, selecione First detection (
ticket.creation.date). Cada ticket chega apenas uma vez, assim como odetection.openedda integração nativa.Em Feed parameters, deixe em branco para receber tudo ou aplique um filtro, por exemplo:
type=phishing,fake-social-media-profile.Defina um título, por exemplo “ServiceNow – Incidents”, e salve. Anote o ID/URL do feed.
Figura 2: Configuração sugerida do feed (ilustração; a tela real pode ser diferente).
Também quer receber redetecções?
Use Any detection (open.date). O script abaixo atualiza o incidente existente pelo ticketKey (correlation_id), então nenhum incidente é duplicado.
Mapeamento de campos
Cada item em collectionData.tickets[] vira um registro na tabela Incident. As cores mostram de onde vem cada informação:
Tabela de mapeamento
Campo no ServiceNow | Origem no JSON | Observações |
| fixo | Definido apenas na criação. Atualizações não reabrem o incidente. |
|
| Usado para evitar duplicidades. |
|
| Igual à integração nativa. |
| Workspace - Tipo - | Mesmo formato da integração nativa. Limitado a 160 caracteres: apenas a URL é encurtada (com |
| Template nativo (Figura 3b) | Link: |
Atenção às chaves com ponto
Campos como open.date e creation.date têm um ponto no nome. Em JavaScript, use colchetes: d['open.date'], e não d.open.date.
Script Include: o mapeador
Este script monta os campos e cria ou atualiza o incidente. Você o cria uma única vez, e ele é usado tanto pelo Push quanto pelo Pull.
No ServiceNow, acesse System Definition › Script Includes → New.
Name:
AxurFeedMapper(precisa ser exatamente este nome).Cole o código abaixo no campo Script e salve.
Figura 4: Criação do Script Include (ilustração).
TYPE_LABELS e WORKSPACES contêm os rótulos oficiais usados pela Plataforma Axur, para que o texto fique igual ao da integração nativa. Tipos que não estão na lista usam Axur Surface e o slug original como padrão, então nada quebra.
var AxurFeedMapper = {
TABLE: 'incident',
TICKET_URL: 'https://one.axur.com/brand-protection/tickets/',
SHORT_DESCRIPTION_LIMIT: 160,
DEFAULT_WORKSPACE: 'Axur Surface',
WORKSPACES: {
'digital-fraud': 'Digital Fraud',
'online-piracy': 'Online Piracy',
'data-leakage': 'Data Leakage',
'deep-dark-web': 'Deep & Dark Web',
'executives-vips': 'Executives & VIPs'
},
TYPE_LABELS: {
'phishing': { workspace: 'digital-fraud', name: 'Phishing' },
'paid-search': { workspace: 'digital-fraud', name: 'Brand use in paid search' },
'malware': { workspace: 'digital-fraud', name: 'Malware' },
'fake-social-media-profile': { workspace: 'digital-fraud', name: 'Fake social media profile' },
'similar-domain-name': { workspace: 'digital-fraud', name: 'Similar domain name' },
'fake-mobile-app': { workspace: 'digital-fraud', name: 'Fake mobile app' },
'fraudulent-brand-use': { workspace: 'digital-fraud', name: 'Fraudulent brand use' },
'unauthorized-sale': { workspace: 'online-piracy', name: 'Counterfeit or irregular sale' },
'unauthorized-distribution': { workspace: 'online-piracy', name: 'Content piracy' },
'corporate-credential-leak': { workspace: 'data-leakage', name: 'Corporate credential leak' },
'code-secret-leak': { workspace: 'data-leakage', name: 'Code secret leak' },
'database-exposure': { workspace: 'data-leakage', name: 'Database exposure' },
'document-leak': { workspace: 'data-leakage', name: 'Document leak' },
'other-sensitive-data': { workspace: 'data-leakage', name: 'Other sensitive data' },
'infostealer-credential': { workspace: 'data-leakage', name: 'Infostealer credentials' },
'dw-activity': { workspace: 'deep-dark-web', name: 'Deep & Dark Web activity' },
'data-exposure-website': { workspace: 'deep-dark-web', name: 'Data exposure in website' },
'data-sale-website': { workspace: 'deep-dark-web', name: 'Data sale in website' },
'fraud-tool-scheme-website': { workspace: 'deep-dark-web', name: 'Fraud tool or scheme in website' },
'suspicious-activity-website': { workspace: 'deep-dark-web', name: 'Suspicious activity in website' },
'data-exposure-message': { workspace: 'deep-dark-web', name: 'Data exposure in messaging app' },
'data-sale-message': { workspace: 'deep-dark-web', name: 'Data sale in messaging app' },
'fraud-tool-scheme-message': { workspace: 'deep-dark-web', name: 'Fraud tool or scheme in messaging app' },
'suspicious-activity-message': { workspace: 'deep-dark-web', name: 'Suspicious activity in messaging app' },
'infrastructure-exposure': { workspace: 'deep-dark-web', name: 'Infrastructure exposure' },
'ransomware-attack': { workspace: 'deep-dark-web', name: 'Ransomware attack alert' },
'executive-fake-social-media-profile': { workspace: 'executives-vips', name: 'Fake social media profile' },
'executive-personalinfo-leak': { workspace: 'executives-vips', name: 'Personal information leak' },
'executive-credential-leak': { workspace: 'executives-vips', name: 'Credential leak' },
'executive-mobile-phone': { workspace: 'executives-vips', name: 'Phone number leak' },
'executive-card-leak': { workspace: 'executives-vips', name: 'Credit card leak' }
},
buildFields: function (item) {
var t = item.ticket || {};
var d = item.detection || {};
var ticketKey = t.ticketKey;
var type = d.type || '';
var label = this.TYPE_LABELS[type] || { workspace: '', name: type };
var workspace = this.WORKSPACES[label.workspace] || this.DEFAULT_WORKSPACE;
var threatUrl = t.reference || '';
var prefix = workspace + ' - ' + label.name + ' - ' + t.customerKey + ' - ';
var suffix = ' (' + ticketKey + ')';
var shortDescription = prefix + this.fitReference(threatUrl, prefix.length + suffix.length) + suffix;
var description = [
'Axur - one.axur.com',
'',
'New threat detected (' + this.TICKET_URL + ticketKey + ')',
'',
'Ticket Key: ' + ticketKey,
this.assetsLine(d.assets || []),
'Ticket Type: ' + label.name + ' (' + type + ')',
'Threat URL: ' + threatUrl,
'Detection Date: ' + this.formatDate(d['open.date'] || t['creation.date'])
].join('\n');
return { ticketKey: ticketKey, shortDescription: shortDescription, description: description };
},
fitReference: function (reference, usedLength) {
var available = this.SHORT_DESCRIPTION_LIMIT - usedLength;
if (reference.length <= available) return reference;
return reference.substring(0, Math.max(available - 3, 0)) + '...';
},
assetsLine: function (assets) {
return assets.length === 1 ? 'Asset: ' + assets[0] : 'Assets: (' + assets.join(', ') + ')';
},
formatDate: function (iso) {
if (!iso) return '';
return iso.substring(8, 10) + '/' + iso.substring(5, 7) + '/' + iso.substring(0, 4);
},
upsert: function (item) {
var f = this.buildFields(item);
if (!f.ticketKey) return;
var gr = new GlideRecord(this.TABLE);
gr.addQuery('correlation_id', f.ticketKey);
gr.query();
var exists = gr.next();
if (!exists) {
gr.initialize();
gr.state = 1;
}
gr.correlation_id = f.ticketKey;
gr.correlation_display = f.ticketKey;
gr.short_description = f.shortDescription;
gr.description = f.description;
if (exists) { gr.update(); } else { gr.insert(); }
},
processPayload: function (payload) {
var tickets = (payload && payload.collectionData && payload.collectionData.tickets) || [];
for (var i = 0; i < tickets.length; i++) {
this.upsert(tickets[i]);
}
return tickets.length;
}
};Outra tabela?
Se os registros não devem ir para incident, altere o valor de TABLE. A tabela precisa ter os campos correlation_id, short_description e description.
Opção A: Pull com um Scheduled Job
Escolha esta opção se a sua instância não pode receber chamadas externas.
Armazenar a URL e a API Key
Acesse sys_properties.list (digite no filtro de navegação) → New.
Crie
axur.feed.urlcom a URL do feed, por exemplo:https://api.axur.com/gateway/1.0/api/integration-feed/feeds/feed/<ID>.Crie
axur.feed.api_keycom a API Key da Plataforma Axur e restrinja os Read roles aadmin.
Segurança
Nunca escreva a API Key diretamente no script. Se o seu time de segurança preferir, use Connection & Credential Aliases em vez da system property.
Criar o agendamento
Acesse System Definition › Scheduled Jobs → New → Automatically run a script of your choosing.
Name:
Axur Feed → Incident. Run: Periodically. Repeat interval:00:05:00(5 min).Cole o script abaixo e salve.
Figura 5: Scheduled Job executando a cada 5 minutos (ilustração).
var FEED_URL = gs.getProperty('axur.feed.url');
var API_KEY = gs.getProperty('axur.feed.api_key');
var MAX_PAGES = 20;
for (var page = 0; page < MAX_PAGES; page++) {
var request = new sn_ws.RESTMessageV2();
request.setEndpoint(FEED_URL);
request.setHttpMethod('GET');
request.setRequestHeader('Authorization', 'Bearer ' + API_KEY);
request.setRequestHeader('Accept', 'application/json');
var response = request.execute();
if (response.getStatusCode() != 200) {
gs.error('Axur feed: HTTP ' + response.getStatusCode() + ' - ' + response.getBody());
break;
}
var processed = AxurFeedMapper.processPayload(JSON.parse(response.getBody()));
if (processed === 0) break;
}
Cada chamada ao feed avança o ponteiro e retorna a próxima página. O loop continua até que uma página volte vazia, com limite de 20 páginas por execução para que o job nunca trave. Consulte a documentação da API para ver o formato do header de autenticação.
Opção B: Push com uma Scripted REST API
Escolha esta opção para receber os tickets quase em tempo real. Sua instância precisa aceitar chamadas de entrada vindas da Plataforma Axur.
Acesse System Web Services › Scripted Web Services › Scripted REST APIs → New.
Name:
Axur Feed, API ID:axur_feed. Salve.Na aba Resources → New: Name
tickets, HTTP methodPOST, Relative path/tickets.Cole o script abaixo no resource e salve.
Copie o Resource path (por exemplo:
https://<instance>.service-now.com/api/<scope>/axur_feed/tickets) e informe-o como endpoint do feed Push na Plataforma Axur.
Figura 6: Resource POST que recebe o Webhook 2.0 (ilustração).
(function process(request, response) {
var processed = AxurFeedMapper.processPayload(request.body.data);
response.setStatus(200);
response.setBody({ processed: processed });
})(request, response);Autenticação do endpoint
Por padrão, o resource exige autenticação do ServiceNow (Requires authentication). Configure-a de acordo com as opções de autenticação disponíveis no feed Push da Plataforma Axur (por exemplo, um usuário de integração dedicado que só pode gravar na tabela Incident). Não desative a autenticação.
Testar e validar
Teste sem avançar o ponteiro: no Pull, adicione
?dry-run=trueao final deaxur.feed.url. Você recebe sempre os mesmos tickets e nada se perde.Execute o job manualmente: abra o Scheduled Job → Execute Now.
Confira os incidentes em Incident › All, filtrando por Correlation ID não vazio.
Execute novamente. Graças ao upsert, o número de incidentes não deve aumentar.
Verifique se há erros em System Logs › Errors (mensagens que começam com
Axur feed:).Tudo certo? Remova o
?dry-run=truepara que o ponteiro comece a avançar.
Dica
Valide em uma instância de subprodução ou de desenvolvimento antes de ativar em produção.
Limitações e checklist
Integração nativa | Com Feeds |
| ✅ Coberto (data do evento First detection ou Any detection) |
Campos | ✅ Mesmo formato, montado pelo script |
Somente novas detecções | ✅ E mais: filtros por tipo, incidente, takedown, qualquer atualização… |
Checklist de go-live
Feed criado na Plataforma Axur com a data do evento e os filtros corretos
Script Include
AxurFeedMappercriadoTabela
TYPE_LABELSatualizada com os tipos que você usaPull: properties
axur.feed.urleaxur.feed.api_keycriadas (com leitura restrita)Pull: Scheduled Job ativo · Push: endpoint cadastrado no feed
Testado com
?dry-run=true, sem duplicidades?dry-run=trueremovido






