Secure Remote Access
Overview
CIS provides secure remote access to targeted remote systems. This allows Centrify users to access those systems without exposing the login password and without requiring a VPN connection to the corporate network on which the remote system lives. After the user logs out of the system, the password is automatically rotated for additional security.
These features improve security and reduce risks for share privileged accounts on remote systems.
This document demonstrates the API workflow for programatically discovering and accessing a remote Unix system.
Before continuing, ensure you are familiar with:
Step 1. Authenticate the User
Start the Authentication Process
Start the authentication process by invoking the /Security/StartAuthentication endpoint and passing in the ID of the tenant and the user name via the TenantId
and User
fields:
POST /Security/StartAuthentication
Formatted JSON Data
{
"TenantId":"aaa1234",
"User":"[email protected]",
"Version":"1.0",
"AssociatedEntityType":"Portal",
"AssociatedEntityName":"Portal",
"ExtIdpAuthChallengeState":""
}
The response contains the session ID and challenge mechanisms:
{
"success":true,
"Result":{
"ClientHints":{
"PersistDefault":false,
"AllowForgotPassword":true,
"AllowPersist":false
},
"TenantId":"aaa1234",
"Summary":"NewPackage",
"SessionId":"ueyV0v7H255Aj849o7dUT_WpWNwvlR9FqbYNoBtBY2A1",
"Challenges":[
{
"Mechanisms":[
{
"PromptSelectMech":"Password",
"Name":"UP",
"AnswerType":"Text",
"MechanismId":"GQqOSNCT50ihn1ovrOdP9oOiKeEIDsXh76sv1M8lGSo1",
"PromptMechChosen":"Enter Password"
}
]
}
],
"Version":"1.0"
},
...
}
Advance the Authentication
Invoke the /Security/AdvanceAuthentication endpoint for each security mechanism. In the following example, a password is being provided:
POST /Security/AdvanceAuthentication
{
"TenantId":"AAU0350",
"SessionId":"ueyV0v7H255Aj849o7dUT_WpWNwvlR9FqbYNoBtBY2A1",
"PersistentLogin":null,
"MechanismId":"GQqOSNCT50ihn1ovrOdP9oOiKeEIDsXh76sv1M8lGSo1",
"Answer":"mypassword",
"Action":"Answer"
}
Once all of the security mechanisms have been satisfied, an authentication code will be returned in the Auth
field for use in subsequent API calls:
{
"success":true,
"Result":{
"EmailAddress":"[email protected]",
"Auth":"CDC92...",
"User":"[email protected]",
"Summary":"LoginSuccess",
"SystemID":"aaa1234",
"CustomerID":"aaa1234",
"PodFqdn":"support.my.centrify.com",
"DisplayName":"John",
"SourceDsType":"CDS",
"UserId":"12341234-0f5c-4834-8894-bb9f749515f4",
"UserDirectory":"CDS",
"AuthLevel":"Normal"
},
...
}
Step 2. Get the Resource Queries
The next step is to get the queries to use for finding the various resources to access. In the following example, ObjectType
is set to Server
to indicate that queries should be returned for finding various types of systems that can be accessed through CIS for your tenant:
POST /Collection/GetObjectCollectionsAndFilters
{
"ObjectType":"Server",
"Args":{
"PageNumber":1,
"PageSize":100000,
"Limit":100000,
"SortBy":"",
"direction":"False",
"Caching":-1
}
}
The response contains SQL queries for various types of servers:
{
"success":true,
"Result":{
"IsAggregate":false,
"Count":11,
"Columns":[
{
"Name":"ID",
"IsHidden":false,
"DDName":null,
"Title":"ID",
"DDTitle":null,
"Description":null,
"Type":12,
"Format":null,
"Width":25,
"TableKey":null,
"ForeignKey":null,
"TableName":null
},
...
],
"FullCount":11,
"Results":[
{
"Entities":[
{
"Type":"Collection",
"Key":"@All Servers",
"IsForeignKey":false
}
],
"Row":{
"Rank":10,
"CollectionType":"SqlDynamic",
"Filters":"SELECT * FROM (Select Server.ID, Server.AgentVersion, Server.ComputerClass, Server.Description, Server.FQDN, Server.LastState, Server.HealthStatus, Server.IsFavorite, Server.IPAddress, Server.Joined, Server.OperatingSystem, Server.Name, Server.UserID, Server.SessionType, Server.Port, Server.ProxyUser, Server.AllowRemote, Server.DefaultCheckoutTime, Server.AllowMultipleCheckouts, Server.ProxyUserIsManaged, Server.ManagementMode, Server.ManagementPort, Server.JoinedBy, Server.PasswordProfileID, Server.JoinedDate, Server.AllowHealthCheck, Server.HealthCheckInterval, Server.AllowPasswordRotation, Server.MinimumPasswordAge, Server.PasswordRotateDuration, Server.AllowPasswordHistoryCleanUp, Server.PasswordHistoryCleanUpDuration, Server.ProxyCollectionList, Server.TimeZoneID,Server.LmiEnabled, Server.DiscoveredTime as ServerDiscoveredTime from Server ORDER BY Name COLLATE NOCASE)",
"Name":"All Systems",
"Description":"All Systems",
"ID":"@All Servers",
"ObjectType":"Server",
"Builtin":true
}
},
{
"Entities":[
{
"Type":"Collection",
"Key":"@Unix Servers",
"IsForeignKey":false
}
],
"Row":{
"Rank":20,
"CollectionType":"SqlDynamic",
"Filters":"SELECT * FROM (Select Server.ID, Server.AgentVersion, Server.ComputerClass, Server.Description, Server.FQDN, Server.LastState, Server.HealthStatus, Server.IsFavorite, Server.IPAddress, Server.Joined, Server.OperatingSystem, Server.Name, Server.UserID, Server.SessionType, Server.Port, Server.ProxyUser, Server.AllowRemote, Server.DefaultCheckoutTime, Server.AllowMultipleCheckouts, Server.ProxyUserIsManaged, Server.ManagementMode, Server.ManagementPort, Server.JoinedBy, Server.PasswordProfileID, Server.JoinedDate, Server.AllowHealthCheck, Server.HealthCheckInterval, Server.AllowPasswordRotation, Server.MinimumPasswordAge, Server.PasswordRotateDuration, Server.AllowPasswordHistoryCleanUp, Server.PasswordHistoryCleanUpDuration, Server.ProxyCollectionList, Server.TimeZoneID,Server.LmiEnabled, Server.DiscoveredTime as ServerDiscoveredTime from Server ORDER BY Name COLLATE NOCASE) WHERE ComputerClass = \"Unix\"",
"Name":"Unix Systems",
"Description":"Unix Systems",
"ID":"@Unix Servers",
"ObjectType":"Server",
"Builtin":true
}
},
{
"Entities":[
{
"Type":"Collection",
"Key":"@Windows Servers",
"IsForeignKey":false
}
],
"Row":{
"Rank":20,
"CollectionType":"SqlDynamic",
"Filters":"SELECT * FROM (Select Server.ID, Server.AgentVersion, Server.ComputerClass, Server.Description, Server.FQDN, Server.LastState, Server.HealthStatus, Server.IsFavorite, Server.IPAddress, Server.Joined, Server.OperatingSystem, Server.Name, Server.UserID, Server.SessionType, Server.Port, Server.ProxyUser, Server.AllowRemote, Server.DefaultCheckoutTime, Server.AllowMultipleCheckouts, Server.ProxyUserIsManaged, Server.ManagementMode, Server.ManagementPort, Server.JoinedBy, Server.PasswordProfileID, Server.JoinedDate, Server.AllowHealthCheck, Server.HealthCheckInterval, Server.AllowPasswordRotation, Server.MinimumPasswordAge, Server.PasswordRotateDuration, Server.AllowPasswordHistoryCleanUp, Server.PasswordHistoryCleanUpDuration, Server.ProxyCollectionList, Server.TimeZoneID,Server.LmiEnabled, Server.DiscoveredTime as ServerDiscoveredTime from Server ORDER BY Name COLLATE NOCASE) WHERE ComputerClass = \"Windows\"",
"Name":"Windows Systems",
"Description":"Windows Systems",
"ID":"@Windows Servers",
"ObjectType":"Server",
"Builtin":true
}
}
...
],
"ReturnID":""
},
"Message":null,
"MessageID":null,
"Exception":null,
"ErrorID":null,
"ErrorCode":null,
"InnerExceptions":null
}
Step 3. Execute a Query to get the Remote Resources
Choose a query from the response in the previous call, using the various fields returned to determine the most appropriate query (e.g. use the Entities
> Key
field to identify the query for listing all servers).
Once a query has been identified, invoke the /RedRock/query endpoint and pass the query string via the Script
field:
POST /RedRock/query
{
"Script":"SELECT * FROM (Select Server.ID, Server.AgentVersion, Server.ComputerClass, Server.Description, Server.FQDN, Server.LastState, Server.HealthStatus, Server.IsFavorite, Server.IPAddress, Server.Joined, Server.OperatingSystem, Server.Name, Server.UserID, Server.SessionType, Server.Port, Server.ProxyUser, Server.AllowRemote, Server.DefaultCheckoutTime, Server.AllowMultipleCheckouts, Server.ProxyUserIsManaged, Server.ManagementMode, Server.ManagementPort, Server.JoinedBy, Server.PasswordProfileID, Server.JoinedDate, Server.AllowHealthCheck, Server.HealthCheckInterval, Server.AllowPasswordRotation, Server.MinimumPasswordAge, Server.PasswordRotateDuration, Server.AllowPasswordHistoryCleanUp, Server.PasswordHistoryCleanUpDuration, Server.ProxyCollectionList, Server.TimeZoneID,Server.LmiEnabled, Server.DiscoveredTime as ServerDiscoveredTime from Server ORDER BY Name COLLATE NOCASE)",
"Args":{
"PageNumber":1,
"PageSize":100,
"Limit":100000,
"SortBy":"",
"direction":"False",
"Caching":-1
}
}
The response contains the list of servers which satisfy the query:
{
"success":true,
"Result":{
"IsAggregate":false,
"Count":11,
"Columns":[
{
"Name":"ID",
"IsHidden":false,
"DDName":"_ID",
"Title":"ID",
"DDTitle":"ID",
"Description":"Row Identifier (primary key)",
"Type":12,
"Format":null,
"Width":0,
"TableKey":"Primary",
"ForeignKey":null,
"TableName":"Server"
},
...
],
"FullCount":11,
"Results":[
{
"Entities":[
{
"Type":"Server",
"Key":"abcdabcd-7461-4be6-982f-afb256770c3e",
"IsForeignKey":false
}
],
"Row":{
"ID":"abcdabcd-7461-4be6-982f-afb256770c3e",
"AllowMultipleCheckouts":null,
"DefaultCheckoutTime":null,
"JoinedBy":null,
"MinimumPasswordAge":null,
"LmiEnabled":null,
"ProxyUser":"",
"UserID":null,
"PasswordHistoryCleanUpDuration":null,
"ManagementMode":null,
"AllowHealthCheck":null,
"JoinedDate":null,
"Joined":null,
"LastState":"OK",
"SessionType":"Ssh",
"PasswordProfileID":null,
"ProxyUserIsManaged":null,
"IPAddress":null,
"PasswordRotateDuration":null,
"ManagementPort":null,
"AgentVersion":null,
"Description":"",
"ProxyCollectionList":null,
"FQDN":"172.27.9.220",
"Name":"csssup-ubuntu",
"AllowRemote":null,
"HealthCheckInterval":null,
"ComputerClass":"Unix",
"ServerDiscoveredTime":"\/Date(1516060925480)\/",
"OperatingSystem":"Ubuntu",
"AllowPasswordHistoryCleanUp":null,
"Port":null,
"HealthStatus":"OK",
"AllowPasswordRotation":null,
"IsFavorite":false,
"TimeZoneID":null
}
},
...
],
"ReturnID":""
},
"Message":null,
"MessageID":null,
"Exception":null,
"ErrorID":null,
"ErrorCode":null,
"InnerExceptions":null
}
Step 4. Get Effective Row Rights
Identify the server in the response from the previous request for which a remote access session is to be started.
Using the Key
value which identifies that server, invoke the /Acl/GetEffectiveRowRights endpoint to get a grant string, and pass the server identity via the 'RowKey' field:
POST Acl/GetEffectiveRowRights
{
"Rows":[
{
"Table":"Server",
"RowKey":"abcdabcd-7461-4be6-982f-afb256770c3e",
"ReduceSysadmin":true
}
]
}
The results contains a grant string for the server:
{
"success":true,
"Result":[
{
"GrantStr":"0000000000000000000000000000000000000000000000110000000011111111",
"RowKey":"abcdabcd-7461-4be6-982f-afb256770c3e",
"Table":"Server"
}
],
"Message":null,
"MessageID":null,
"Exception":null,
"ErrorID":null,
"ErrorCode":null,
"InnerExceptions":null
}
Step 5. Get the Login Accounts
The next step is to get the login accounts for the system by invoking the /ServerManage/GetAccountsForLogin endpoint and passing the server ID via the host
field:
POST /ServerManage/GetAccountsForLogin
{
"domainOnly":"false",
"filter":"",
"host":"abcdabcd-7461-4be6-982f-afb256770c3e",
"Args":{
"PageNumber":1,
"PageSize":100000,
"Limit":100000,
"SortBy":"",
"direction":"False",
"Caching":-1
}
}
The result contains information for each of the accounts on that system:
{
"success":true,
"Result":[
{
"accountId":"tyuityui-9fe3-4f2a-8924-0ca3b0f6de0b",
"name":"[email protected]",
"authority":"resource.centrify.com",
"authorityType":"AD",
"requestRequired":false
},
{
"accountId":"dddddddd-1d1d-473b-9ca4-cbc2d53b6061",
"name":"root",
"authority":"csssup-ubuntu",
"authorityType":"Local",
"requestRequired":false
}
],
"Message":null,
"MessageID":null,
"Exception":null,
"ErrorID":null,
"ErrorCode":null,
"InnerExceptions":null
}
Try the API in Postman:
.
Click here for help with using our sample Postman collection.
Step 6. Get the Server Session
Now that the ID of the system and login account have been acquired, the next step is to acquire the HTML code necessary to start session and display a browser window so the user can access the remote system.
Invoke the /serversession/jumpterm endpoint setting the mode
parameter to 1. Pass the account ID via the pvacct
query parameter and the system ID via the host
query parameter:
GET /serversession/jumpterm?mode=1&pvacct=dddddddd-1d1d-473b-9ca4-cbc2d53b6061&hostname=csssup-ubuntu&height=480&width=640&debug=false&token=&host=abcdabcd-7461-4be6-982f-afb256770c3e&colrows=&title=Login%20session%20csssup-ubuntu
The response contains the HTML indicating how to render the remote terminal window
HTTP/1.1 200 OK
Cache-Control: private
Content-Type: text/html; charset=utf-8
Vary: Accept-Encoding
X-CFY-TX-PN: Pod9
X-CFY-TX-ID: 5da94240bbc84fcf8056175b532f634c
X-CFY-TX-DT: Mi8xMi8yMDE4IDU6MTk6MjUgUE0_
X-Frame-Options: SAMEORIGIN
P3P: CP="NON COR ADMa CURa DEVa OUR IND COM UNI NAV INT PRE LOC ONL PHY STA ONL"
X-CFY-TX-TM: 157
Set-Cookie: antixss=k7fkHgxR28e_LmPvaWG4Fg__-HWPt3M1f5gWW3BT7bxuDag__-dImPD1A3pR_0xIXnkZ21Tw__-WrUho88cTg_DtvESULbtgA__-LS971c84V3ycyD4qIcxHeQ__-bPcBoJBIzWH3zMb54gPmBA__-n6WNZMK9lcgEq6K_R_Z22w__-ilI45jB0S4IdTwakrYuf7w__; path=/; secure
Set-Cookie: sessdata=L3dVSF...; path=/; secure; HttpOnly
Set-Cookie: podloc=eyJkZXZkb2cuY...; domain=centrify.com; expires=Fri, 31-Dec-9999 23:59:59 GMT; path=/; secure
Set-Cookie: userdata=eyJEYXR...; expires=Wed, 14-Mar-2018 17:19:25 GMT; path=/; secure
X-Robots-Tag: noindex, nofollow
Date: Mon, 12 Feb 2018 17:19:25 GMT
Content-Length: 4346
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=8,9,10" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<link rel="shortcut icon"/>
<link rel="stylesheet" type="text/css" href="/vfslow/lib/ui/../uibuild/compiled/centrify/production/resources/centrify-all_01.css?_ver=1518281911"/>
<link rel="stylesheet" type="text/css" href="/vfslow/lib/ui/../uibuild/compiled/centrify/production/resources/centrify-all_02.css?_ver=1518281911"/>
<link rel="stylesheet" type="text/css" href="/vfslow/lib/ui/../uibuild/compiled/centrify/production/resources/centrify-all_03.css?_ver=1518281911"/>
<style>
.x-viewport body{
overflow: hidden !important;
background-color: #000;
}
</style>
<script src="/vfslow/lib/ui/jsutil/resources/locale/en.js?_ver=1518281911"></script>
<script src="/vfslow/lib/ui/jsutil/resources/locale/en.js?_ver=1518281911"></script>
<link href='/vfslow/lib/ui/../uibuild/compiled/jsutil/production/resources/fonts/Roboto.css?_ver=1518281911' rel='stylesheet' type='text/css'>
<link href='/vfslow/lib/ui/../uibuild/compiled/centrify/production/resources/fonts/Icon-Set.css?_ver=1518281911' rel='stylesheet' type='text/css'>
<script type="text/javascript">
var ServerConfig = {
ResourceBase: "/vfslow/lib/ui/",
ExtLocation: "/vfslow/lib/ui//ext/src",
DisableCacheSetting: false,
LoadBase: "/vfslow/lib/ui/",
Version: "1518281911",
AppBase:"1518281911",
SkinDef: {"themeColor":"#363a40","theme":"centrify","adminRegisTxtCSSCls":"","cssDirectory":"compiled/centrify/production/resources","emailImage":"/logos/logo-centrify-1.png","footer":{"termsUrl":"https://www.centrify.com/eula/","termsText":"footer_term","privacyText":"footer_policy","copyrightText":"© 2004-{0} Centrify Corporation.","privacyUrl":"https://www.centrify.com/privacypolicy.asp"},"navigationColor":"#979797","loginCssDirectory":"compiled/jsutil/production/resources","backgroundColor":"#FFFFFF","newHelpRoot":"{helpRootServer}/","pageIcon":"/logos/centrify-16-1.png","proxy":{"download64Bit":"Cloud-Management-Suite-win64.zip"},"helpDirectoryBrandName":"","mfa":{"waitGif":"/ellipses_anim.gif","stepsFolder":"/steps/"},"loginImage":"/logos/centrify-breach-stops-here.png","macEnrollDialogImage":"/enroll/centrify-macs.png","brand":"centrify","helpRoot":"{helpRootServer}/{1}/centrify/{2}/index.html","name":"Centrify","portalImage":"/logos/centrify-main-logo.png","aboutWindowIcon":"/logos/centrify-main-logo.png"},
droppedPacketThreshold: 25,
droppedPacketThresholdTime: 120,
heartBeatTime: 5,
useFastForwardOnDrop: true,
continueOnDropped: true,
sendFailureCountLimit: 200,
challengeSessionId: "LHUUVpHKsU-8vxxJzcVGNUiuhdNmw4DIKEWfGmW475w1",
MissingBuildFilesFail: false,
signalRTransport: "auto",
ManDef: {}
};
window.Jsutil = window.Jsutil || {};
//Do not show login automatically when we utilize jsutil.
Jsutil.bypassLogin = true;
</script>
<script src="/vfslow/lib/ui/jsutil/external/term.js?_ver=1518281911"></script>
<script src="/vfslow/lib/ui/../uibuild/compiled/jsutil/production/app.js?_ver=1518281911"></script>
<style type="text/css">
html {
height: 100%;
}
body {
height:100%;
font-size: 12px;
background: black;
}
.no-script-alert {
background: #fff;
text-align: left;
padding: 10px 20px 10px 45px;
border-top: 2px solid #ffd324;
border-bottom: 2px solid #ffd324;
}
</style>
<script type="text/javascript" src="/vfslow/lib/ui/terminals/ssh.js?_ver=1518281911"></script>
</head>
<body>
</body>
</html>
Step 7. Negotiate an SSH session
Negotiate an SSH session terminal by invoking the /signalr/negotiate endpoint:
GET /signalr/negotiate?clientProtocol=1.5&connectionData=%5B%7B%22name%22%3A%22sshtermhub%22%7D%5D&_=1518455965170 HTTP/1.1
The response contains information about the connection including a unique ConnectionToken
for use in subsequent API calls:
{
"Url":"/signalr",
"ConnectionToken":"VYIL...",
"ConnectionId":"deea698f-2d47-4bb8-9301-8adabac6bbb1",
"KeepAliveTimeout":20.0,
"DisconnectTimeout":30.0,
"ConnectionTimeout":110.0,
"TryWebSockets":true,
"ProtocolVersion":"1.5",
"TransportConnectTimeout":5.0,
"LongPollDelay":0.0
}
Step 8. Connect to the SSH Session
Connect to the remote SSH session by invoking the /signalr/connect endpoint and pass the token returned from the /signalr/negotiate
endpoint via the ConnectionToken
query parameter:
GET /signalr/connect?transport=webSockets&clientProtocol=1.5&connectionToken=VYIL...&connectionData=%5B%7B%22name%22%3A%22sshtermhub%22%7D%5D&tid=6 HTTP/1.1
The response contains information about the connection including the number of bytes sent and received:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Server: Microsoft-IIS/10.0
X-Content-Type-Options: nosniff
Sec-WebSocket-Accept: J9RUnHzBXXnP29a2L5E2tmVxkoA=
Connection: Upgrade
X-Robots-Tag: noindex, nofollow
Date: Mon, 12 Feb 2018 17:19:25 GMT
EndTime: 09:19:53.134
ReceivedBytes: 622
SentBytes: 201
Step 9. Start the SSH Session
Start the SSH session by invoking the /signalr/start endpoint and pass the token returned from the /signalr/negotiate
endpoint via the ConnectionToken
query parameter:
GET /signalr/start?transport=webSockets&clientProtocol=1.5&connectionToken=VYIL...&connectionData=%5B%7B%22name%22%3A%22sshtermhub%22%7D%5D&_=1518455965171 HTTP/1.1
The response indicates that the session was started:
{
"Response":"started"
}
Updated about 5 years ago