外部 API の実装例

以下のコード抜粋は、外部 API メソッドを使用した curl での PHP の例を示しています。この例では、ユーザ、デバイス、およびそれら 2 つの間の自動接続ポリシーをプロビジョニングします。API リクエストで にアクセスできるクライアント ソフトウェアを準備するには、
CA Technologies
プロフェッショナル サービスを利用できます。
capamnew
以下のコード抜粋は、外部 API メソッドを使用した curl での PHP の例を示しています。この例では、ユーザ、デバイス、およびそれら 2 つの間の自動接続ポリシーをプロビジョニングします。API リクエストで
Privileged Access Manager
にアクセスできるクライアント ソフトウェアを準備するには、
CA Technologies
プロフェッショナル サービスを利用できます。
<?php
class APIConstants{
    const DEVICE_ENDPOINT_V1 = "/api.php/v1/devices.json";
    const DEVICE_GROUP_ENDPOINT_V1 = "/api.php/v1/devicegroups.json";
    const GET = "GET";
    const POLICIES_ENDPOINT_V1 = "/api.php/v1/policies.json";
    const ROLE_GLOBAL_ADMINISTRATOR = 1;
    const ROLE_STANDARD_USER = 2;
    const ROLE_OPERATIONAL_ADMINISTRATOR = 14;
    const POST = "POST";
    const PUT = "PUT";
    const TWO_DAYS = 172800;
    const USER_ENDPOINT_V1 = "/api.php/v1/users.json";
    const USER_GROUP_ENDPOINT_V1 = "/api.php/v1/userGroups.json";
}
/**
 *
 * This function will make a single request to the API.
 * @param string $apiKey - api key name and password delimited by colon
 * @param string $url - the URL to reach the desired endpoint of the API.
 * For a get may include parameters
 * @param string $postData - JSON encoded set of parameters
 * @param string $httpOperation - GET, POST, PUT, or DELETE
 * @return string -1 for failure, otherwise results of request
 */
function makeAPIRequest($apiKey, $url, $postData = null, $httpOperation) {
     global $debug;
     $httpOperation = strtoupper($httpOperation);
     if(!in_array($httpOperation,array("GET","POST","PUT","DELETE"))){
          return -1;
     }
     /*
         In real code the url could be validated. This is left out as a distraction
          to the point of the cookbook.
     */
     if(!empty($postData) && is_null(json_decode($postData))){
         error_log("Invalid post data " . print_r($postData,true) .
             "\n Post data must be in JSON format.");
         return -1;
     }
     // apiKey must have at least one colon, and not in the first position
     if(strpos($apiKey,":") == 0){
         error_log("Incorrectly formated api key. Key must consist of api key name, a colon, and the api password");
         return -1;
     } 
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);
    curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
    curl_setopt($ch, CURLOPT_USERPWD, $apiKey);
    switch($httpOperation){
        case "GET":
            break;
            case "PUT":
                curl_setopt($ch, CURLOPT_CUSTOMREQUEST,"PUT");
                // absence of break is intentional
        case "POST":
            curl_setopt($ch, CURLOPT_POST, true);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
            curl_setopt($ch, CURLOPT_HTTPHEADER,
                array('Content-Type: application/json','Content-Length: ' . strlen($postData)));
            break;
        case "DELETE":
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
    }
    /*
     * These are useful debug statements
     */
    if($debug){
        echo "XXX: URL = " . $url . PHP_EOL;
        echo "YYY: parameters = " . print_r($postData, true) . PHP_EOL;
        echo "ZZZ: httpOperation = " . $httpOperation . PHP_EOL;
    }
    $data = curl_exec($ch);
    if($debug){
        echo "AAA: return = " . print_r($data,true) . PHP_EOL;
    }
    $error = curl_error($ch);
    if(!empty($error)){
        error_log("CURL request to $url returned error: $error");
        $data = -1;
    }
    curl_close($ch);
    return trim($data);
}
/* assume following parameters
 * argv[1] = URL component e.g, http://10.1.10.24/ port may be included
 * argv[2] = user name for REST API
 * argv[3] = password for REST API
 * argv[4] = first name of user to be provisioned
 * argv[5] = last name of user
 * argv[6] = email address of user
 * argv[7] = device name
 * argv[8] = domain name
 * agrv[9] = operating system
 * argv[10] = user name for target account
 * argv{11] = debug 0 for false any positive for true
 */
