外部 API の実装例

以下のコード抜粋は、外部 API メソッドを使用した curl での PHP の例を示しています。この例では、ユーザ、デバイス、およびそれら 2 つの間の自動接続ポリシーをプロビジョニングします。API リクエストで にアクセスできるクライアント ソフトウェアを準備するには、
CA Technologies
プロフェッショナル サービスを利用できます。
capamnew
以下のコード抜粋は、外部 API メソッドを使用した curl での PHP の例を示しています。この例では、ユーザ、デバイス、およびそれら 2 つの間の自動接続ポリシーをプロビジョニングします。API リクエストで
CA 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);
}