
Thanks to this article, you will learn how to use the API.
SUMMARY
Limitations
- In the event of a large number of results, the API retrieves a maximum of 50 results per page. You must use the pagination system to access the other results.
- At present, our API is in pull mode only.
API Authentication
Authentication by API key (recommended)
Step 1 : Generate an API key
An API key (also called token) is an alternative credential to the login/password pair.
It must be generated in the user settings.
- To access these settings, go to the top right of the Portal interface (on your initials) and click on Account settings
- Click on the Security tab.
Requests using the API key will run in the user's context, therefore with identical accesses.
Step 2 : lnclude the key into the request header
The API key must be included in the Authorization header (with type Bearer) :
Authorization: Bearer <API key>
The request should have the following structure, and contain the Authorization header:
GET /api/user/current HTTP/1.1 Host: leportail.xmco.com Authorization: Bearer xxxxxxxxxxxxxxxxxxx
Here is an example of a cUrl request :
curl -H "Authorization: Bearer xxxxxxxxxxxxxxxxxxx" 'https://leportail.xmco.fr/api/user/current'
When API key authentication is used, the second factor is not required (if enabled)
Conventional Authentication
Step 1 : Get a session cookie via HTTP request
You need to make a HTTP POST request to https://leportail.xmco.fr/api/authenticate
The request should have the following structure:
POST /api/authenticate HTTP/1.1 Host: leportail.xmco.fr Content-Type: application/json Content-Length: 76 Connection: close {"username": "value", "password": "password"}
Here is an example of a cUrl request :
curl -i -d '{"username": "value", "password": "password"}' -H "Content-Type: application/json" -X POST 'https://leportail.xmco.fr/api/authenticate'
The response to this request will include a session cookie, identified as XMSESSION.
- It must be sent to the API for each request.
- To do this, the request must include a header Cookie of the form XMSESSION=xxxxx.
Step 2 : Use the session cookie to validate the MFA (optional)
If two-factor authentication is enabled, an additional request to https://leportail.xmco.fr/api/validate_otp is necessary.
The session cookie retrieved from the request to https://leportail.xmco.fr/api/authenticate will have to be included in this request, which will have the following structure:
POST /api/validate_otp HTTP/1.1 Host: leportail.xmco.fr Content-Type: application/json Content-Length: 76 Connection: close Cookie: XMSESSION=xxxxxxxxxx {"otp": "the code received by SMS"}
Here is an example of a cUrl request :
curl -i -d '{"otp": "the code received by SMS"}' -H "Content-Type: application/json" -H "Cookie: XMSESSION=xxxxxxxxxx" -X POST 'https://leportail.xmco.fr/api/validate_otp'
The response to this request will include the session cookie that must be sent to the API for each request.
The session cookie retrieved from the request to https://leportail.xmco.fr/api/authenticate will no longer be used.
Step 3 : Use our API with the help of the session cookie customized to your authentication mode
For all your subsequent requests, you will need to include a cookie header of the form XMSESSION=xxxxx.
- If you are in classic authentication, use the session cookie retrieved in step 1;
- If you are in multi-factor authentication, use the session cookie retrieved in step 2.
Action plan
Get the list of tickets assigned to me
Step 1 : Obtain your user ID (user_id)
This identifier will allow you to filter the tickets assigned to you. It is contained in the user._id field obtained by a GET request to https://leportail.xmco.fr/api/user/current.
Here is an example of a cUrl request :
curl -H "Content-Type: application/json" -H "Cookie: XMSESSION=xxxxxxxxxx" 'https://leportail.xmco.fr/api/user/current'
The response will have the following structure:
Step 2 : Get the list of tickets assigned to me
This list can be obtained via a GET request to https://leportail.xmco.fr/api/action_plan/list and by specifying the argument assignee_id with the identifier obtained previously.
Here is an example of a cUrl request :
curl -G -g -H "Content-Type: application/json" -H "Cookie: XMSESSION=xxxxxxxxxx" 'https://leportail.xmco.fr/api/action_plan/list' --data-urlencode 'assignee_id=55ca2585f2c3425976c28abf'
The response will have the following structure:
For detailed explanation of the fields, please refer to the following explanations :
- _created : creation date
- _updated : date of the last modification
- assignee : id of the assigned user
- company : id of your company
- custom fields : list of custom fields. For serenety alerts, you will have the following custom fields :
- category
- subcategory
- identification (manual or automatic)
- scope (passive or active)
- description : description of the ticket
- description_format : format of the description (html or plain text)
- impact : only useful for pentests
- is_open : if the ticket is open (true/false)
- closed_on : date the ticket was closed (if is_open = false)
- severity (low, medium, high)
- status (new, in progress, pending, resolved)
- title
- tracker
- type
Access the tickets/alerts list of your company
Step 1 : Obtain your company ID (company_id)
This identifier is contained in the field user.company
obtained by a request GET
to the url https://leportail.xmco.fr/api/user/current
.
Here is an example of the cUrl request:
curl -H "Content-Type: application/json" -H "Cookie: XMSESSION=xxxxxxxxxx" 'https://leportail.xmco.fr/api/user/current'
The response will have the following structure :
Step 2 : Get the list of the company's tickets/alerts
This list can be obtained via a request GET
to the url https://leportail.xmco.fr/api/action_plan/list
specifying the argument company_id
with the identifier obtained previously.
The results returned are limited according to your access rights! If no filter is applied, the result can therefore be voluminous. Use the pagination (50)
Here is an example of the cUrl request for Serenety alerts :
curl -g -XPOST -H "Content-Type: application/json" -H "Cookie: XMSESSION=xxxxxxxxxx" 'https://leportail.xmco.fr/api/tracker/by_company' --data '{"module":"serenety","company_id":"55ca2584f2c3425976c28aa4"}'
The response will have the following structure:
Access tickets linked to a particular product (Serenety, Yuno, Pentest)
Step 1 : Obtain your company ID (company_id)
See above.
Step 2 : Obtain trackers IDs
As this list may be subject to change, we propose you to recover it dynamically.
This list can be obtained via a request POST
to the url https://leportail.xmco.fr/api/tracker/by_company
by specifying the argument company_id
with the identifier obtained previously and with one of the following values for the parameter module
: watch
, serenety
or pentest
.
We can thus extract the list of tracker identifiers, contained in the field _id
of each document on the list returned by the API.
The parameter queryExtras
supports the MongoDB syntax.
Various filters are available, including :
- open tickets :
"is_open":{"$eq":true}
the "New" or "In progress":
"status":{"$in":["new","in_progress"]}
the creation date :
"_created":{"$gt":"2019-07-31T22:00:00.000Z"}
Here is an example of the cUrl request for Serenety alerts :
curl -g -XPOST -H "Content-Type: application/json" -H "Cookie: XMSESSION=xxxxxxxxxx" 'https://leportail.xmco.fr/api/tracker/by_company' --data '{"module":"serenety","company_id":"55ca2584f2c3425976c28aa4"}'
The response will have the following structure :
Step 3 : Get the list of tickets associated with a product
This list can be obtained via a GET request to the url https://leportail.xmco.fr/api/action_plan/list specifying the argument company_id with the identifier obtained previously and by setting the queryExtras argument with the desired filter.
In our specific case, we will use the following syntax :
'tracker':{'$in': ['list of tracker IDs previously retrieved']}
Here is an example of the cUrl request :
curl -G -g -H "Content-Type: application/json" -H "Cookie: XMSESSION=xxxxxxxxxx" 'https://leportail.xmco.fr/api/action_plan/list' -- data-urlencode 'queryExtras={"tracker":{"$in":["5ca6019ff44a43003f808ffd","5ca6019ff44a43003f808ffe"]}}' --data-urlencode 'company_id=55ca2584f2c3425976c28aa4'
The response will have the following structure :
Update an action ticket / alert
Step 1 :Obtain the identifier and the etag of the ticket / alert
This information can be found in the fields _id and _etag, obtained via the queries previously described.
Step 2 : Update the ticket / alert
An update consists of a request PATCH to the url https://leportail.xmco.fr/api/action_plan/xxxxxxxxx. This request must contain the `etag` in its header "If-Match" as well as the modifications in the form of a dictionary.
Here is an example of the cUrl request :
curl -g -X PATCH -H "Content-Type: application/json" -H "Cookie: XMSESSION=xxxxxxxxxx" -H "If-Match: etag" 'https://leportail.xmco.fr/api/action_plan/xxxxxxxxx' --data '{"severity":"low","status":"in_progress"}'
The response will have the following structure :
Add a comment to an alert/action ticket
Step 1 :Obtain the identifier and the etag of the ticket / alert
This information can be found in the fields _id and _etag, obtained via the queries previously described.
Step 2 : Update the ticket / alert
Adding a comment consists of a request PATCH to https://leportail.xmco.fr/api/action_plan/xxxxxxxxx. This request must contain the `etag` in its header "If-Match" as well as the modifications in the form of a dictionary.
Here is an example of the cUrl request :
Retrieve files from alert/action ticket
Step 1 :Obtain the identifier and the etag of the ticket / alert
This information can be found in the fields _id and _etag, obtained via the queries previously described.
Step 2 : Get the file(s)
Here's an exemple of a GET request (where {{id_actionticket}} must be replaced by the previously obtained _id):
Here is an example of the answer format :
Recovery of Yuno bulletins
Data format
The YUNO advisories can be retrieved by making a request GET towards https://leportail.xmco.fr/api/advisory.curl -H "Content-Type: application/json" -H "Cookie: XMSESSION=xxxxxxxxxx" 'https://leportail.xmco.fr/api/advisory'
- Example of an INFO bulletin :
- Example of a PATCH bulletin :
Search filters
It is possible to apply search filters using the parameter where . The format to be applied is that of MongoDB requests. All MongoDB operations are supported, with the exception of operators $regex and $where.
The following requests are all examples of search filters :
- Return only INFO advisories
curl -g -H "Content-Type: application/json" -H "Cookie: XMSESSION=xxxxxxxxxx" 'https://leportail.xmco.fr/api/advisory' --data-urlencode 'where={"advisory_type":"INFO"}'
- Return only advisories published between 8 and 22 February 2018 (dates follow the RFC2822 format)
curl -g -H "Content-Type: application/json" -H "Cookie: XMSESSION=xxxxxxxxxx" 'https://leportail.xmco.fr/api/advisory' --data-urlencode 'where={"_created":{"$gte":"Thu, 8 Feb 2018 00:00:00 GMT","$lte":"Thu, 22 Feb 2018 00:00:00 GMT"}}'
- Return only High severity advisories
curl -g -H "Content-Type: application/json" -H "Cookie: XMSESSION=xxxxxxxxxx" 'https://leportail.xmco.fr/api/advisory' --data-urlencode 'where={"severity":"high"}'
- Return only advisories about Debian
curl -g -H "Content-Type: application/json" -H "Cookie: XMSESSION=xxxxxxxxxx" 'https://leportail.xmco.fr/api/advisory' --data-urlencode 'where={"cpe_names":"55ca2587f2c3425976c28d8d"}'
- Return only advisories about Wordpress, with severity greater or equal to "Medium" and published since 8 February 2023
curl -g -H "Content-Type: application/json" -H "Cookie: XMSESSION=xxxxxxxxxx" 'https://leportail.xmco.fr/api/advisory' --data-urlencode 'where={"cpe_names":"55ca2586f2c3425976c28d43","severity":{"$in":["urgent","high","medium"]},"_created":{"$gte":"Thu, 8 Feb 2023 00:00:00 GMT"}}
Retrieving the identifier of a technology
As illustrated in the sample requests, it is possible to apply filters to retrieve advisories for a particular technology. For this purpose, it is necessary to know the identifier of the technology in question.
It is possible to search for a technology from its name by making a query GET to the endpoint cpename.
For example, if you wish to obtain information on the technology Wordpress:
curl -H "Content-Type: application/json" -H "Cookie: XMSESSION=xxxxxxxxxx" 'https://leportail.xmco.fr/api/cpename' --data-urlencode 'where={"name":"Wordpress"}'
It will return the following document :
The list of documents validating the search filters is in the list _items. Each of these documents has a field _id which contains the identifier of the element.
In the previous example, only one technology with the name Wordpress has been reassembled. Its identifier is
55ca2586f2c3425976c28d43. Technology bulletins Wordpress can therefore be recovered with the following filter :
/advisory?where={"cpe_names":"55ca2586f2c3425976c28d43"}
Paging
The returned results by the API are paginated.
- By default, each page contains 25 results (up to 50 can be obtained using the parameter max_results ).
- It is possible to navigate from page to page using the parameter page :
/advisory?page=2 , /advisory?page=3 , etc.
Asset recovery
It is possible to retrieve the assets processed by Serenety by making a request GET towards https://leportail.xmco.fr/api/serenety/asset.
Here is an example of a cUrl request to retrieve assets :
curl -H "Content-Type: application/json" -H "Cookie: XMSESSION=xxxxxxxxxx" 'https://leportail.xmco.fr/api/serenety/asset'
Another example of a cUrl request to return only the IP addresses :
curl -g -H "Content-Type: application/json" -H "Cookie: XMSESSION=xxxxxxxxxx" 'https://leportail.xmco.fr/api/serenety/asset' --data-urlencode 'where={"type":"ipv4"}'
The returned documents will have the following structure (example for a Serenety asset) :
The data structure of these properties may change. The content of each property depends on the information available about the asset.
Search filters
- Return only the IP addresses :
/serenety/asset' --data-urlencode 'where={"type": "ipv4"}'
- Return only the asset 'xmco.fr'(it will be always contained in the _items list) :
/serenety/asset' --data-urlencode 'where={"value":"xmco.fr"}'
- Return only assets of which port 80 is exposed :
/serenety/asset' --data-urlencode 'where={"properties.ports.no": 80}'
- Return only the assets vulnerable to HeartBleed :
/serenety/asset' --data-urlencode 'where={"properties.ssllabs.vulns.heartbleed":true}'
List of available properties
- ssl_cert : SSL certificate information
- ssl_ciphers : Information on supported encryption algorithms
- ssl_protos : Information on supported SSL protocols
- ssllabs : SSLLabs Analysis Information
- ports : Information on the services on display
- axfr : Information on the configuration of the DNS zone transfer
- http_controls : HTTP configuration information
- dns_records : DNS configuration information
- vulns : Information on detected vulnerabilities
- domain_expiration : Domain Expiration Information
Was this article helpful?
That’s Great!
Thank you for your feedback
Sorry! We couldn't be helpful
Thank you for your feedback
Feedback sent
We appreciate your effort and will try to fix the article