000032481 - How to use the RSA Archer REST API with Windows PowerShell

Document created by RSA Customer Support Employee on Jun 14, 2016Last modified by RSA Customer Support Employee on Apr 21, 2017
Version 5Show Document
  • View in full screen mode

Article Content

Article Number000032481
Applies ToRSA Product Set: Archer

RSA Version/Condition: 5.5.x and higher

Platform: Windows
ResolutionWindows PowerShell makes it easy to use the Archer REST API when compared to tools like Visual Studio.  Depending on the PowerShell version, it will include common functions, or cmdlets, to perform an action and return a Microsoft.NET object to process further.  For more details, check out the Task-Based Guide to PowerShell Cmdlets.



PowerShell 4.0 (Windows Management Framework 4.0) includes cmdlets for REST and Web Service API calls that simplify these tasks and process the results.  This article focuses on the REST API.  PowerShell 4.0 or higher needs to be installed on the computer running the scripts.
Download Windows Management Framework 4.0 here.  NOTE: PowerShell 4.0 can be installed on an Archer Admin's workstation and does not have to be installed on the Archer servers.


After installing PowerShell 4.0 or higher, open the attached script in the Windows PowerShell ISE application.  At the top of the script, update the Archer Instance variables for Base URL, Instance Name, User Domain, User Name, and Password.  NOTE: Instance Name is case sensitive.
$base_url = "http://localhost/Archer" 
$instance_name = "Archer"
$user_domain = ""
$username = "apiuser"
$password = "Archer"

To login and create a session token, the following code snippet calls the login controller and saves the session token to a variable.
$login_url = $base_url + "/api/core/security/login"
$body = '{"InstanceName":"' + $instance_name + '","Username":"' + $username + '","UserDomain":"' + $user_domain + '","Password":"' + $password + '"}'
$response_login = Invoke-RestMethod -Method Post -Uri $login_url -Body $body -ContentType "application/json" -SessionVariable $sess
$session_token = $response_login.RequestedObject.SessionToken



For any other API calls, the session token is required.  When using the REST API, the session token is passed in the header and the standard GET request is unencrypted. To avoid this inherent vulnerability, the API watches for and responds to the X-HTTP-Method-Override header. A client can submit a request with the HTTP verb POST and the override header set to GET.  The following code snippet creates two header variables to use in additional calls: one for GET and one for all others.
$headersGET = @{}
$headersGET.Add("Authorization", "Archer session-id=" + $session_token)
$headersGET.Add("X-Http-Method-Override", "GET")
$headers = @{}
$headers.Add("Authorization", "Archer session-id=" + $session_token)



The following code snippet gets the Archer version.
$api_url = $base_url + "/api/core/system/applicationinfo/version"
$results = Invoke-RestMethod -Method POST -Uri $api_url -Headers $headersGET -ContentType "application/json" -WebSession $sess
$version = $results.RequestedObject.Version



