Add PA Host OK
This commit is contained in:
parent
681b83188b
commit
80f81b4013
11
server/package-lock.json
generated
11
server/package-lock.json
generated
|
@ -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",
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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 }) {
|
||||||
const result = await axios({
|
try {
|
||||||
url: `https://${ip}/api/`,
|
const result = await axios({
|
||||||
method: 'POST',
|
url: `https://${ipAddr}/api/`,
|
||||||
params: { type: 'keygen', user, password },
|
method: 'POST',
|
||||||
httpsAgent
|
params: { type: 'keygen', user, password },
|
||||||
})
|
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')
|
||||||
encryptedKey,
|
throw new Error('Esta não é uma combinação de IP/máscara IPv4 válida')
|
||||||
user,
|
|
||||||
description,
|
const key = await getUserKey({ ipAddr, user, password })
|
||||||
note
|
|
||||||
}
|
const encryptedKey = encryptKey(key)
|
||||||
|
|
||||||
|
const pAHost = {
|
||||||
|
cidr,
|
||||||
|
encryptedKey,
|
||||||
|
user,
|
||||||
|
description,
|
||||||
|
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)
|
||||||
|
|
|
@ -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 })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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!
|
||||||
|
|
Loading…
Reference in New Issue
Block a user