if(count($argv) != 12){
     // in real code more information would be supplied
     echo " Missing required parameters. ". PHP_EOL;
     return ;
}
$baseURL = $argv[1];
$apiKey = $argv[2]. ":" . $argv[3];
$firstName = $argv[4];
$lastName = $argv[5];
$email = $argv[6];
$device['deviceName'] = $argv[7];
$device['domainName'] = $argv[8];
$device['os'] = $argv[9];
$userAccountName = $argv[10];
$debug = $argv[11]; 
$userName = $firstName . "_" . $lastName; 
/*
 * Determine if the user already exists.
 * The user name has to be unique, but since all searches are 'contains ' style, add the first and last names
 * to reduce the number of substring hits. For this first example we will code the URL manually
 */
$url = "https://" . $baseURL . APIConstants::USER_ENDPOINT_V1 . "?userName=" .urlencode($userName) .
"&firstName=" . urlencode($firstName) ."&lastName=" . urlencode($lastName) .
"&fields=userId,userName,expiration,roles";
$userData = makeAPIRequest($apiKey, $url, null,APIConstants::GET);
//the true in the decode parameter list makes the JSON be turned into PHP associative arrays,
// rather than a mix of arrays and stdClass objects.
$userList = json_decode($userData,true); 
/*
 * if the user is not found, create it. Have it immediately active, but expiring in 48 hours
 * from now
 */
if($userList['totalRows'] === 0){
    // The return from creating a new user is the id of the newly created user
    $userId = buildNewUser($userName,$firstName,$lastName,$email);
    // add error checking
    if($userId == -1){
        echo " Failed to add new user " . $userName .". Aborting";
        return;
    }
}else{
    /*
    // if the user already exists then
    // update the expiration time by two days unless the expiration date is set to unlimited or
     * later than 2 days away
    // add standard user to the list of roles if they don't already have the role
    */
    unset($user);
    foreach($userList['users'] AS $userCandidate){
        // There can be only one exact match on userName
        if($userCandidate['userName'] == $userName){
            // null is returned for a successful update
            $result = updateUser($userCandidate);
            if(!empty($result)){
                echo "Update failed with result " . print_r($result,true) .PHP_EOL;
            }
            $userId = $userCandidate['userId'];
            break;
        }
    }
}
/*
// Add the user to a group, either to give it a desired set of privileges or
  * to let the user have access to group level policies
  */
if(isset($userId)){
    addUserToGroup($userId, "Standard Role Users");
}
/* now to process the device. Do an OR search to find any devices that match either the device name
 * or the domain name
 */
$searchParameters = $device;
unset($searchParameters['os']);
// add extra fields to make device usable - assume typeAccess
$device['typeAccess'] = 't';
$deviceList = findDevice($searchParameters,"OR",
        "deviceId,deviceName,domainName,os,typePassword,typeAccess,deviceAccessMethods");
if(isset($deviceList['totalRows'])){
    // cases 0 matches - go ahead and create it
    switch($deviceList['totalRows']){
        case 0:
            $deviceId = buildNewDevice($device);
            $device['deviceId'] = $deviceId;
            // now add an access method
            $accessMethodId = updateDevice($device);
            break;
        case 1:
            // confirm both dom name and device name match
            // check for access method if missing add it.
            $deviceCandidate = $deviceList['devices'][0];
            if($deviceCandidate['deviceName'] == $device['deviceName'] &&
                    $deviceCandidate['domainName'] == $device['domainName']){
                $accessMethodId = updateDevice($deviceCandidate);
                $deviceId = $deviceCandidate['deviceId'];
                $device['deviceId'] = $deviceId;
            }else{ // conflict
                echo "Device retrieved was " . $deviceCandidate['deviceName'] .
                " with a domain name of " . $deviceCandidate['domainName'] . PHP_EOL;
                echo "Device searched for was " . $device['deviceName'] .
                " with a domain name of " . $device['domainName'] . PHP_EOL;
                return -1;
            }
            break;
        default:
            // find the device that has an exact hit if any and update it
            foreach($deviceList['devices'] AS $deviceCandidate){
                $foundDevice = false;
                if($deviceCandidate['deviceName'] == $device['deviceName'] &&
                       $deviceCandidate['domainName'] == $device['domainName']){
                    $accessMethodId = updateDevice($deviceCandidate);
                    $deviceId = $deviceCandidate['deviceId'];
                    $device['deviceId'] = $deviceId;
                    $foundDevice = true;
                    break;
                }
            }
            if(!$foundDevice){
                echo "Could not find device with name " . $device['deviceName'] .
                " and domain name of " . $device['domainName'] . PHP_EOL;
                return -1;
            }
    }
}else{
    /*
     * problem with query
     */
    echo "Device retrieve query had a problem. Details were " . print_r($deviceList,true) . PHP_EOL;
    echo "Aborting." . PHP_EOL;
    return;
}
/*
 * create a policy between the user and the device using the access method we added
 */
