Device Migration API Postman Collection

Disclaimer: This information is provided as-is for the benefit of the Community. Please contact Sophos Professional Services if you require assistance with your specific environment.


Overview

This sample script gives you an easy start when using Sophos Endpoint API for device migration between Sophos Central accounts.

https://docs.sophos.com/central/Customer/help/en-us/ManageYourProducts/Overview/GlobalSettings/DeviceMigration/index.html

What to do

Save the following as "Sophos Central Device Migration.postman_collection.json"

{
	"info": {
		"_postman_id": "43aeba01-038e-45dc-b4a3-fc44e60b63db",
		"name": "Sophos Central Device Migration",
		"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
	},
	"item": [
		{
			"name": "Step 1 - Authentication",
			"item": [
				{
					"name": "Source: Authenticate",
					"event": [
						{
							"listen": "test",
							"script": {
								"exec": [
									"var jsonData = JSON.parse(responseBody);",
									"pm.collectionVariables.set(\"SourceAccessToken\", jsonData.access_token);"
								],
								"type": "text/javascript"
							}
						}
					],
					"request": {
						"auth": {
							"type": "noauth"
						},
						"method": "POST",
						"header": [],
						"body": {
							"mode": "urlencoded",
							"urlencoded": [
								{
									"key": "grant_type",
									"value": "client_credentials",
									"type": "text"
								},
								{
									"key": "scope",
									"value": "token",
									"type": "text"
								},
								{
									"key": "client_id",
									"value": "{{SourceClientID}}",
									"type": "text"
								},
								{
									"key": "client_secret",
									"value": "{{SourceClientSecret}}",
									"type": "text"
								}
							]
						},
						"url": {
							"raw": "https://id.sophos.com/api/v2/oauth2/token",
							"protocol": "https",
							"host": [
								"id",
								"sophos",
								"com"
							],
							"path": [
								"api",
								"v2",
								"oauth2",
								"token"
							]
						}
					},
					"response": []
				},
				{
					"name": "Source: Who am I?",
					"event": [
						{
							"listen": "test",
							"script": {
								"exec": [
									"pm.test(\"Status code is 200\", function () {",
									"    pm.response.to.have.status(200);",
									"    ",
									"    pm.test(\"Save ID and api host\", function () {",
									"        var jsonData = pm.response.json();",
									"",
									"        pm.collectionVariables.set(\"SourceTenantID\", jsonData.id);",
									"        pm.collectionVariables.set(\"SourceDataRegion\", jsonData.apiHosts.dataRegion.slice(12, 16));",
									"    });",
									"});",
									""
								],
								"type": "text/javascript"
							}
						}
					],
					"request": {
						"auth": {
							"type": "bearer",
							"bearer": [
								{
									"key": "token",
									"value": "{{SourceAccessToken}}",
									"type": "string"
								}
							]
						},
						"method": "GET",
						"header": [],
						"url": {
							"raw": "https://api.central.sophos.com/whoami/v1",
							"protocol": "https",
							"host": [
								"api",
								"central",
								"sophos",
								"com"
							],
							"path": [
								"whoami",
								"v1"
							]
						},
						"description": "Returns information about the caller."
					},
					"response": []
				},
				{
					"name": "Target: Authenticate",
					"event": [
						{
							"listen": "test",
							"script": {
								"exec": [
									"var jsonData = JSON.parse(responseBody);",
									"pm.collectionVariables.set(\"TargetAccessToken\", jsonData.access_token);"
								],
								"type": "text/javascript"
							}
						}
					],
					"request": {
						"auth": {
							"type": "noauth"
						},
						"method": "POST",
						"header": [],
						"body": {
							"mode": "urlencoded",
							"urlencoded": [
								{
									"key": "grant_type",
									"value": "client_credentials",
									"type": "text"
								},
								{
									"key": "scope",
									"value": "token",
									"type": "text"
								},
								{
									"key": "client_id",
									"value": "{{TargetClientID}}",
									"type": "text"
								},
								{
									"key": "client_secret",
									"value": "{{TargetClientSecret}}",
									"type": "text"
								}
							]
						},
						"url": {
							"raw": "https://id.sophos.com/api/v2/oauth2/token",
							"protocol": "https",
							"host": [
								"id",
								"sophos",
								"com"
							],
							"path": [
								"api",
								"v2",
								"oauth2",
								"token"
							]
						}
					},
					"response": []
				},
				{
					"name": "Target: Who am I?",
					"event": [
						{
							"listen": "test",
							"script": {
								"exec": [
									"pm.test(\"Status code is 200\", function () {",
									"    pm.response.to.have.status(200);",
									"    ",
									"    pm.test(\"Save ID and api host\", function () {",
									"        var jsonData = pm.response.json();",
									"",
									"        pm.collectionVariables.set(\"TargetTenantID\", jsonData.id);",
									"        pm.collectionVariables.set(\"TargetDataRegion\", jsonData.apiHosts.dataRegion.slice(12, 16));",
									"           ",
									"    });",
									"});",
									""
								],
								"type": "text/javascript"
							}
						}
					],
					"request": {
						"auth": {
							"type": "bearer",
							"bearer": [
								{
									"key": "token",
									"value": "{{TargetAccessToken}}",
									"type": "string"
								}
							]
						},
						"method": "GET",
						"header": [],
						"url": {
							"raw": "https://api.central.sophos.com/whoami/v1",
							"protocol": "https",
							"host": [
								"api",
								"central",
								"sophos",
								"com"
							],
							"path": [
								"whoami",
								"v1"
							]
						},
						"description": "Returns information about the caller."
					},
					"response": []
				}
			],
			"auth": {
				"type": "noauth"
			},
			"event": [
				{
					"listen": "prerequest",
					"script": {
						"type": "text/javascript",
						"exec": [
							""
						]
					}
				},
				{
					"listen": "test",
					"script": {
						"type": "text/javascript",
						"exec": [
							""
						]
					}
				}
			]
		},
		{
			"name": "Step 2 - Source: Get List of Endpoints",
			"event": [
				{
					"listen": "test",
					"script": {
						"exec": [
							"let response = pm.response.json(),\r",
							"    ids = _.map(response.items, ({ id }) => ( id )); \r",
							"\r",
							"pm.collectionVariables.set('EndpointList', JSON.stringify(ids));\r",
							""
						],
						"type": "text/javascript"
					}
				}
			],
			"request": {
				"auth": {
					"type": "bearer",
					"bearer": [
						{
							"key": "token",
							"value": "{{SourceAccessToken}}",
							"type": "string"
						}
					]
				},
				"method": "GET",
				"header": [
					{
						"description": "(Required) Tenant ID.",
						"key": "X-Tenant-ID",
						"value": "{{SourceTenantID}}"
					}
				],
				"url": {
					"raw": "https://api-{{SourceDataRegion}}.central.sophos.com/endpoint/v1/endpoints?fields=id,hostname",
					"protocol": "https",
					"host": [
						"api-{{SourceDataRegion}}",
						"central",
						"sophos",
						"com"
					],
					"path": [
						"endpoint",
						"v1",
						"endpoints"
					],
					"query": [
						{
							"key": "fields",
							"value": "id,hostname"
						},
						{
							"key": "hostnameContains",
							"value": "WIN",
							"disabled": true
						}
					]
				},
				"description": "Get all the endpoints for the specified tenant."
			},
			"response": []
		},
		{
			"name": "Step 3 - Target: Start Receiver Task",
			"event": [
				{
					"listen": "test",
					"script": {
						"exec": [
							"var jsonData = pm.response.json();\r",
							"\r",
							"pm.collectionVariables.set(\"MigrationID\", jsonData.id);\r",
							"pm.collectionVariables.set(\"MigrationToken\", jsonData.token);"
						],
						"type": "text/javascript"
					}
				}
			],
			"request": {
				"auth": {
					"type": "bearer",
					"bearer": [
						{
							"key": "token",
							"value": "{{TargetAccessToken}}",
							"type": "string"
						}
					]
				},
				"method": "POST",
				"header": [
					{
						"description": "(Required) Tenant ID.",
						"key": "X-Tenant-ID",
						"value": "{{TargetTenantID}}"
					},
					{
						"key": "Content-Type",
						"value": "application/json"
					}
				],
				"body": {
					"mode": "raw",
					"raw": "{\n    \"fromTenant\": \"{{SourceTenantID}}\",\n    \"endpoints\": {{EndpointList}}\n}"
				},
				"url": {
					"raw": "https://api-{{TargetDataRegion}}.central.sophos.com/endpoint/v1/migrations",
					"protocol": "https",
					"host": [
						"api-{{TargetDataRegion}}",
						"central",
						"sophos",
						"com"
					],
					"path": [
						"endpoint",
						"v1",
						"migrations"
					]
				},
				"description": "Adds a new local site."
			},
			"response": []
		},
		{
			"name": "Step 4 - Source: Start Migration Job",
			"event": [
				{
					"listen": "test",
					"script": {
						"exec": [
							""
						],
						"type": "text/javascript"
					}
				}
			],
			"request": {
				"auth": {
					"type": "bearer",
					"bearer": [
						{
							"key": "token",
							"value": "{{SourceAccessToken}}",
							"type": "string"
						}
					]
				},
				"method": "PUT",
				"header": [
					{
						"description": "(Required) Tenant ID.",
						"key": "X-Tenant-ID",
						"value": "{{SourceTenantID}}"
					},
					{
						"key": "Content-Type",
						"value": "application/json"
					}
				],
				"body": {
					"mode": "raw",
					"raw": "{\n    \"token\": \"{{MigrationToken}}\",\n    \"endpoints\": {{EndpointList}}\n}\n"
				},
				"url": {
					"raw": "https://api-{{SourceDataRegion}}.central.sophos.com/endpoint/v1/migrations/{{MigrationID}}",
					"protocol": "https",
					"host": [
						"api-{{SourceDataRegion}}",
						"central",
						"sophos",
						"com"
					],
					"path": [
						"endpoint",
						"v1",
						"migrations",
						"{{MigrationID}}"
					]
				},
				"description": "Adds a new local site."
			},
			"response": []
		},
		{
			"name": "Step 5 - Target: Check Migration Status",
			"event": [
				{
					"listen": "test",
					"script": {
						"exec": [
							""
						],
						"type": "text/javascript"
					}
				}
			],
			"request": {
				"auth": {
					"type": "bearer",
					"bearer": [
						{
							"key": "token",
							"value": "{{TargetAccessToken}}",
							"type": "string"
						}
					]
				},
				"method": "GET",
				"header": [
					{
						"key": "X-Tenant-ID",
						"value": "{{TargetTenantID}}",
						"type": "default"
					}
				],
				"url": {
					"raw": "https://api-{{TargetDataRegion}}.central.sophos.com/endpoint/v1/migrations/{{MigrationID}}/endpoints",
					"protocol": "https",
					"host": [
						"api-{{TargetDataRegion}}",
						"central",
						"sophos",
						"com"
					],
					"path": [
						"endpoint",
						"v1",
						"migrations",
						"{{MigrationID}}",
						"endpoints"
					]
				},
				"description": "Returns information about the caller."
			},
			"response": []
		}
	],
	"event": [
		{
			"listen": "prerequest",
			"script": {
				"type": "text/javascript",
				"exec": [
					""
				]
			}
		},
		{
			"listen": "test",
			"script": {
				"type": "text/javascript",
				"exec": [
					""
				]
			}
		}
	],
	"variable": [
		{
			"key": "SourceClientID",
			"value": "",
			"type": "default"
		},
		{
			"key": "SourceClientSecret",
			"value": "",
			"type": "default"
		},
		{
			"key": "TargetClientID",
			"value": "",
			"type": "default"
		},
		{
			"key": "TargetClientSecret",
			"value": "",
			"type": "default"
		}
	]
}

