For more information regarding the security incident at F5, the actions we are taking to address it, and our ongoing efforts to protect our customers, click here.

Forum Discussion

yamashin55's avatar
Jun 27, 2020

How to update data-group using iRules LX

I created the following code with iRules LX.

The code does not work properly.

 

The log is output up to "console.log('getDataGroup start');".

 

Does anyone know how to check if icontrol is successfully connecting to BIG-IP?

List() of iControl doesn't seem to work properly.

 

 

iRule

---------------------------------------------

when ACCESS_POLICY_AGENT_EVENT {
    switch [ACCESS::policy agent_id] {
        ....
        ....
 
 
        "add_user" {
            set ilx_handle [ILX::init "f5_mfa_plugin" "f5_mfa_extension"]
            set user [ACCESS::session data get session.logon.last.username]
            set sec [ACCESS::session data get session.custom.otp.secret]
            log local0.info "INFO: f5_mfa.tcl - user:$user secret:$sec"
            if {[catch {set result [ILX::call $ilx_handle -timeout 10000 addUser $user $sec]} result]} {
                log local0.error "ERROR: f5_mfa.tcl - Client - [IP::client_addr], ILX failure: $result"
                return
            }
            log local0.info "user:$result"
        }
    }
}

 

iRuleLX: index.js

---------------------------------------------

var f5 = require('f5-nodejs');
var User = require('./f5_user').User;
var ilx = new f5.ILXServer();
ilx.listen();
ilx.addMethod('addUser', function(req,res) {
  console.log("START: addMethod", req.params()[0], req.params()[1]);
  var user = new User(req.params()[0]);
  user.secret = req.params()[1];
  user.add(function(response) {
    res.reply(response);
  });
});

 

 

iRuleLX: user.js

---------------------------------------------

var dg = require('./f5_data_group');
 
 
exports.User = function(name) {
	var self = this;
 
 
	self.name = name;
	self.enrolled = false;
	self.secret = "";
 
 
	this.methods = {};
 
 
	/**
	* add a user to the data group
	*
	* @return {Boolean} user added
	*/
	this.add = function(callback){
	    console.log('user.add start');
		if(typeof this.secret === undefined) {
			console.error('you have to set a secret before calling add');
			callback(false);
		}
		console.log(self.name, self.secret);
		dg.put(self.name, self.secret, function(status) {
			if(status) {
				self.enrolled = true;
			}
			callback(true);
		});
	};
 
 
};

 

 

iRuleLX: f5_data_group.js

---------------------------------------------

var iControl = require('icontrol');
var util = require('util');
 
 
// set API connection and authentication
var bigip = new iControl({
  host: '127.0.0.1',
  proto: 'https',
  port: '443',
  username: 'admin',
  pass: 'admin',
  strict: 'true',
  debug: 'true'
});
 
 
var dgPath = '/ltm/data-group/internal/~Common~token_keys';
var exports = module.exports = {};
 
 
//ignore self signed certificate
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
bigip.strict = false;
 
 
 
 
/**
 * return dta group
 *
 * @param {Function} callback
 */
exports.getDataGroup = function(callback) {
  console.log('getDataGroup start');
  bigip.list(dgPath, function(err, res) {
    callback(res);
  });
};
 
 
/**
 * add key:data pair to the data group
 *
 * @param {String} key
 * @param {String} data
 * @param {Function} callback
 */
exports.put = function (key, data, callback) {
  console.log('put data-group key:', key, 'data:', data);
  exports.getDataGroup(function(res) {
      // add new user to the object stack
      // make sure the data group isn't empty
      if (typeof res.records !== 'undefined') {
        // make sure user doesn't already exist
        var isset = false;
        for(var record in res.records) {
          if(res.records[record].name == key) {
            // user exists, update secret
            res.records[record].data = data;
            isset = true;
            break;
          }
        }
        if(!isset) {
          // user doesn't exist, add them
          res.records.push({"name": key, "data": data});
        }
      } else {
        res.records = [{"name": key, "data": data}];
      }
      // populate the arguments for the http post
      args = {
        data: { records: res.records },
        header: { "Content-Type": "application/json" }
      };
      bigip.modify(dgPath, args, function(err, res) {
        callback(data);
      });
    });
};

 

3 Replies