$policy = findExistingPolicy($userId,$deviceId);
if($policy === 0){
    $policyId = addPolicy($userId,$deviceId,$accessMethodId);
    /*
     * if we found a policy then we returned the details
     */
}elseif(is_array($policy)){
    $policyId = $policy['id'];
    /*
     * otherwise something went wrong
     */
}elseif ($policy == -1){
    return;
}
// check to see if a target application for this device already exists
$targetApplicationId = findTargetApplication($device);
/*
 * check to see if array returned, if so check for error code
 */
if(is_array($targetApplicationId)){
    foreach($targetApplicationId AS $errorMessage){
        /*
         * Message 5186 says Device not found or is not a target server.
         * Since the device must exist because we found it earlier, it must not be a target server.
         * Update the device to be of typePassword (i.e., a target server).
         */
        if(strpos($errorMessage['message'],"5186")){
            $results = updateDeviceTargetServer($device['deviceId'], 't');
            /*
             * A successful update returns nothing.
             */
            if(empty($results)){
                $targetApplicationId = 0;
                break;
            }else{
                /*
                 * More error processing goes here
                 */
            }
        }
    }
}
if(empty($targetApplicationId)){
    /*
     * To demonstrate error handling we will try to add a target application despite the fact that
     * the device is not typePassword
     */
    $targetApplicationId = addTargetApplication($device);
}
if(!is_numeric($targetApplicationId) || $targetApplicationId < 1){
    // error time to abort
    return;
}
// if needed add a target account for auto-connect to the target application
$targetAccountId = findTargetAccount($deviceId,$targetApplicationId,$userAccountName);
if(empty($targetAccountId)){
    $targetAccountId = addTargetAccount($deviceId,$targetApplicationId,$userAccountName);
}
$policy = findExistingPolicy($userId,$deviceId);
if($policy === 0){
    $policyId = addPolicy($userId,$deviceId,$accessMethodId);
}elseif(is_array($policy)){
    $policyId = $policy['id'];
}elseif ($policy == -1){
    return;
}
// retrieve the policy again and add the target application for auto-connect
$policy = findExistingPolicy($userId,$deviceId);
addSSOToPolicy($policy,$accessMethodId,$targetAccountId);
function buildNewUser($userName,$firstName,$lastName,$email){
    global $apiKey, $baseURL;
    // We can either use stdClass or an associative array to build POST or PUT data.
    // This example uses stdClass
    $user = new stdClass();
    $user->userName = $userName;
    $user->firstName = $firstName;
    $user->lastName = $lastName;
    $user->email = $email;
    $user->roles = array(array("roleId"=>2,"userGroups"=>array(),"deviceGroups"=>array()));
    $user->password = "password";
    $user->expiration = time() + APIConstants::TWO_DAYS;
    $parameters = new stdClass();
    $parameters->data = $user;
    $addUrl = "https://" . $baseURL . APIConstants::USER_ENDPOINT_V1;
    return makeAPIRequest($apiKey, $addUrl, json_encode($parameters),APIConstants::POST);
}
/*
 * Another way to give users certain roles is to assign them to a user group with those roles.
 * As an example we will get the id for a group called Standard Role Users
 * This example uses the php http_build_query function to generate the URL encoded parameters
 */