The attached PowerShell script contains sample code using the following REST API controllers with the GET, POST, PUT, and DELETE verbs.  Depending on the Archer version, some controllers may not be available.  Please download the REST API Guide for your version.
/api/core/security/login
/api/core/system/applicationinfo/version
/api/core/system/application
/api/core/system/level
/api/core/system/fielddefinition/level/*levelid*
/api/core/system/user/*userid*
/api/core/system/group/*groupid*
/api/core/system/usergroup
/api/core/system/user/group/*groupid*
/api/core/content/*contentid*
/api/core/content



Most of the code snippets in the attached script are commented out using the pound symbol (#) for a single line or comment blocks using <# ... #>.  Deleting the "<" after the section's description will uncomment the whole block for testing.  Below are sample code snippets.

NOTE: some sections contain variables that rely on previous sections.



Get all Applications and display results.
$api_url = $base_url + "/api/core/system/application"
$results = Invoke-RestMethod -Method POST -Uri $api_url -Headers $headersGET -ContentType "application/json" -WebSession $sess
$results.RequestedObject



Get all Levels while also demonstrating the concept of projecting to limit results using the OData $select keyword and sorting using the OData $orderby keyword.
$api_url = $base_url + "/api/core/system/level"
$body = '{ "Value" : "?$select=Id,Name,ModuleId&$orderby=Name" }'
$results = Invoke-RestMethod -Method POST -Uri $api_url -Body $body -Headers $headersGET -ContentType "application/json" -WebSession $sess
$results.RequestedObject | Format-Table -AutoSize



Get all Field Definitions for a Level and display results.
$api_url = $base_url + "/api/core/system/fielddefinition/level/191"
$results = Invoke-RestMethod -Method POST -Uri $api_url -Body $body -Headers $headersGET -ContentType "application/json" -WebSession $sess
# Because the results is a collection of Json objects and the objects contain a duplicate key (GUID and guid), prepend a _ to make one unique.
$results = $results.ToString().Replace("guid", "_guid") | ConvertFrom-Json
# Display all property values for each field.
$results.ForEach({$_.RequestedObject | Select-Object *})
# Display specific property values for each field in a table format
$results.ForEach({$_.RequestedObject | Select-Object Id,Name,Alias,Type,IsKey,IsActive,IsCalculated,IsPrivate,IsContentReadOnly,GUID}) | Format-Table -AutoSize



Get User details for a User Id and display results.
$api_url = $base_url + "/api/core/system/user/190"
$results = Invoke-RestMethod -Method POST -Uri $api_url -Headers $headersGET -ContentType "application/json" -WebSession $sess
$results.RequestedObject



Get Group details for a Group Id and display results.
$api_url = $base_url + "/api/core/system/group/2"
$results = Invoke-RestMethod -Method POST -Uri $api_url -Headers $headersGET -ContentType "application/json" -WebSession $sess
$results.RequestedObject



Add a User to a Group with error handling and display results.
try {
    $api_url = $base_url + "/api/core/system/usergroup"
    $body = '{"UserId":190,"GroupId":2,"IsAdd":true}'
    $results = Invoke-RestMethod -Method PUT -Uri $api_url -Body $body -Headers $headers -ContentType "application/json" -WebSession $sess
    if ($results.IsSuccessful -and $results.ValidationMessages.count -eq 0) {
        $results
    }
    else {
        $results.ValidationMessages
    }
}
catch { $_.Exception|Format-List -Force }
finally { $results = $null }

Get members of Group Id and display results in a table.
$api_url = $base_url + "/api/core/system/user/group/2"
$results = Invoke-RestMethod -Method POST -Uri $api_url -Headers $headersGET -ContentType "application/json" -WebSession $sess
$results.RequestedObject|Format-Table -Wrap

Get a Content Record and display details.
###########################################################################################################################################
# GET a Content Record from Policies application. Display the top object and the field contents.
###########################################################################################################################################
$api_url = $base_url + "/api/core/content/123006"
$results = Invoke-RestMethod -Method POST -Uri $api_url -Headers $headersGET -ContentType "application/json" -WebSession $sess
$results.RequestedObject
$results.RequestedObject.FieldContents

Create a Content Record and save the Content Id to use in the next section.
###########################################################################################################################################
# CREATE a Content Record and save the Content Id to use in the next UPDATE sample.
#      191 = Application Level Id
#    13867 = Text field
#    13868 = Text Area field (html)
###########################################################################################################################################
try {
    $api_url = $base_url + "/api/core/content"
    $body =
    '{"Content" : {"LevelId" : 191, "FieldContents" : {
     "13867" : {"Type" : 1, "Value" : "Name created via REST API", "FieldId" : 13867}
    ,"13868" : {"Type" : 1, "Value" : "Description created via REST API", "FieldId" : 13868}
    }}}'
    $results = Invoke-RestMethod -Method POST -Uri $api_url -Body $body -Headers $headers -ContentType "application/json" -WebSession $sess
    if ($results.IsSuccessful -and $results.ValidationMessages.count -eq 0) {
        $results
        $content_id = $results.RequestedObject.Id
    }
    else {
        $results.ValidationMessages
    }
}
catch { $_.Exception|Format-List -Force }
finally { $results = $null }

Update a Content Record using the Content Id from the above snippet.  The second HTML value is commented out as an example.
###########################################################################################################################################
# UPDATE a Content Record using the Content Id created above.
#   Demo a HTML value converted to JSON and used for the update.
#      191 = Application Level Id
#    13867 = Text field
#    13868 = Text Area field (html)
###########################################################################################################################################
try {
    $html = ConvertTo-Json(
        '<p>This is a description that contains HTML content with different styles,
        <strong><span style="color: #ff0000;">COLORS</span></strong>, 
        <span style="font-family: comic sans ms,sans-serif;">This is COMIC SANS, 
        <em><span style="font-size: 14pt;">font </span></em></span><span style="font-size: 24pt;">sizes</span>.
        <span style="background-color: #ffff00;">This is highlighted.</span></p>
        <p>My bullet points:</p> <ul> <li>Point 1</li> <li>Point 2</li> </ul>
        <p><img src="https://community.rsa.com/resources/images/palette-1004/RSA-Link_logo.png" alt="RSA Link" width="155" height="60" /></p>')
    # This HTML is a series of links to folder, files, or website.
    #$html = ConvertTo-Json(
    #    '<p><a href="file://ServerName/Share/FolderName" target="_blank">Click here to access it''s network share folder</a></p>
    #    <p><a href="file://ServerName/Share/FolderName/MyTextFile.txt" target="_blank">Text File</a></p>
    #    <p><a href="file://ServerName/Share/FolderName/File%20Name%20with%20spaces.pdf" target="_blank">PDF File</a></p>
    #    <p><a href="https://knowledge.rsasecurity.com/scolcms/knowledge.aspx?solution=a64501" target="_blank">Archer Knowledge Base Article on SCOL</a></p>')
    # Replace some escaped values back to its friendly character for display.
    $html = $html.Replace("\u003c","<")
    $html = $html.Replace("\u003e",">")
   
    $api_url = $base_url + "/api/core/content"
    $body =
        '{"Content": {"Id": ' + $content_id + ', "LevelId": 191, "FieldContents": {
          "13867": {"Type": 1, "Value": "Name updated via REST API", "FieldId": 13867}
         ,"13868": {"Type": 1, "Value": ' + $html + ', "FieldId": 13868}
         }}}'
    $results = Invoke-RestMethod -Method PUT -Uri $api_url -Body $body -Headers $headers -ContentType "application/json" -WebSession $sess
    if ($results.IsSuccessful -and $results.ValidationMessages.count -eq 0) {
        $results
    }
    else {
        $results.ValidationMessages
    }
}
catch { $_.Exception|Format-List -Force }
finally { $results = $null }

Delete a Content Record.
###########################################################################################################################################
# DELETE a Content Record.
###########################################################################################################################################
try {
    $api_url = $base_url + "/api/core/content/326532"
    $results = Invoke-RestMethod -Method DELETE -Uri $api_url -Headers $headers -ContentType "application/json" -WebSession $sess
    if ($results.IsSuccessful -and $results.ValidationMessages.count -eq 0) {
        $results
    }
    else {
        $results.ValidationMessages
    }
}
catch { $_.Exception|Format-List -Force }
finally { $results = $null }

Create a Sub-Form Record and save the Sub-Form Content Id.  Then create a parent Content Record linking it to the Sub-Form Content Id.
###########################################################################################################################################
# CREATE a Sub-Form Record and save the Sub-Form Content Id to be used below.
#      192 = Sub-Form Level Id
#    13884 = Text field in the Sub-Form
#    13886 = Sub-Form field in the parent app
###########################################################################################################################################
try {
    $api_url = $base_url + "/api/core/content"
    $body =
    '{"Content": {
        "LevelId": 192, "FieldContents": {
        "13884": { "Type": 1, "Value": "Subform created via REST API", "FieldId": 13884 }
    }}, "SubformFieldId": 13886}'
    $results = Invoke-RestMethod -Method POST -Uri $api_url -Body $body -Headers $headers -ContentType "application/json" -WebSession $sess
    if ($results.IsSuccessful -and $results.ValidationMessages.count -eq 0) {
        $results
        $subform_id = $results.RequestedObject.Id
    }
    else {
        $results.ValidationMessages
    }
}
catch { $_.Exception|Format-List -Force }
finally { $results = $null }

###########################################################################################################################################
# CREATE a parent record and link the Sub-Form record created above.
#      191 = Application Level Id
#    13867 = Text field in the parent app
#    13868 = Text Area field in the parent app
#    13886 = Sub-Form field in the parent app
###########################################################################################################################################
try {
    $api_url = $base_url + "/api/core/content"
    $body =
    '{"Content" : {"LevelId" : 191, "FieldContents" : {
     "13867" : {"Type" : 1, "Name" : "My Text Field", "Value" : "Name created via REST API", "FieldId" : 13867}
    ,"13868" : {"Type" : 1, "Name" : "My Description", "Value" : ' + $html + ', "FieldId" : 13868}
    ,"13886" : {"Type" : 24, "Name" : "My Sub-Form", "Value" : [' + $subform_id + '], "FieldId" : 13886}
    }}}'
    $results = Invoke-RestMethod -Method POST -Uri $api_url -Body $body -Headers $headers -ContentType "application/json" -WebSession $sess
    if ($results.IsSuccessful -and $results.ValidationMessages.count -eq 0) {
        $results
        $content_id = $results.RequestedObject.Id
    }
    else {
        $results.ValidationMessages
    }
}
catch {$_.Exception|Format-List -Force}
finally {$results = $null}

 

Outcomes