Add PA Host OK

This commit is contained in:
Douglas Barone 2021-01-14 15:12:37 -04:00
parent 681b83188b
commit 80f81b4013
7 changed files with 73 additions and 39 deletions

View File

@ -20,6 +20,7 @@
"date-fns": "^2.16.1", "date-fns": "^2.16.1",
"dotenv": "^8.2.0", "dotenv": "^8.2.0",
"graphql": "^14.6.0", "graphql": "^14.6.0",
"ip": "^1.1.5",
"jsonwebtoken": "^8.5.1", "jsonwebtoken": "^8.5.1",
"ldapjs": "^2.2.1", "ldapjs": "^2.2.1",
"node-cron": "^2.0.3", "node-cron": "^2.0.3",
@ -5857,6 +5858,11 @@
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
"integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw=="
}, },
"node_modules/ip": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
"integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo="
},
"node_modules/ipaddr.js": { "node_modules/ipaddr.js": {
"version": "1.9.1", "version": "1.9.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
@ -13822,6 +13828,11 @@
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
"integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw=="
}, },
"ip": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
"integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo="
},
"ipaddr.js": { "ipaddr.js": {
"version": "1.9.1", "version": "1.9.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",

View File

@ -46,6 +46,7 @@
"date-fns": "^2.16.1", "date-fns": "^2.16.1",
"dotenv": "^8.2.0", "dotenv": "^8.2.0",
"graphql": "^14.6.0", "graphql": "^14.6.0",
"ip": "^1.1.5",
"jsonwebtoken": "^8.5.1", "jsonwebtoken": "^8.5.1",
"ldapjs": "^2.2.1", "ldapjs": "^2.2.1",
"node-cron": "^2.0.3", "node-cron": "^2.0.3",

View File

@ -1,8 +1,8 @@
-- CreateTable -- CreateTable
CREATE TABLE "PanOS" ( CREATE TABLE "PAHost" (
"id" SERIAL, "id" SERIAL,
"cidr" TEXT NOT NULL,
"description" TEXT NOT NULL, "description" TEXT NOT NULL,
"ip" TEXT NOT NULL,
"encryptedKey" TEXT NOT NULL, "encryptedKey" TEXT NOT NULL,
"note" TEXT, "note" TEXT,
"user" TEXT NOT NULL, "user" TEXT NOT NULL,

View File

@ -123,11 +123,11 @@ model Statistic {
onlineWifiDevices Int onlineWifiDevices Int
} }
model PanOS { model PAHost {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
user String user String
description String description String
ip String @unique cidr String @unique
encryptedKey String encryptedKey String
note String? note String?
createdAt DateTime @default(now()) createdAt DateTime @default(now())

View File

@ -1,14 +1,18 @@
// Ref.: https://docs.paloaltonetworks.com/pan-os/9-1/pan-os-panorama-api/pan-os-xml-api-request-types/apply-user-id-mapping-and-populate-dynamic-address-groups-api.html // Ref.: https://docs.paloaltonetworks.com/pan-os/9-1/pan-os-panorama-api/pan-os-xml-api-request-types/apply-user-id-mapping-and-populate-dynamic-address-groups-api.html
import axios from 'axios' import axios from 'axios'
import prisma from '../prisma'
import https from 'https' import https from 'https'
import { subMinutes } from 'date-fns' import { isIPv4 } from 'net'
import qs from 'qs' import qs from 'qs'
import { add, subMinutes } from 'date-fns'
import { logError, logSuccess } from './logger' import { logError, logSuccess } from './logger'
import { AES, enc } from 'crypto-js' import { AES, enc } from 'crypto-js'
import ip from 'ip'
import prisma from '../prisma'
const TIMEOUT_IN_MINUTES = '3' const TIMEOUT_IN_MINUTES = '3'
const CIDR_RE = /^([0-9]{1,3}\.){3}[0-9]{1,3}(\/([0-9]|[1-2][0-9]|3[0-2]))?$/
const httpsAgent = new https.Agent({ const httpsAgent = new https.Agent({
rejectUnauthorized: false rejectUnauthorized: false
@ -92,49 +96,67 @@ async function updateUserIdMappings() {
} }
} }
async function getUserKey({ ip, user, password }) { async function getUserKey({ ipAddr, user, password }) {
try {
const result = await axios({ const result = await axios({
url: `https://${ip}/api/`, url: `https://${ipAddr}/api/`,
method: 'POST', method: 'POST',
params: { type: 'keygen', user, password }, params: { type: 'keygen', user, password },
httpsAgent httpsAgent
}) })
return result.data.split('<key>')[1].split('</key>')[0] return result.data.split('<key>')[1].split('</key>')[0]
} catch (e) {
throw new Error(e.message)
}
} }
async function addHost({ ip, user, password, description, note }) { function encryptKey(key) {
return AES.encrypt(key, process.env.CRYPT_SECRET).toString()
}
function decryptKey(encryptedKey) {
return AES.decrypt(encryptedKey, process.env.CRYPT_SECRET).toString(enc.Utf8)
}
async function addHost({ cidr, user, password, description, note }) {
try { try {
const key = await getUserKey({ ip, user, password }) if (!CIDR_RE.test(cidr)) throw new Error('Este não é um CIDR válido')
const encryptedKey = AES.encrypt(key, process.env.CRYPT_SECRET).toString() const ipAddr = cidr.split('/')[0]
// const decryptedKey = AES.decrypt( if (!isIPv4(ipAddr)) throw new Error('Este não é um IPv4 válido')
// encryptedKey,
// process.env.CRYPT_SECRET
// ).toString(enc.Utf8)
const host = await prisma.panOS.create({ const net = ip.cidrSubnet(cidr)
data: {
ip, if (net.subnetMaskLength > 32 || net.networkAddress == '0.0.0.0')
throw new Error('Esta não é uma combinação de IP/máscara IPv4 válida')
const key = await getUserKey({ ipAddr, user, password })
const encryptedKey = encryptKey(key)
const pAHost = {
cidr,
encryptedKey, encryptedKey,
user, user,
description, description,
note note
} }
const host = await prisma.pAHost.upsert({
where: { cidr: cidr },
create: pAHost,
update: pAHost
}) })
return { return {
...host, ...host,
key: `${key.slice( key: `${key.slice(0, 5)}`
0,
8
)}************************************************************************************************`
} }
} catch (e) { } catch (e) {
logError({ logError({
message: `Não foi possível adicionar o host ${ip}.`, message: `Não foi possível adicionar o host ${cidr}. ${e?.message}`,
data: e.message,
tags: ['paloalto'] tags: ['paloalto']
}) })
throw new Error(e.message) throw new Error(e.message)

View File

@ -46,8 +46,8 @@ const Mutation = {
return updateUserIdMappings() return updateUserIdMappings()
}, },
async addPAHost(_, { data: { ip, user, password, description, note } }) { async addPAHost(_, { data: { cidr, user, password, description, note } }) {
return addHost({ ip, user, password, description, note }) return addHost({ cidr, user, password, description, note })
} }
} }

View File

@ -260,7 +260,7 @@ const typeDefs = gql`
type PAHost { type PAHost {
id: ID! id: ID!
description: String description: String
ip: String cidr: String
key: String key: String
note: String note: String
createdAt: String createdAt: String
@ -303,7 +303,7 @@ const typeDefs = gql`
} }
input AddPAHostInput { input AddPAHostInput {
ip: String! cidr: String!
user: String! user: String!
password: String! password: String!
description: String! description: String!