function addUserToGroup($userId,$groupName){
    global $apiKey,$baseURL;
    $url = "https://" . $baseURL . APIConstants::USER_GROUP_ENDPOINT_V1 . "?" .
http_build_query(array("groupName"=>$groupName,"fields"=>"groupId,groupName,description"));
    $groupData = makeAPIRequest($apiKey, $url,null, APIConstants::GET);
    if($groupData == -1){
        echo "Failed to get user group list. User " .
        $userId . " will not be added to the Standard Role Users group" . PHP_EOL;
    }
    //the true in the decode parameter list makes the JSON be turned into PHP associative arrays,
    // rather than a mix of arrays and stdClass objects.
    $groupList = json_decode($groupData,true);
    if(isset($groupList['totalRows'])){
        switch($groupList['totalRows']){
            case 0:
                break;
            case 1:
                $groupId = $groupList['groups'][0]['groupId'];
                echo "groupId " . $groupId .PHP_EOL;
                break;
            default:
                foreach($groupList['groups'] AS $userGroup){
                    if("Standard Role Users" == $userGroup['groupName']){
                        $groupId = $userGroup['groupId'];
                        break 2;
                    }
                }
        }
        if(isset($groupId)){
            $url = "https://" .$baseURL . APIConstants::USER_ENDPOINT_V1 . "/" .
                $groupId . "/users/" . $userId;
            $result = makeAPIRequest($apiKey, $url, null, APIConstants::POST);
        }
    }else{
        echo "totalrows not found" . PHP_EOL;
    }
function updateUser($userCandidate){
    global $apiKey,$baseURL;
    $user['userId'] = $userCandidate['userId'];
    $userId = $userCandidate['userId'];
    if(!empty($userCandidate['expiration'])){
        $newExpirationTime = time() + APIConstants::TWO_DAYS;
        $user['expiration'] = ($newExpirationTime > $userCandidate['expiration']) ?
        $newExpirationTime : $userCandidate['expiration'];
    }
    $addStandardUsers = true;
    if(count($userCandidate['roles']) > 0){
        foreach($userCandidate['roles'] AS $role){
            if(in_array($role['roleId'],
array(APIConstants::ROLE_STANDARD_USER,APIConstants::ROLE_GLOBAL_ADMINISTRATOR,
                            APIConstants::ROLE_OPERATIONAL_ADMINISTRATOR))){
                $addStandardUsers = false;
��               break;
            }
        }
    }
    if($addStandardUsers){
        $user['roles'] = $userCandidate['roles'];
        $user['roles'][] = array("roleId"=>APIConstants::ROLE_STANDARD_USER,
                "userGroups"=>array(),
                "deviceGroups"=>array());
    }
    $updateUrl = "https://" . $baseURL . APIConstants::USER_ENDPOINT_V1;
    $parameters['data'] = $user;
    $result = makeAPIRequest($apiKey, $updateUrl, json_encode($parameters),APIConstants::PUT);
    return $result;
}
/**
 *
 * @param array $searchParms - keys are search fields value are values
 * @param string $searchRelationShip AND or OR if there are multiple search parameters
 * @param string $fields what information about a device you want returned. NULL takes the
 * default the API returns
 */
function findDevice(array $searchParameters,$searchRelationship="AND",$fields=null){
    global $apiKey,$baseURL;
    $searchParameters['searchRelationship'] = $searchRelationship;
    if(!empty($fields)){
        $searchParameters['fields'] = $fields;
    }
    $url = "https://" . $baseURL . APIConstants::DEVICE_ENDPOINT_V1 . "?" .
        http_build_query($searchParameters);
    $deviceData = makeAPIRequest($apiKey, $url, null, APIConstants::GET);
    $deviceList = json_decode($deviceData,true);
    return $deviceList;
}
function findDeviceById($deviceId,$fields=null){
    global $apiKey,$baseURL;
    if(!empty($fields)){
        $searchParameters['fields'] = $fields;
    }
    $url = "https://" . $baseURL . APIConstants::DEVICE_ENDPOINT_V1 . "/" . $deviceId;
}
/**
 * create a new device
 * @return deviceId (int)
 * @param array $device
 */
function buildNewDevice($device){
    global $apiKey,$baseURL;
    $url = "https://" . $baseURL . APIConstants::DEVICE_ENDPOINT_V1;
    $deviceId = makeAPIRequest($apiKey, $url,json_encode($device), APIConstants::POST);
    $device['deviceId'] = $deviceId;
    return $deviceId;
}
/**
 * Updates a device to add an access method.
 * @param array $device
 * @return access method id
 */
function updateDevice(array $device){
    global $apiKey,$baseURL;
    $addAccessMethod = true;
    if(!empty($device['deviceAccessMethods'])){
        foreach($device['deviceAccessMethods'] as $accessMethod){
            if((strtoupper($device['os']) == "LINUX" && $accessMethod['type'] == "SSH" &&
                isset($accessMethod['id'])) ){
                    return $accessMethod['id'];
            }
        }
    }
    /*
     * Always add SSH if one isn't there
     */
        $accessMethods = array(
            "type" => "SSH",
            "port" => 22
        );
        $url = "https://" . $baseURL . APIConstants::DEVICE_ENDPOINT_V1 . "/" .
            $device['deviceId'] . "/accessMethods";
        $parameters['accessMethods'] = array($accessMethods);
        $accessMethodJSON = makeAPIRequest($apiKey, $url, json_encode($parameters), APIConstants::POST);
        /*
         * We know there is only one entry in the array at most
         */
        $accessMethod = json_decode($accessMethodJSON,true);
        $addedAccessMethod = $accessMethod[0];
        return $addedAccessMethod['id'];
}
/**
 * Add a UNIX type target application (Windows Domain/Proxy not supported, Generic too simple)
 * @param array $device
 */
function addTargetApplication(array $device){
    global $apiKey, $baseURL;
    $results = addUnixTargetApplication($device);
    if(is_numeric($results)){
        $targetApplicationId = $results;
    }else{
        $errors = json_decode($results,true);
        if(is_array($errors)){
            // More error processing here
            $targetApplicationId = -1;
        } 
    }
    // either the actual target application id or -1 for failure to find or error message if one returned
    return $targetApplicationId;
}
/**
 *
 * @param array $device
 * @return mixed empty array if no target application found,
 * int the targetApplication id if found
 * array of error messages if found
 */
function findTargetApplication($device){
    global $apiKey,$baseURL;
    // first see if the application already exists. Don't specify fields so as to take the default
    $url = "https://" . $baseURL . APIConstants::DEVICE_ENDPOINT_V1 . "/" . $device['deviceId'] . "/targetApplications";
    $parameter['data']['applicationName'] = $device['deviceName'] . " Unix account";
    $results = makeAPIRequest($apiKey, $url, json_encode($parameter), APIConstants::GET);
    $targetApplications = json_decode($results,true);
    // if an empty array was returned the search was successful and there were no matching target application.
    if(is_array($targetApplications) && !empty($targetApplications)){
        foreach($targetApplications AS $targetApplication){
            if(isset($targetApplication['id']) && $parameter['data']['applicationName'] == $targetApplication['applicationName']){
                return $targetApplication['id'];
            }else if(!isset($targetApplication['id'])){ // error code returned
                echo " Error when trying to search for a target application. Error was " . print_r($targetApplications,true) . PHP_EOL;
                // since there may be multiple error messages return everything, not just this error
                return json_decode($results,true);
            }
        }
    }
}
/**
 * Add a new target server of type Unix to the specified device
 * @param array $device
 * @return Ambigous <string, number>
 */
function addUnixTargetApplication($device){
    global $apiKey,$baseURL;
    $parameter['data']['applicationName'] = $device['deviceName'] . " Unix account";
    $parameter['data']['applicationType'] = "unixII";
    $attributes = array("sshSessionTimeout"=>60000,"sshPort"=>22,"unixVariant"=>"LINUX",
        "sshUseDefaultCiphers"=>"true");
    $parameter['data']['attributes'] = $attributes;
    /*
     * notice how we use exactly the same URL here as in findTargetApplication.
     * The only difference is that the type of transaction is POST.
     * The parameters are different, but that isn't part of the URL.
     */
    $url = "https://" . $baseURL . APIConstants::DEVICE_ENDPOINT_V1 . "/" . $device['deviceId'] .
        "/targetApplications";
    $results = makeAPIRequest($apiKey, $url, json_encode($parameter), APIConstants::POST);
    return $results;
}
/**
 * change a device to either be of typePassword (t) or not (f)
 * @param integer $deviceId
 * @param string $trueOrFalse
 */
function updateDeviceTargetServer($deviceId,$trueOrFalse){
    global $apiKey, $baseURL;
    // obviously check if $trueOrFalse is t or f
    $parameter['data']['typePassword'] = $trueOrFalse;
    $parameter['data']['deviceId'] = $deviceId;
    $url = "https://" . $baseURL . APIConstants::DEVICE_ENDPOINT_V1;
    $results = makeAPIRequest($apiKey, $url, json_encode($parameter), APIConstants::PUT);
}
/**
 * Find a target account for a particular target application (and hence for a particular device)
 * @param integer $deviceId
 * @param integer $targetApplicationId
 * @param string $accountName
 * @return mixed - id if successful, error messages if not
 */
function findTargetAccount($deviceId, $targetApplicationId, $accountName){
    global $apiKey, $baseURL;
    // same thing - check if target account exists already
    $parameter['data']['accountName'] = $accountName;
    $url = "https://" . $baseURL . APIConstants::DEVICE_ENDPOINT_V1 . "/" . $deviceId . "/targetApplications/" . $targetApplicationId . "/targetAccounts";
    $targetAccountResults = makeAPIRequest($apiKey, $url, json_encode($parameter), APIConstants::GET);
    $targetAccounts = json_decode($targetAccountResults, true);
    if(is_array($targetAccounts)){
        foreach($targetAccounts as $targetAccount){
            if($targetAccount['accountName'] == $accountName){
                return $targetAccount['accountId'];
            }
        }
    }
    return $targetAccounts;
/**
 *
 * @param int $deviceId
 * @param int $targetApplicationId
 * @param string $accountName
 * @return Ambigous <string, number> int if successful add otherwise
 */
function addTargetAccount($deviceId, $targetApplicationId, $accountName){
    global $apiKey, $baseURL;
    $parameter['data']['accountName'] = $accountName;
    // special code to tell PA to generate a unique password based on password composition policy
    $parameter['data']['password'] = "
generate_pass
";
    $parameter['data']['useAliasNameParameter'] = 't';
    $parameter['data']['aliasNames'] = $accountName . ",alias" . $accountName;
    $url = "https://" . $baseURL . APIConstants::DEVICE_ENDPOINT_V1 . "/" . $deviceId . "/targetApplications/" . $targetApplicationId . "/targetAccounts";
    $results = makeAPIRequest($apiKey, $url, json_encode($parameter), APIConstants::POST);
    if(!is_numeric($results)){
        // decode if this is a JSON string
       $checkResults = json_decode($results, true);
       if(!empty($checkResults)){
            $results = $checkResults;
        }
    }
    return $results;
}
/**
 *
 * @param int $userId
 * @param int $deviceId
 * @return policy object if found, 0 if no policy, -1 if invalid parameters
 */
function findExistingPolicy($userId,$deviceId){
    global $apiKey, $baseURL;
    $url = "https://" . $baseURL . APIConstants::POLICIES_ENDPOINT_V1 . "/" . $userId . "/" . $deviceId ."?fields=id,accessMethods";
    $results = makeAPIRequest($apiKey, $url, null, APIConstants::GET);
    $policy = json_decode($results,true);
    if(isset($policy['id'])){
        return $policy;
    }
    // most likely results are some kind of error message
    if(is_array($policy) && count($policy) > 0){
        foreach($policy AS $message){
            // Message 12033 - userid and device id were both valid, but no policy between them exists
            if(strpos($message['message'],"12033") !== false){
                return 0;
            }
            // Message 12034 - user or group id specified in policy does not exist
            if(strpos($message['message'],"12034") !== false){
                echo $message['message'] . PHP_EOL;
                return -1;
            }
            // Message 12035 - device or group id specified in policy does not exist
            if(strpos($message['message'],"12035") !== false){
                echo $message['message'] . PHP_EOL;
                return -1;
            }
            // unexpected error
            echo $message['message'] . PHP_EOL;
            return -1;
        }
    }
/**
 * Add a policy between a user and a device for an access method, without specifying auto-connection.
 * @param integer $userId
 * @param integer $deviceId
 * @param integer $accessMethodId
 * @return policy id on success else void
 */
function addPolicy($userId,$deviceId,$accessMethodId){
    global $apiKey, $baseURL;
    $url = "https://" . $baseURL . APIConstants::POLICIES_ENDPOINT_V1 . "/" . $userId . "/" . $deviceId;
    $accessMethods = array(array("accessMethodId"=>$accessMethodId));
    $parameter['accessMethods'] = $accessMethods;
    // turn on cli recording
    $parameter['cliRecording'] = "t";
    $results = makeAPIRequest($apiKey, $url, json_encode($parameter), APIConstants::POST);
    if(is_numeric($results)){
        return $results;
    }
}
/**
 * Replace the existing access method for the policy with one that has a target account for auto-connection.
 * @param array $policy
 * @param integer $accessMethodId
 * @param integer $targetAccountId
 */
function addSSOToPolicy($policy,$accessMethodId,$targetAccountId){
    global $apiKey, $baseURL;
    /**
     * Multiple target accounts could be assigned, so the accountIds are an array
     */
    $putData = array(array("accessMethodId"=>$accessMethodId,"accountIds"=>array($targetAccountId)));
    $url = "https://" . $baseURL . APIConstants::POLICIES_ENDPOINT_V1 . "/" . $policy['id'] .
    "/accessMethods";
    $results = makeAPIRequest($apiKey, $url,json_encode($putData),APIConstants::PUT);
}