Open the file in Postman and replace any necessary fields.



Updated link
[edited by: Qoosh at 4:25 PM (GMT -7) on 11 Oct 2024]
Parents
  • When I run this in Postman, I get to the point where I am creating the migration task and get the response "Forbidden". I am migrating from one sub-estate to another within the same organization. What could be the problem?

  • No, that should not be the issue. Possible reasons I can think of are:

    • your authentication token for the source is expired, authentication tokens are valid for 60 minutes
    • you are using API credentials from the Enterprise Dashboard, with the Postman collection you need to use credentials created within the tenant 
    • "Allow device migration" is not active in the source account

    For more details see: https://developer.sophos.com/endpoint-migrations.

  • Hi, thanks for ideas.

    1 - This was all done in the space of 10 minutes within postman, so the tokens should be good

    2 - I was using enterprise dashboard credentials before. However following the postman flow and using separate tenant credentials for the source and destination tenants did not help

    3 - Device migration is enabled indefinately for all tenants

    Any other ideas?

  • Unfortunately no. I just used the Postman collection in my own test environment and successfully migrated a device from one tenant to the other.

    I only get a forbidden, at Step 4 when Device Migration is not enabled in the Source account. But in that case it will also show you the reason why its not allowed, see example below:

    {
        "error": "forbidden",
        "correlationId": "a4535e0f-2d35-46c7-b5b7-0debaab25160",
        "requestId": "6ee51443-1de3-4933-92df-2ebfdfd21001",
        "message": "Endpoint Migration is not enabled"
    }


    If it is only a small number of devices that you have to migrate then a manual migration might be an option, you could download the SophosSetup installer from the target account and run that one on the devices with the paremeter --registeronly. Just make sure that you deactivate Tamper Protection before doing so.

    If it is concerning a larger number of devices then I would recommend opening a support case.

Reply
  • Unfortunately no. I just used the Postman collection in my own test environment and successfully migrated a device from one tenant to the other.

    I only get a forbidden, at Step 4 when Device Migration is not enabled in the Source account. But in that case it will also show you the reason why its not allowed, see example below:

    {
        "error": "forbidden",
        "correlationId": "a4535e0f-2d35-46c7-b5b7-0debaab25160",
        "requestId": "6ee51443-1de3-4933-92df-2ebfdfd21001",
        "message": "Endpoint Migration is not enabled"
    }


    If it is only a small number of devices that you have to migrate then a manual migration might be an option, you could download the SophosSetup installer from the target account and run that one on the devices with the paremeter --registeronly. Just make sure that you deactivate Tamper Protection before doing so.

    If it is concerning a larger number of devices then I would recommend opening a support case.

Children
No Data