Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V1.6.0 #28

Merged
merged 3 commits into from
Apr 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,19 @@ Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how
### Fixed


---

## [1.6.0] - (04-03-2024)

### Fixed

- [Bug] Missing "add server" from "bind serviceGroup" reference
- Bug when config is missing title information with code version
- defaults to v13.0
- Bug when config is missing hostname (should use filename instead)
- Moved conversion codeLense from preview to main
- added test for serviceGroup abstraction

---

## [1.5.0] - (03-25-2024)
Expand Down
Binary file modified f5_flipper_test.tgz
Binary file not shown.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"displayName": "F5 Flipper",
"description": "Breaking down Citrix NetScaler ADC configs",
"publisher": "F5DevCentral",
"version": "1.5.0",
"version": "1.6.0",
"keywords": [
"F5",
"F5Networks",
Expand Down
21 changes: 16 additions & 5 deletions src/CitrixADC.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ export default class ADC extends EventEmitter {
* hostname of the source device
*/
public hostname: string | undefined;
/**
* input file name
*/
public inputFile: string;
/**
* input file type (.conf/.tgz)
*/
Expand Down Expand Up @@ -76,6 +80,9 @@ export default class ADC extends EventEmitter {
// capture incoming file type
this.inputFileType = path.parse(file).ext;

// capture input file name
this.inputFile = path.parse(file).name;

const parseConfPromises: any[] = [];
const parseStatPromises: any[] = [];
const unPacker = new UnPacker();
Expand Down Expand Up @@ -136,9 +143,11 @@ export default class ADC extends EventEmitter {
await parseAdcConfArrays(config, this.configObjectArry, this.rx!)

// get hostname from configObjectArry, assign to parent class for easy access
if (this.configObjectArry.set?.ns?.hostName.length > 0) {
if (this.configObjectArry.set?.ns?.hostName) {
// there should always be only one in this array
this.hostname = this.configObjectArry.set.ns.hostName[0];
} else {
this.hostname = this.inputFile;
}

// gather stats on the number of different objects found (vservers/monitors/policies)
Expand All @@ -161,8 +170,6 @@ export default class ADC extends EventEmitter {

// get adc version
[this.adcVersion, this.adcBuild] = this.getAdcVersion(x.content, rex.adcVersionBaseReg);

intLogger.info(`Recieved .conf file of version: ${this.adcVersion}`)

// assign regex tree for particular version
this.rx = rex.get(this.adcVersion)
Expand Down Expand Up @@ -288,12 +295,16 @@ export default class ADC extends EventEmitter {
if (version) {
//found adc version, grab build (split off first line, then split build by spaces)
const build = config.split('\n')[0].split(' ')[2]

intLogger.info(`Recieved .conf file of version: ${this.adcVersion}`)

// return details
return [version[1], build];
} else {
const msg = 'citrix adc/ns version not detected -> meaning this probably is not an ns.conf'
const msg = 'citrix adc/ns version not detected, defaulting to v13.0'
intLogger.error(msg)
throw new Error(msg)
return ['13.0', '000'];
// throw new Error(msg)
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/codeLens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export class NsCodeLensProvider implements CodeLensProvider {
)
);

} else if(document.fileName === 'app.ns.json' && ext.settings.preview) {
} else if(document.fileName === 'app.ns.json') {
// if document.name === 'app.ns.conf'

// find the editor -> get first line of text and abstract the appName
Expand Down
84 changes: 48 additions & 36 deletions src/digLbVserver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export async function digLbVserver(coa: AdcConfObj, rx: AdcRegExTree) {

const apps: AdcApp[] = [];

if(!coa.add?.lb?.vserver) return apps;
if (!coa.add?.lb?.vserver) return apps;

await Promise.all(coa.add?.lb?.vserver?.map(vServ => {
const parent = 'add lb vserver';
Expand Down Expand Up @@ -67,29 +67,32 @@ export async function digLbVserver(coa: AdcConfObj, rx: AdcRegExTree) {
return logger.error(`regex "${rx.parents[parent]}" - failed for line "${originalString}"`);
}

// todo: need to see if this references a "add service" or "add serviceGroup"

if (!app.bindings) app.bindings = {};
if (rxMatch.groups?.service) {

const serviceName = rxMatch.groups?.service;
// app.bindings.service.push(rxMatch.groups.service)

// dig service details
coa.add?.service?.filter(s => s.startsWith(serviceName))
.forEach(async x => {
const parent = 'add service';
const originalString = parent + ' ' + x;
app.lines.push(originalString);
const rxMatch = x.match(rx.parents[parent])
const opts = parseNsOptions(rxMatch.groups?.opts, rx);
if (!rxMatch) {
/* istanbul ignore next */
return logger.error(`regex "${rx.parents[parent]}" - failed for line "${originalString}"`);
}
// also get server reference under 'add server <name>'
if(rxMatch.groups.server) {

// dig server from serviceGroup server reference
await digServer(rxMatch.groups.server, app, coa, rx)
// dig service details -> do we have a service with this name?
const serviceD = coa.add?.service?.filter(s => serviceName)[0]
if (serviceD) {
// this should only ever find one
const parent = 'add service';
const originalString = parent + ' ' + serviceD;
app.lines.push(originalString);
const rxMatch = serviceD.match(rx.parents[parent])
const opts = parseNsOptions(rxMatch.groups?.opts, rx);
if (!rxMatch) {
/* istanbul ignore next */
return logger.error(`regex "${rx.parents[parent]}" - failed for line "${originalString}"`);
}
// also get server reference under 'add server <name>'
if (rxMatch.groups.server) {

// dig server from serviceGroup server reference
await digServer(rxMatch.groups.server, app, coa, rx)
.then(i => {
if (i) {
// rxMatch.groups.server.splice(1, 0, i)
Expand All @@ -103,25 +106,25 @@ export async function digLbVserver(coa: AdcConfObj, rx: AdcRegExTree) {
// port: memberRef[2]
// })
})
}
}

// if we have service details create array to put them
if (!app.bindings.service) {
app.bindings.service = [];
}
// if we have service details create array to put them
if (!app.bindings.service) {
app.bindings.service = [];
}

// push service details to app config
app.bindings.service.push({
name: serviceName,
protocol: rxMatch.groups.protocol,
port: rxMatch.groups.port,
server: rxMatch.groups.server,
address: rxMatch.groups.address,
opts
})
// push service details to app config
app.bindings.service.push({
name: serviceName,
protocol: rxMatch.groups.protocol,
port: rxMatch.groups.port,
server: rxMatch.groups.server,
address: rxMatch.groups.address,
opts
})


})
}

// dig serviceGroup details
await digServiceGroup(serviceName, app, coa, rx)
Expand Down Expand Up @@ -313,10 +316,18 @@ export async function digSslBinding(app: AdcApp, obj: AdcConfObj, rx: AdcRegExTr

const sslBindObj = []

const appName = app.name;

const appSslVservers = obj.bind?.ssl?.vserver?.filter(s => s.startsWith(appName))

// check ssl bindings
for await (const x of obj.bind?.ssl?.vserver) {
// for await (const x of obj.bind?.ssl?.vserver) {

// if (x.startsWith(app.name)) {
if (appSslVservers.length > 0) {
for await (const x of appSslVservers) {


if (x.startsWith(app.name)) {
const parent = 'bind ssl vserver';
const originalString = parent + ' ' + x;
app.lines.push(originalString);
Expand All @@ -339,9 +350,10 @@ export async function digSslBinding(app: AdcApp, obj: AdcConfObj, rx: AdcRegExTr
})

}
// deepmergeInto(sslBindObj, opts)
}
// deepmergeInto(sslBindObj, opts)
}
// }

if (sslBindObj.length > 0) {
app.bindings.certs = sslBindObj;
Expand Down
2 changes: 1 addition & 1 deletion src/regex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ export class RegExTree {
'set ns hostName': /(?<hostName>[\S ]+)/,
'set gslb vserver': /(?<name>\S+) (?<opts>[\S ]+)/,
'bind service': /(?<opts>[\S ]+)/,
'bind serviceGroup': /(?<name>\S+) ((?<serv>\S+ \d+)|(?<monitor>-monitorName \S+)|(?<opts>[\S ]+))/,
'bind serviceGroup': /(?<name>\S+) ((?<serv>\S+ (\d+|\*))|(?<monitor>-monitorName \S+)|(?<opts>[\S ]+))/,
'bind lb vserver': /(?<name>\S+) ((?<opts>-[\S ]+)|(?<service>[\S]+))/,
'bind cs vserver': /(?<server>\S+) (?<opts>[\S ]+)/,
'bind ssl vserver': /(?<server>\S+) (?<opts>[\S ]+)/,
Expand Down
124 changes: 124 additions & 0 deletions tests/025_serviceGroups.unit.tests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
/*
* Copyright 2020. F5 Networks, Inc. See End User License Agreement ("EULA") for
* license terms. Notwithstanding anything to the contrary in the EULA, Licensee
* may copy and modify this software product for its internal business purposes.
* Further, Licensee may upload, publish and distribute the modified version of
* the software product on devcentral.f5.com.
*/

'use strict';

import assert from 'assert';
import ADC from '../src/CitrixADC'
import { Explosion } from '../src/models';
import { archiveMake } from './archiveBuilder';

const events = [];
let testFile: string;

const parsedFileEvents: any[] = []
const parsedObjEvents: any[] = []

describe('serviceGroup abstraction tests', function () {

let adc: ADC;
let expld: Explosion;
let log;
let err;

before(async function () {
// log test file name - makes it easer for troubleshooting
console.log(' file:', __filename)
testFile = await archiveMake() as string;
// clear the events arrays
parsedFileEvents.length = 0
parsedObjEvents.length = 0
adc = new ADC();

adc.on('parseFile', x => parsedFileEvents.push(x))
adc.on('parseObject', x => parsedObjEvents.push(x))

await adc.loadParseAsync(testFile)
.then(async x => {
await adc.explode()
.then(x => {
expld = x
})
})
.catch(y => {
err = y;
log = adc.logs()
debugger;
})

});

afterEach(function () {
events.length = 0;
})



it(`basic serviceGroup reference`, async () => {

// cs -> bind ssl vserver groot-cs-vsvr -certkeyName star.groot.cer

// get application we are looking for
const app = expld.config.apps?.find(x => x.name === 'skree1_vip_RDP')

// get the serviceGroup details
const appServiceGroup = app!.bindings!.serviceGroup![0]

assert.deepStrictEqual(appServiceGroup, {
name: "skree1_servicegroup_RDP",
protocol: "RDP",
"-maxClient": "0",
"-maxReq": "0",
"-cip": "DISABLED",
"-usip": "YES",
"-useproxyport": "YES",
"-cltTimeout": "9000",
"-svrTimeout": "9000",
"-CKA": "NO",
"-TCPB": "NO",
"-CMP": "NO",
servers: [
{
name: "skree1server02",
address: "10.10.10.8",
port: "*",
},
{
name: "skree1server01",
address: "10.10.10.7",
port: "*",
},
],
})

})


// it(`lb ssl cert binding`, async () => {

// // lb -> bind ssl vserver starlord_offload_lb_vs -certkeyName starlord.galaxy.io_cert

// const app = expld.config.apps?.find(x => x.name === 'starlord_offload_lb_vs');

// // get the cert details
// const appCert = app?.bindings?.certs![0]

// assert.deepStrictEqual(appCert, {
// "-cert": "foo.crt",
// "-key": "foo.key",
// profileName: "starlord.galaxy.io_cert",
// })
// })

// // it(`vpn? ssl cert binding`, async () => {

// // // and ssl cert binding? like a service?
// // })

});
Loading