Skip to content
Snippets Groups Projects
Commit dc0f00a8 authored by Peter Rotich's avatar Peter Rotich
Browse files

Allow IP address to have multiple keys. Add specific permission for API services

parent 9c77432a
Branches
Tags
No related merge requests found
......@@ -22,7 +22,9 @@ class TicketController extends ApiController {
}
function create($format) {
$this->requireApiKey();
if(!($key=$this->getApiKey()) || !$key->canCreateTickets())
Http::response(401, 'API key not authorized');
# Parse request body
$data = $this->getRequest($format);
......
......@@ -17,102 +17,115 @@ class API {
var $id;
var $info;
var $ht;
function API($id){
$this->id=0;
function API($id) {
$this->id = 0;
$this->load($id);
}
function load($id) {
function load($id=0) {
if(!$id && !($id=$this->getId()))
return false;
$sql='SELECT * FROM '.API_KEY_TABLE.' WHERE id='.db_input($id);
if(($res=db_query($sql)) && db_num_rows($res)) {
$info=db_fetch_array($res);
$this->id=$info['id'];
$this->info=$info;
return true;
}
return false;
if(!($res=db_query($sql)) || !db_num_rows($res))
return false;
$this->ht = db_fetch_array($res);
$this->id = $this->ht['id'];
return true;
}
function reload() {
return $this->load($this->getId());
return $this->load();
}
function getId(){
function getId() {
return $this->id;
}
function getKey(){
return $this->info['apikey'];
function getKey() {
return $this->ht['apikey'];
}
function getIPAddr(){
return $this->info['ipaddr'];
function getIPAddr() {
return $this->ht['ipaddr'];
}
function getNotes(){
return $this->info['notes'];
function getNotes() {
return $this->ht['notes'];
}
function isActive(){
return ($this->info['isactive']);
function getHashtable() {
return $this->ht;
}
function update($vars,&$errors){
if(API::save($this->getId(),$vars,$errors)){
$this->reload();
return true;
}
function isActive() {
return ($this->ht['isactive']);
}
function canCreateTickets() {
return ($this->ht['can_create_tickets']);
}
function update($vars, &$errors) {
if(!API::save($this->getId(), $vars, $errors))
return false;
return false;
$this->reload();
return true;
}
function delete(){
function delete() {
$sql='DELETE FROM '.API_KEY_TABLE.' WHERE id='.db_input($this->getId()).' LIMIT 1';
return (db_query($sql) && ($num=db_affected_rows()));
}
/** Static functions **/
function add($vars,&$errors){
return API::save(0,$vars,$errors);
function add($vars, &$errors) {
return API::save(0, $vars, $errors);
}
function validate($key,$ip){
$sql='SELECT id FROM '.API_KEY_TABLE.' WHERE ipaddr='.db_input($ip).' AND apikey='.db_input($key);
return (($res=db_query($sql)) && db_num_rows($res));
function validate($key, $ip) {
return ($key && $ip && self::getIdByKey($key, $ip));
}
function getKeyByIPAddr($ip){
function getIdByKey($key, $ip='') {
$sql='SELECT apikey FROM '.API_KEY_TABLE.' WHERE ipaddr='.db_input($ip);
$sql='SELECT id FROM '.API_KEY_TABLE.' WHERE apikey='.db_input($key);
if($ip)
$sql.=' AND ipaddr='.db_input($ip);
if(($res=db_query($sql)) && db_num_rows($res))
list($key)=db_fetch_row($res);
list($id) = db_insert_id();
return $key;
return $id;
}
function lookup($id){
return ($id && is_numeric($id) && ($k= new API($id)) && $k->getId()==$id)?$k:null;
function lookupByKey($key, $ip='') {
return self::lookup(self::getIdByKey($key, $ip));
}
function save($id,$vars,&$errors){
function lookup($id) {
return ($id && is_numeric($id) && ($k= new API($id)) && $k->getId()==$id)?$k:null;
}
if(!$id) {
if(!$vars['ipaddr'] || !Validator::is_ip($vars['ipaddr']))
$errors['ipaddr']='Valid IP required';
elseif(API::getKeyByIPAddr($vars['ipaddr']))
$errors['ipaddr']='API key for the IP already exists';
}
function save($id, $vars, &$errors) {
if(!$id && (!$vars['ipaddr'] || !Validator::is_ip($vars['ipaddr'])))
$errors['ipaddr'] = 'Valid IP required';
if($errors) return false;
$sql=' updated=NOW() '.
',isactive='.db_input($vars['isactive']).
',notes='.db_input($vars['notes']);
$sql=' updated=NOW() '
.',isactive='.db_input($vars['isactive'])
.',can_create_tickets='.db_input($vars['can_create_tickets'])
.',notes='.db_input($vars['notes']);
if($id) {
$sql='UPDATE '.API_KEY_TABLE.' SET '.$sql.' WHERE id='.db_input($id);
......@@ -120,14 +133,17 @@ class API {
return true;
$errors['err']='Unable to update API key. Internal error occurred';
}else{
$sql='INSERT INTO '.API_KEY_TABLE.' SET '.$sql.',created=NOW() '.
',ipaddr='.db_input($vars['ipaddr']).
',apikey='.db_input(strtoupper(md5(time().$vars['ipaddr'].md5(Misc::randcode(16)))));
} else {
$sql='INSERT INTO '.API_KEY_TABLE.' SET '.$sql
.',created=NOW() '
.',ipaddr='.db_input($vars['ipaddr'])
.',apikey='.db_input(strtoupper(md5(time().$vars['ipaddr'].md5(Misc::randcode(16)))));
if(db_query($sql) && ($id=db_insert_id()))
return $id;
$errors['err']='Unable to add API key. Internal error';
$errors['err']='Unable to add API key. Try again!';
}
return false;
......@@ -141,16 +157,24 @@ class API {
* API request.
*/
class ApiController {
function requireApiKey() {
# Validate the API key -- required to be sent via the X-API-Key
# header
if (!isset($_SERVER['HTTP_X_API_KEY']))
if (!isset($_SERVER['HTTP_X_API_KEY']) || !isset($_SERVER['REMOTE_ADDR']))
Http::response(403, "API key required");
else if (!Api::validate($_SERVER['HTTP_X_API_KEY'],
$_SERVER['REMOTE_ADDR']))
Http::response(401,
"API key not found or source IP not authorized");
elseif (!($key=API::lookupByKey($_SERVER['HTTP_X_API_KEY'], $_SERVER['REMOTE_ADDR']))
|| !$key->isActive()
|| $key->getIP()!=$_SERVER['REMOTE_ADDR'])
Http::response(401, "API key not found/active or source IP not authorized");
return $key;
}
function getApiKey() {
return $this->requireApiKey();
}
/**
* Retrieves the body of the API request and converts it to a common
* hashtable. For JSON formats, this is mostly a noop, the conversion
......@@ -243,7 +267,7 @@ class ApiJsonDataParser extends JsonDataParser {
return $current;
foreach ($current as $key=>&$value) {
if ($key == "phone") {
list($value,$current["phone_ext"])
list($value, $current["phone_ext"])
= explode("X", strtoupper($value), 2);
} else if ($key == "alert") {
$value = (bool)$value;
......
......@@ -6,9 +6,7 @@ if($api && $_REQUEST['a']!='add'){
$title='Update API Key';
$action='update';
$submit_text='Save Changes';
$info['id']=$api->getId();
$info['isactive']=$api->isActive()?1:0;
$info['notes']=$api->getNotes();
$info=$api->getHashtable();
$qstr.='&id='.$api->getId();
}else {
$title='Add New API Key';
......@@ -30,13 +28,13 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
<tr>
<th colspan="2">
<h4><?php echo $title; ?></h4>
<em>API Key is autogenerated and unique per IP address.</em>
<em>API Key is auto-generated. Delete and re-add to change the key.</em>
</th>
</tr>
</thead>
<tbody>
<tr>
<td width="180" class="required">
<td width="150" class="required">
Status:
</td>
<td>
......@@ -47,7 +45,7 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
</tr>
<?php if($api){ ?>
<tr>
<td width="180">
<td width="150">
IP Address:
</td>
<td>
......@@ -55,14 +53,14 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
</td>
</tr>
<tr>
<td width="180">
<td width="150">
API Key:
</td>
<td><?php echo $api->getKey(); ?> &nbsp;&nbsp;<em>(Delete and re-add to change the key)</em></td>
<td><?php echo $api->getKey(); ?> &nbsp;</td>
</tr>
<?php }else{ ?>
<tr>
<td width="180" class="required">
<td width="150" class="required">
IP Address:
</td>
<td>
......@@ -73,16 +71,13 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
<?php } ?>
<tr>
<th colspan="2">
<em><strong>Enabled Services:</strong>: Check applicable API services.</em>
<em><strong>Enabled Services:</strong>: Check applicable API services. All active keys can make cron call.</em>
</th>
</tr>
<tr>
<td width="180">
Email piping:
</td>
<td>
<input type="checkbox" name="email_piping" value="1" checked="checked" disabled="disabled" >
<strong>Enable</strong> remote email piping.
<td colspan=2 style="padding-left:5px">
<input type="checkbox" name="can_create_tickets" value="1" <?php echo $info['can_create_tickets']?'checked="checked"':''; ?> >
Can Create Tickets. <em>(XML/JSON/PIPE)</em>
</td>
</tr>
<tr>
......
......@@ -5,7 +5,7 @@ $qstr='';
$sql='SELECT * FROM '.API_KEY_TABLE.' WHERE 1';
$sortOptions=array('key'=>'apikey','status'=>'isactive','ip'=>'ipaddr','date'=>'created','created'=>'created','updated'=>'updated');
$orderWays=array('DESC'=>'DESC','ASC'=>'ASC');
$sort=($_REQUEST['sort'] && $sortOptions[strtolower($_REQUEST['sort'])])?strtolower($_REQUEST['sort']):'date';
$sort=($_REQUEST['sort'] && $sortOptions[strtolower($_REQUEST['sort'])])?strtolower($_REQUEST['sort']):'key';
//Sorting options...
if($sort && $sortOptions[$sort]) {
$order_column =$sortOptions[$sort];
......@@ -54,10 +54,10 @@ else
<thead>
<tr>
<th width="7">&nbsp;</th>
<th width="150" nowrap><a <?php echo $date_sort; ?>href="apikeys.php?<?php echo $qstr; ?>&sort=date">Date Added</a></th>
<th width="320"><a <?php echo $key_sort; ?> href="apikeys.php?<?php echo $qstr; ?>&sort=key">API Key</a></th>
<th width="100"><a <?php echo $status_sort; ?> href="apikeys.php?<?php echo $qstr; ?>&sort=status">Status</a></th>
<th width="120"><a <?php echo $ip_sort; ?> href="apikeys.php?<?php echo $qstr; ?>&sort=ip">IP Addr.</a></th>
<th width="100"><a <?php echo $status_sort; ?> href="apikeys.php?<?php echo $qstr; ?>&sort=status">Status</a></th>
<th width="150" nowrap><a <?php echo $date_sort; ?>href="apikeys.php?<?php echo $qstr; ?>&sort=date">Date Added</a></th>
<th width="150" nowrap><a <?php echo $updated_sort; ?>href="apikeys.php?<?php echo $qstr; ?>&sort=updated">Last Updated</a></th>
</tr>
</thead>
......@@ -75,10 +75,10 @@ else
<td width=7px>
<input type="checkbox" class="ckb" name="ids[]" value="<?php echo $row['id']; ?>"
<?php echo $sel?'checked="checked"':''; ?>> </td>
<td>&nbsp;<?php echo Format::db_date($row['created']); ?></td>
<td>&nbsp;<a href="apikeys.php?id=<?php echo $row['id']; ?>"><?php echo Format::htmlchars($row['apikey']); ?></a></td>
<td><?php echo $row['isactive']?'Active':'<b>Disabled</b>'; ?></td>
<td><?php echo $row['ipaddr']; ?></td>
<td><?php echo $row['isactive']?'Active':'<b>Disabled</b>'; ?></td>
<td>&nbsp;<?php echo Format::db_date($row['created']); ?></td>
<td>&nbsp;<?php echo Format::db_datetime($row['updated']); ?></td>
</tr>
<?php
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment