PolicyLogic Examples

All examples should be used as references. Depending on the NAS, you may need to add or remove AVPs in your implementation. 

Disconnect-Message OR Change-Of-Authorization

function getExistingSession() {
  // Query for existing active entries (assuming that Accounting records stored on the "sessions" colllection)
  var session = queryOne("Calling-Station-Id", radius.request['Calling-Station-Id'], "sessions");
  // Check for result
  if (session){
    // Store NAS-IP-Address for Disconnect or Change-Of-Authorization requests
    var nas_ip = session['NAS-IP-Address'];
    if (nas_ip) {
      sendDM(nas_ip);
      // sendCoA(coa_avps);
    }
  // Entry is not found
  } else {
  // Create Reply-Message
  radius.reply['Reply-Message'] = "No active sessions found";
  // Return fail response
  fail();
  }

}

function sendDM(nas_ip) {
  // Before building DM or CoA request, save existing AVP's
  // into "old_request" group
  radius.old_request = radius.request 
  // Clean "request" group
  radius.request = {};
  // Add Calling-Station-Id to "request" group
  radius.request['Calling-Station-Id'] = radius.old_request['Calling-Station-Id'];
  // Send Disconnect-Request
    var r = RadiusRequest("DM-REQUEST", nas_ip, 3799, "3000");
  // Return result of request
  return r;
}

function sendCoA(avps) {
  // Before building DM or CoA request, save existing AVP's
  // into "old_request" group
  radius.old_request = radius.request 
  // Clean "request" group
  radius.request = {};
  // Add Calling-Station-Id to "request" group
  radius.request['Calling-Station-Id'] = radius.old_request['Calling-Station-Id'];
  // Send Disconnect-Request
    var r = RadiusRequest("COA-REQUEST", nas_ip, 3799, "3000");
  // Return result of request
  return r;
}

Send PPSK (DPSK) response with dynamic vlan.

// Check for PPSK Auth
    //
    function checkPPSK() {

      if (radius.request['User-Name'] == radius.request['User-Password']) {
        var dbResult = queryMany("Called-Station-Id", radius.request['Called-Station-Id'], "ppsk");
        if (dbResult) {
          for (i = 0; i <= dbResult.length - 1; i++) {
            radius.reply['tag'][i] = {};
            radius.reply['tag'][i]['Tunnel-Password'] = dbResult[i]['Tunnel-Password'];
            radius.reply['tag'][i]['Tunnel-Private-Group-Id'] = dbResult[i]['Tunnel-Private-Group-Id'];
            radius.reply['tag'][i]['Tunnel-Type'] = dbResult[i]['Tunnel-Type'];
            radius.reply['tag'][i]['Tunnel-Medium-Type'] = dbResult[i]['Tunnel-Medium-Type'];
          }

          radius.reply['Reply-Message'] = "Success Auth";

          //
          // Store request in the "Session" collection with TTL 1hr
          //
          // function: upsertEntry(collectionName, object, TTL, indexName, indexValue);
          //      
          upsertEntry("sessions", radius.request, 3600, "Calling-Station-Id", radius.request['Calling-Station-Id']);

          success();
          return true;
        }
        return false;
      }
    }

Send Radius request to different AAA (proxy the request)

//
// Determine whether the request has to be proxied to a partner network.
// getProxySettings(realm_or_identity) is internal function.
//
function proxyCheck() {
  const proxySettings = getProxySettings(radius.user['Realm']);
    if (proxySettings) {
        // Parameters for this realm is exists on the "config" collections. 
        const proxyInstance = new RadiusProxy();

        // Or set parameters manually.
        // proxyInstance.code = radius.code;
        // proxyInstance.dst = "1.2.3.4"; //radius.proxy['Proxy-Address'] = "1.2.3.4";
        // proxyInstance.dst_port = "1812"; // radius.proxy['Proxy-Address-Port'] = "1812";
        // proxyInstance.timeout = "2000";
        // proxyInstance.name = "MY_PROXY_PROVIDER";
        // proxyInstance.timeout_unreachable = "10000";
        // proxyInstance.balance_mode = "round-robin";
        // proxyInstance.dpd = "false";

        var  proxyResult = proxyInstance.send();
        if (proxyResult)
          return proxyResult;
    }
    return false;
}

RFC5580

    radius.request['Location-Capable'] = "NAS-Location";
    radius.request['Location-Data'] = {
      'Index': '1',
      'Location': {
        'city': 'Chicago',
        'state': 'IL',
        'zip': '60603',
        'nam': 'NAM_Value',
        'plc': 'PLC_Value',
        'loc': 'LOC_Value',
        'lmk': 'LMK_Value'
      },
      'Country': 'US'
    };

    radius.request['Location-Information'] = {
      'Index': '1',
      'Code': '0',
      'Entity': '1',
      'Sighting-Time': convertToNTP64(Date.now()),
      'Time-To-Live': convertToNTP64(Date.now() + (43200*1000)),
      'Method': 'Manual'
    }

Call function in the new thread or parallel

function acct_handler() {

    //
    // To avoid delaying the Accounting-Response, execute the Session update function in parallel.
    // So first return Acct-Response
    success();
    //
    // and then insert / update "sessions" collection
    //
    runParallel('acct()', 500);
  }

  //
  // Update sessions collection.
  //
  function acct() {
    // function: upsertEntry(collectionName, object, TTL, indexName, indexValue);
    upsertEntry("sessions", radius.request, 3600, "Calling-Station-Id", radius.request['Calling-Station-Id']);
  }

Issue EAP-TLS certificate by calling SpherAAA API

function issue_cert() {
  var ca_id = "6461706ef4befabdc81e6d19";
  var cert_type = "pem";
  var url = "https://aaa.spheralogic.com/api/pki/gen/?ca_id="+ca_id+"&cert_type="+cert_type

  var headers = {}
  headers["accept"] = "application/json"
  headers["Content-Type"] = "application/json"
  headers["Authorization"] = "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...."

  var httpclient = new HTTPClient();
  httpclient.url = url;
  httpclient.headers = headers;
  httpclient.method = "POST";

  var data = {
    "ct": "US",
    "st": "NY",
    "city": "NewYork",
    "o": "Company",
    "ou": "USER_NAME/ID/Department_Name",
    "cn": "anonymous@company.com",
    "days": "365",
    "passphrase": "nopass",
    "comment": "EAP-TLS Client Cert",
    "email_send_as_file": false,
    "email_send_as_url": false,
    "ssid": "nossid"
  };
  httpclient.data = JSON.stringify(data);

  try {
    var response = httpclient.send();
    log("httpclient result: " + JSON.stringify(response));
  } catch (e) {
    log("Recived error: " + e.toString());
  }
}

Insert data to the Elasticsearch or OpenSearch (HTTP Basic Auth)

function ops_insert() {
  var url = "https://opensearch.domain.com:9200/my_index/_doc"
  var headers = {}
  var auth = Base64.encode("user:password")
  headers["Content-Type"] = "application/json"
  headers["Authorization"] = "Basic "+ auth
  var httpclient = new HTTPClient();
  httpclient.url = url;
  httpclient.headers = headers;
  httpclient.method = "POST";
  httpclient.disableSslVerification = false; 
  var data = {"sourcetype":"auth", "data":radius}
  //var data = {"sourcetype":"acct", "data":radius}
  httpclient.data = JSON.stringify(data);

  try {
    var response = httpclient.send();
    log("httpclient result: " + JSON.stringify(response));
  } catch (e) {
    log("Recived error: " + e.toString());
  }
}