The Patchman Portal API allows you to modify and update resources that you would otherwise have managed through the web interface.
The Portal API is organized around REST and designed to have predictable, resource-oriented URLs. We use built-in HTTP features, such as HTTP authentication, methods and response codes, that are understood by many HTTP clients. JSON is returned whenever possible, including in all errors.
Additionally, we have created a online web interface that allows you to explore the API with point-and-click. This interface is available from /api/v1/. The API is only available for plans featuring API access.
Unless specified otherwise in this documentation, you can simply use the operations listed to the right to access and modify objects. Not all operations are available on all resources, especially regarding which fields can be modified and which objects can be deleted. Searching is available in on a subset of fields (specified per resource) and only supports exact matches. Filters can be combined conjunctively.
In the case your client does not support e.g. PATCH
or DELETE
, you
can:
_method
field to your POST request.X-HTTP-Method-Override
header to your POST request.All code examples below assume you are requesting JSON data (which is at this time the only accepted format).
In a RESTful API, specific HTTP methods are used for specific actions.
When using PUT, you must specify a full resource representation as the request entity. Any properties that are omitted will be set to default values. Using PATCH will only update the resource with properties provided in the request entity.
GET /api/v1/{RESOURCE}/ - retrieve a list of objects GET /api/v1/{RESOURCE}/?{FIELD}={VALUE} - retrieve filtered list of objects POST /api/v1/{RESOURCE}/ - create a new object GET /api/v1/{RESOURCE}/{ID}/ - retrieve the object PUT /api/v1/{RESOURCE}/{ID}/ - replace the object PUT /api/v1/{RESOURCE}/{ID}/?{MODIFIER}={VALUE} - replace the object with modifiers PATCH /api/v1/{RESOURCE}/{ID}/ - update the object DELETE /api/v1/{RESOURCE}/{ID}/ - destroy the object
Pagination is off per default, but is encouraged to be used when requesting bigger datasets.
Depending on the size of your server and user base, some API calls can return thousands of results.
To enable pagination, provide a page_size
GET parameter.
The maximum number of results per page is 100.
As pagination provides extra values in the result to help you find the next and previous page,
the actual result is stored in the result
value.
The meta parameters are:
null
if this is the last page.
null
if this is the first page.
curl https://portal.patchman.co/api/v1/servers/?page_size=3
import requests requests.get("https://portal.patchman.co/api/v1/servers/", data={'page_size':3})
{ "count": 51, "next": "https://portal.patchman.co/api/v1/servergroups/?page=2&page_size=3", "previous": null, "results": [ { "id": 6, "url": "https://portal.patchman.co/api/v1/servergroups/6/", "name": "Default group", "language_override": "", "default_reseller_policy": "https://portal.patchman.co/api/v1/policies/6/", "default_user_policy": "https://portal.patchman.co/api/v1/policies/6/" }, { "id": 7, "url": "https://portal.patchman.co/api/v1/servergroups/7/", "name": "The other group", "language_override": "", "default_reseller_policy": "https://portal.patchman.co/api/v1/policies/7/", "default_user_policy": "https://portal.patchman.co/api/v1/policies/7/" }, { "id": 8, "url": "https://portal.patchman.co/api/v1/servergroups/8/", "name": "New group", "language_override": "", "default_reseller_policy": "https://portal.patchman.co/api/v1/policies/8/", "default_user_policy": "https://portal.patchman.co/api/v1/policies/8/" } ] }
Certain API end-points allow you to order their results by providing ordering
GET parameter.
The value should be a comma separated list of fields by which detections will be ordered. By default,
the order is ascending, if descending order is desired, the field must be prefix by a "-" sign.
As of now, only detections allow sorting, every type of detections below describes the possible fields for ordering.
curl https://portal.patchman.co/api/v1/detections/applications/?ordering=application,-detected_at
import requests requests.get("https://portal.patchman.co/api/v1/detections/applications/?ordering=application,-detected_at")
[ { "url": "https://portal.patchman.co/api/v1/detections/applications/25432354/", "path": "/home/username/domains/domain-4.com/public_html/", "detected_at": "2021-01-01T12:00:00Z", "end_user": "https://portal.patchman.co/api/v1/endusers/1/", "definition": { "id": 1, "application": "Application A", "version": "1.1", "up_to_date": true } }, { "url": "https://portal.patchman.co/api/v1/detections/applications/484263/", "path": "/home/username/domains/domain-2.com/public_html/", "detected_at": "2018-01-01T12:00:00Z", "end_user": "https://portal.patchman.co/api/v1/endusers/1/", "definition": { "id": 1, "application": "Application A", "version": "1.1", "up_to_date": true } }, { "url": "https://portal.patchman.co/api/v1/detections/applications/484262/", "path": "/home/username/domains/domain-1.com/public_html/", "detected_at": "2020-01-01T12:00:00Z", "end_user": "https://portal.patchman.co/api/v1/endusers/1/", "definition": { "id": 1, "application": "Application B", "version": "1.1", "up_to_date": true } }, { "url": "https://portal.patchman.co/api/v1/detections/applications/25432358/", "path": "/home/username/domains/domain-3.com/public_html/", "detected_at": "2019-01-01T12:00:00Z", "end_user": "https://portal.patchman.co/api/v1/endusers/1/", "definition": { "id": 1, "application": "Application B", "version": "1.1", "up_to_date": true } }, ]
The API's scope is by default limited to objects that fall directly under your organization's control.
In contrast, the Portal webinterface does provide access to objects owned by suborganizations by default,
so this may cause apparent differences between results shown in the webinterface and through the API.
However, there's a filter option available for all objects that allows you to show results that fall under a
particular suborganization. The filter field is suborganization
and it accepts the ID of the
suborganization.
Note that this filter is not available for the license key endpoint and suborganization endpoint, since those endpoints show suborganization results by default.
GET /api/v1/{RESOURCE}/?suborganization={ID} - retrieve objects for suborganization POST /api/v1/{RESOURCE}/?suborganization={ID} - create a new object for a suborganization GET /api/v1/{RESOURCE}/{ID}/?suborganization={ID} - retrieve the object for a suborganization PUT /api/v1/{RESOURCE}/{ID}/?suborganization={ID} - replace the object for a suborganization PATCH /api/v1/{RESOURCE}/{ID}/?suborganization={ID} - update the object for a suborganization DELETE /api/v1/{RESOURCE}/{ID}/?suborganization={ID} - destroy the object for a suborganization
In case your account is suspended, any request will give a HTTP 403 response and JSON from the example.
{ "error": "Your account is suspended" }
The API is primarily accessible using OAuth2 Authorization Code and Client Credentials grants. Both flows require you to create an application in the 'Apps' section of your account in the Portal web interface.
The Authorization Code grant type is the one you should pick when you want others to authenticate through your app. This is a flow you may already know from other websites: the client logs in using his own credentials at the Portal web interface and accepts the application access.
The Client Credentials grant type is suited for situations where you are the only user of your application and you want to access your account details using an API.
If your application is not suited for use of any of these grant types, Implicit and Resource Owner Password Credentials (legacy) grants are also available. Please contact support detailing why you need these types if this is applicable to your situation.
https://portal.patchman.co/oauth2/authorize/
https://portal.patchman.co/oauth2/token/
Independent of the OAuth grant type, you will receive an access token that can be used to authorize your requests in the HTTP header. The token type will (almost) always be 'Bearer', which can be used to set the HTTP Authorization request header.
The latter of this section will describe how you can obtain such a token for the two supported grant types. The implementation of the Portal matches most common OAuth2 implementations and conforms to RFC 6749. You should be able to use most OAuth2 libraries to authenticate with the Portal. The documentation that follows is intended for those not comfortable using a dedicated OAuth2 library.
curl https://portal.patchman.co/api/v1/ \ -H "Authorization: Bearer rBJVOkiV0Zv9O0B23HQwp4bgQVpyuB"
import requests requests.get("https://portal.patchman.co/api/v1/", headers={'Authorization': 'Bearer rBJVOkiV0Zv9O0B23HQwp4bgQVpyuB'})
Authentication using authorization codes consists of the following steps:
The first step in the authorization process is authentication of the user to the Portal and the authorization of the user for your application. This process starts by you, as client, redirecting the user to the authorization endpoint url, allowing you to provide the query parameters as specified below.
After authentication succeeds, the user is redirected to the redirect URI you specified
before, with the code
and state
query parameters added to the
URI. The provided authorization code is only valid for 60 seconds, requiring you to
exchange the code for an access token.
Redirect the user to
https://portal.patchman.co/oauth2/authorize/ ?response_type=code &client_id={CLIENT_ID} &state=some_random_string &scope=policy &redirect_uri=http://mysite.com
The user is redirected to
http://mysite.com ?code=x4cwG0Lz9dsFmyDpQip0rMT3FMatNY &state=some_random_string
To exchange the authorization code received in the previous step for a more permanent
access token, a POST request to the token endpoint should be made. This request is
authorized using HTTP Basic authentication, using your client_id
and
client_secret
as username and password (separated by a colon). Use the
following POST parameters:
authorization_code
in this case.
The response (in JSON) includes the expiration time of the token, the granted scopes, and an access token and refresh token.
curl https://portal.patchman.co/oauth2/token/ \ -u '{CLIENT_ID}:{CLIENT_SECRET}' \ -d grant_type=authorization_code \ -d code=x4cwG0Lz9dsFmyDpQip0rMT3FMatNY \ -d 'redirect_uri=http://mysite.com'
requests.post("https://portal.patchman.co/oauth2/token/", auth=("{CLIENT_ID}", "{CLIENT_SECRET}"), data={"grant_type": "authorization_code", "code": "x4cwG0Lz9dsFmyDpQip0rMT3FMatNY", "redirect_uri": "http://mysite.com"})
{ "expires_in": 36000, "scope": "policy", "access_token": "rBJVOkiV0Zv9O0B23HQwp4bgQVpyuB", "refresh_token": "5RrL9WqrwZ5rRHNT9tk1yxRqEDtU3z", "token_type": "Bearer" }
As we have seen before, an access token can expire. You also receive a refresh token that can be used to obtain a new access token. After executing this action, the original access and refresh token can not be used to obtain access to the account anymore.
refresh_token
in this case.
curl https://portal.patchman.co/oauth2/token/ \ -u '{CLIENT_ID}:{CLIENT_SECRET}' \ -d grant_type=refresh_token \ -d refresh_token=5RrL9WqrwZ5rRHNT9tk1yxRqEDtU3z
requests.post("https://portal.patchman.co/oauth2/token/", auth=("{CLIENT_ID}", "{CLIENT_SECRET}"), data={"grant_type": "refresh_token", "refresh_token": "5RrL9WqrwZ5rRHNT9tk1yxRqEDtU3z"})
{ "expires_in": 36000, "scope": "policy", "access_token": "75dhO6pzvRIpc4EbH9Tgz3bNIqgtfJ", "refresh_token": "Q5Bgj7K6lkbfnAcFNdUdqxdlSmUa0w", "token_type": "Bearer" }
Authentication using client credentials is significantly easier to implement, as it only involves the client authenticating with the Portal and receiving an access token. You can directly exchange your client id and client secret for an access token for your own account:
client_credentials
in this case.
The response (in JSON) includes the expiration time of the token, the granted scopes, and an access token and refresh token. The refresh token can be used in the same manner as with the authorization code grant type, although you could also simply reauthorize using the same method as described above.
curl https://portal.patchman.co/oauth2/token/ \ -u '{CLIENT_ID}:{CLIENT_SECRET}' \ -d grant_type=client_credentials
requests.post("https://portal.patchman.co/oauth2/token/", auth=("{CLIENT_ID}", "{CLIENT_SECRET}"), data={"grant_type": "client_credentials"})
{ "expires_in": 36000, "scope": "policy", "access_token": "rBJVOkiV0Zv9O0B23HQwp4bgQVpyuB", "token_type": "Bearer" }
License keys are used for registering new servers to your Portal account. They are used by
the installation script, or used manually to enter in the /etc/patchman/license/key
file prior to the agent's first start.
Note that after using the license key you will still need to approve the new server to your Portal account before it starts functioning completely. See server approval for more information.
null
value for this field.
{ "url": "https://portal.patchman.co/api/v1/license-keys/1/", "key": "ARgnLtcLqQVU2dJ4pKG9NosXSvwOYWxYsTn07agqvjgjwbmtjyjWrhPjbAYMziN7dsMKowgstFTWcisht7JRd4wF1vxiYuo0Twpt" "suborganization": null, }
If you think a license key may have been compromised, you can revoke it by performing a
DELETE
request to the license key object. A new license key will automatically
be generated in its place, which you can request after the conclusion of the request. Since
internally only the key property changes and the wrapping object isn't deleted in full, you
will be able to request the new key using the same URL as the old one (the object isn't
removed and the ID doesn't change).
Servers are objects representing your own hosting servers. They are part of a server group, which governs which default policies apply to the end-users of the server.
plesk
, directadmin
and cpanel
,
or custom_files
and custom_scripts
when using a custom
integration method.
13:45
. The input is
validated using the following regular expression: (2[0-3]|[01][0-9]):[0-5][0-9]
.
null
. If the server can be
deleted without delay, the value will show the current date and time (and will thus
depend on the time at which the request is performed).
true
, false
and all
. The
default value is true
.
show
and
hide
, and defaults to show
.
{ "id": 1, "url": "https://portal.patchman.co/api/v1/servers/1/", "server_group": "https://portal.patchman.co/api/v1/servergroups/1/", "hostname": "localhost", "ip_address": "127.0.0.1", "domain_count": 3, "platform": "detect", "end_users": [ { "url": "https://portal.patchman.co/api/v1/endusers/1/", "username": "admin" }, { "url": "https://portal.patchman.co/api/v1/endusers/2/", "username": "enduser1234" } ], "scan_time": "15:46", "removable_per": "2016-01-01T00:00:00Z", "removed_at": null }
To request the cancellation for a server, you can use the cancel
action using a POST request.
No content is required in the POST body. If the server can be removed immediately, this call will cancel
the license and remove the server from your account. If the server can not be removed immediately, the
license will be canceled and removed on the first allowed removal date. The removal date is determined by
your plan's license period, and can be seen as the property removable_per
on the server
object.
You can only cancel a server that has been approved (i.e. is active) and has not yet been cancelled. For removing an unapproved server, please refer to this section.
POST https://portal.patchman.co/api/v1/servers/1/cancel/
When a newly installed server contacts the Portal, it has to be approved before it will be
fully activated and allowed to start scanning. You can approve a server using a POST request
to the approve
action on a Server object. During approval, you may change the
hostname and server group of a server as well. Note that an unapproved server will always be
created as a member of the default server group if you don't change this property before or
during approval.
The action will not have any effect on an already approved server, even if you specify changes on the hostname and/or server group fields. Please use the regular server update method if you wish to change those properties after approval.
POST https://portal.patchman.co/api/v1/servers/1/approve/
{ "server_group": "https://portal.patchman.co/api/v1/servergroups/1/", "hostname": "my.unapproved.server" }
If a server creation request has been submitted for your account but you don't want to
approve the server, you can delete it using the DELETE method on the server object in
question (not the approve
action).
Please note that deleting an unapproved server is not the same as cancelling the license for an approved and active server. That action is documented here. Performing this action on any server that has already been approved will be rejected.
DELETE https://portal.patchman.co/api/v1/servers/1/
A server group contains common settings for all servers that are part of the server group.
Fields below available only if the organization has enabled the custom platform integrations. If you do not use a standard panel automatically supported by Patchman, you can use the configuration options below to configure the integration parameters. Check the article for details.
auto
, custom_files
and custom_scripts
.
{ "id": 1, "url": "https://portal.patchman.co/api/v1/servergroups/1/", "name": "Default group", "language_override": "en", "default_reseller_policy": "https://portal.patchman.co/api/v1/policies/1/", "default_user_policy": "https://portal.patchman.co/api/v1/policies/1/", "platform": "auto", "file_integration_user_data_path": "", "file_integration_path_data_path": "", "file_integration_user_changes_path": "", "script_integration_user_data_path": "/etc/patchman/echo_details.sh", "script_integration_path_data_path": "/etc/patchman/echo.sh", "script_integration_user_changes_path": "/etc/patchman/echo_list.sh" }
Policies are sets of rules that apply to end-users. Any end-user has only one applicable policy at a given time, and may be set explicitly on the end-user object, but also on one of its parent end-users or at the server level.
The availability of adding and changing policies depends on the plan of the organization.
admin
,
reseller
, user
and descendant
.
nobody
, admin
, reseller
, user
and descendant
.
nobody
, admin
, reseller
, user
and descendant
.
none
, centralized
, homedir_own
,
homedir_parent
, homedir_descendant
.
audit_logging
. Not required if audit_logging
is set to
none
or centralized
.
?lang={LANG}
as query parameter.
{ "name": "Default Policy", "url": "https://portal.patchman.co/api/v1/policies/1/", "notification_parent": "admin", "end_user_login": "user", "end_user_blocking": "user", "block_suspended": true, "allow_disabling_notifications": true, "allow_changing_email": true, "audit_logging": "centralized", "audit_log_relative_path": "", "audit_log_chown": false, "email_from_name": "", "email_from_address": "no-reply@patchman.co", "base_email_template_text": "{{> content}}\r\n\r\n--\r\n{{> branding}}", "base_email_template_html": "<html></html>", "base_email_template": "https://portal.patchman.co/api/v1/policies-base-email-template/1/" }
The policy base email templates are used as a base for formatting email messages sent to end-users.
{ "url": "https://portal.patchman.co/api/v1/policies-base-email-template/1/", "languages": [ "en", "es", "da", "de", "fi", "nl", "fr", "ru", "uk", "el", "it", ], "text_en": "...", "text_es": "...", "text_da": "...", "text_de": "...", "text_fi": "...", "text_nl": "...", "text_fr": "...", "text_ru": "...", "text_uk": "...", "text_el": "...", "text_it": "...", "html_en": "...", "html_es": "...", "html_da": "...", "html_de": "...", "html_fi": "...", "html_nl": "...", "html_fr": "...", "html_ru": "...", "html_uk": "...", "html_el": "...", "html_it": "...", }
End-users are accounts on your server.
admin
,
reseller
or user
.
true
,
false
and all
. The default value is all
.
{ "id": 1, "url": "https://portal.patchman.co/api/v1/endusers/1/", "scan_url": "https://portal.patchman.co/api/v1/endusers/1/scan/", "token_url": "https://portal.patchman.co/api/v1/endusers/1/token/", "metrics_url": "https://portal.patchman.co/api/v1/endusers/1/metrics/", "server": "https://portal.patchman.co/api/v1/servers/1/", "parent": null, "policy": null, "effective_policy": "https://portal.patchman.co/api/v1/policies/1/", "username": "admin", "suspended": false, "level": "admin", "language": "en", "email": "admin@localhost", "language_frozen": false, "email_frozen": false, "notifications_enabled": true, "last_scan_at": "2015-01-01T12:00:00Z", "last_scan_requested_at": "2015-01-01T11:00:00Z" }
Obtains the number of resolved and unresolved detections for each of the three types: malware, vulnerabilities and outdated applications.
These counts reflect the number of results if you were to call Detections with an end-user filter.
curl https://portal.patchman.co/api/v1/endusers/1/metrics/
import requests requests.get("https://portal.patchman.co/api/v1/endusers/1/metrics/")
{ "malware_unresolved": 1, "malware_resolved": 2, "outdated_applications_unresolved": 3, "outdated_applications_resolved": 4, "vulnerabilities_unresolved": 5, "vulnerabilities_resolved": 6 }
Patchman reports various kinds of detections. Each kind of detection has different parameters and supports different actions. Take care that you implement usage of these API resources separately.
All fields on detections and their associated actions are read-only. The only allowed modification is the creation of new actions for detections. Which actions are allowed depends on the type of detection, the current state of the detection, your policy settings and your plan.
Detections can be sorted by providing ordering
GET parameter to the request. The value
should be a comma separated list of fields by which detections will be ordered. By default the order
is ascending, if descending order is desired, the field must be prefix by a "-" sign. Every detection
end-point below gives a list of fields by which it can be ordered.
Application detections report the detected installations of web software packages. Only current detections are listed. Note that no actions are available for application detections.
unresolved
, resolved
.
{ "url": "https://portal.patchman.co/api/v1/detections/applications/1/", "path": "/home/username/domains/domain.com/public_html/", "detected_at": "2015-01-01T12:00:00Z", "end_user": "https://portal.patchman.co/api/v1/endusers/1/", "definition": { "id": 1, "application": "Application", "version": "1.1", "up_to_date": true } }
Malware detections list script files with malicious purposes. These malware detections are based on hash matching. No dynamic malware will be returned using this API endpoint.
waiting
,
resolved
, blocked
, retracted
,
reverted
, error
, pending_change
and requires_attention
.
quarantine
or delete
action), if applicable.
quarantine
or delete
action), if applicable. An action is requested if the command
was sent to the server and is pending completion.
undo_quarantine
action), if applicable.
resolved
and was not retracted.
resolved
and was retracted.
unresolved
, resolved
.
{ "url": "https://portal.patchman.co/api/v1/detections/malware/1/", "actions": "https://portal.patchman.co/api/v1/detections/malware/1/actions/", "allowed_actions": [ "quarantine", "block" ], "path": "/home/username/domains/domain.com/public_html/directory/file.php", "state": "waiting", "detected_at": "2015-01-01T12:00:00Z", "resolution_scheduled_at": "2015-01-15T12:00:00Z", "resolution_requested_at": null, "resolution_reverted_at": null, "resolved_at": null, "retracted_at": null, "end_user": "https://portal.patchman.co/api/v1/endusers/1/", "definition": { "id": 1, "name": "shell.generic", "description": "Generic web shell", "type": "Web shell" } }
Each malware detection has actions associated with it to denote the various changes that can be made to a file that was detected as malware. You cannot modify existing actions, but you are allowed to create new actions. These actions are for hash based detections. Actions submitted for dynamic malware to this endpoint will result in detection not found.
detection
, reminder
,
retraction
, retraction_changed
, retraction_deleted
,
retraction_definition_retracted
, retraction_definition_superseded
,
quarantine
, undo_quarantine
, delete
,
block
and unblock
. When creating a new action, valid values are
quarantine
, undo_quarantine
, delete
, block
and unblock
(depending on the detection state and your plan).
{ "type": "detection", "scheduled_at": null, "issued_at": null, "failed_at": null, "completed_at": "2015-01-01T12:00:00Z", "notified_at": null }
Dynamic malware detections list script files with malicious purposes. These malware detections are based on rules that match partial files. No hash based malware detections will be returned using this API endpoint.
waiting
,
resolved
, blocked
, retracted
,
reverted
, error
, pending_change
and requires_attention
.
quarantine
or delete
action), if applicable.
quarantine
or delete
action), if applicable. An action is requested if the command
was sent to the server and is pending completion.
undo_quarantine
action), if applicable.
resolved
and was not retracted.
resolved
and was retracted.
'M'
or an
automatic action 'A'
.
unresolved
, resolved
.
{ "url": "https://portal.patchman.co/api/v1/detections/dynamic-malware/1/", "actions": "https://portal.patchman.co/api/v1/detections/dynamic-malware/1/actions/", "allowed_actions": [ "undo_clean", ], "path": "/home/username/domains/domain.com/public_html/directory/file.php", "state": "resolved", "detected_at": "2019-01-01T12:00:00Z", "resolution_scheduled_at": "2019-01-15T12:00:00Z", "resolution_requested_at": null, "resolution_reverted_at": null, "resolved_at": null, "retracted_at": null, "end_user": "https://portal.patchman.co/api/v1/endusers/1/", "definition": { "id": 1, "name": "shell.generic.dynamic", "description": "Generic web shell", "type": "Web shell" }, "file_cleans": [{ "id": 1, "performed_at": "2019-01-02T17:00:00Z", "before_hash": "bb4870deb77e8993abe9c6a2925a93ed", "after_hash": "ad2e5352cc4abb6aa0b503974b6c5354", "deleted_at": null, "action": "A" }] }
Each dynamic malware detection has actions associated with it to denote the various changes that can be made to a file that was detected as malware. You cannot modify existing actions, but you are allowed to create new actions. These malware detections are based on rules that match partial files. Actions submitted for hash based malware to this endpoint will result in detection not found.
detection
, reminder
,
retraction
, retraction_changed
, retraction_deleted
,
retraction_definition_retracted
, retraction_definition_superseded
,
delete
, block
, unblock
, clean
and
undo_clean
. When creating a new action, valid values are unblock
,
clean
and undo_clean
(depending on the detection state and your plan).
'M'
or an
automatic action 'A'
.
curl https://portal.patchman.co/api/v1/detections/dynamic-malware/1/actions/ \ -F type=undo_clean \ -F file_clean=1
r = requests.post("https://portal.patchman.co/api/v1/detections/dynamic-malware/1/actions/", data={"type": "undo_clean", "file_clean": "1"})
{ "type": "detection", "file_clean: { "id": 1, "performed_at": "2019-01-02T17:00:00Z", "before_hash": "bb4870deb77e8993abe9c6a2925a93ed", "after_hash": "ad2e5352cc4abb6aa0b503974b6c5354", "deleted_at": null, "action": "A" } "scheduled_at": null, "issued_at": null, "failed_at": null, "completed_at": "2015-01-01T12:00:00Z", "notified_at": null }
Vulnerability detections list files of installed web application software containing exploitable security vulnerabilities.
waiting
,
resolved
, blocked
, reverted
,
retracted
and error
.
patch
action), if applicable.
patch
action), if applicable. An action is requested if the command was sent to the server
and is pending completion.
undo_patch
action), if applicable.
resolved
and was not retracted.
resolved
and was retracted.
unresolved
, resolved
.
{ "url": "https://portal.patchman.co/api/v1/detections/vulnerabilities/1/", "actions": "https://portal.patchman.co/api/v1/detections/vulnerabilities/1/actions/", "allowed_actions": [ "patch", "block" ], "path": "/home/username/domains/domain.com/public_html/software/file.php", "state": "waiting", "detected_at": "2015-01-01T12:00:00Z", "resolution_scheduled_at": "2015-01-15T12:00:00Z", "resolution_requested_at": null, "resolution_reverted_at": null, "resolved_at": null, "retracted_at": null, "end_user": "https://portal.patchman.co/api/v1/endusers/1/", "definitions": [ { "id": 1, "name": "First vulnerability", "description": "Background information for the first vulnerability", "type": "CSRF", "application": "Application" }, { "id": 2, "name": "Second vulnerability", "description": "Background information for the second vulnerability", "type": "XSS", "application": "Application" } ] }
Each vulnerability detection has actions associated with it to denote the various changes that can be made to a file that was detected as vulnerable. You cannot modify existing actions, but you are allowed to create new actions.
detection
, reminder
,
retraction
, retraction_changed
, retraction_deleted
,
retraction_definition_retracted
, retraction_definition_superseded
,
patch
, undo_patch
, block
and unblock
.
When creating a new action, valid values are patch
, undo_patch
,
block
and unblock
(depending on the detection state and
your plan).
{ "type": "detection", "scheduled_at": null, "issued_at": null, "failed_at": null, "completed_at": "2015-01-01T12:00:00Z", "notified_at": null }
If your plan allows it, malware rule detection files will be automatically cleaned by Patchman. Consecutive cleans within the grace period (of the last clean) are grouped together, unless the time between the first and a new clean is more than the grace period limit, which is a setting on your plan.
All fields on file cleans are read-only.
null
if the file clean has not been billed yet.
curl https://portal.patchman.co/api/v1/filecleans/
import requests requests.get("https://portal.patchman.co/api/v1/filecleans/")
{ "id": 1, "username": "username", "domain": "domain.com", "cleans": [ { "id": 1, "cleaned_at": "2015-12-01T10:00:00Z", "full_detection_path": "/home/username/domains/domain.com/public_html/index.php" }, { "id": 2, "cleaned_at": "2015-12-02T10:00:00Z", "full_detection_path": "/home/username/domains/domain.com/public_html/index.php" }, ], "billed_at": "2016-01-01T00:00:00Z", }
Part of this API, but not publicly exposed (as this uses a different authentication scheme) is retrieving a token for end-user authentication. This token is used by the end-users of a server to access the Patchman Portal interface detailing their specific user. This API is intended for use by control panel plugins and only available if the plan of the organization enables end-user logins. Additionally, this API will return HTTP 403 errors if the end-user has no policy that allows end-user logins.
This API is only available using the license certificate and key issued to server and only
from the same IP that has been registered with Patchman. Authentication occurs through
HTTPS client certificates. For OAuth2 authentication see token_url
on
End-users.
After issuing a successful request, the API returns a URL you should redirect your user to.
This URL will take care of placing an authentication cookie on the end-user's computer.
Following this, the user will be redirected to the page provided in the next
argument, or (if this is not provided) to the default user view. Note that the redirect URL
is only valid for one minute.
curl https://client-portal.patchman.co/api/v1/token/ \ --cert license/patchman.crt \ --key license/patchman.key \ -d username=enduser1234If curl is compiled against NSS, a bug requires you to add:
--cacert license/patchman.crt \ --capath /etc/ssl/certs/
import requests r = requests.post("https://client-portal.patchman.co/api/v1/token/", data={"username": "enduser1234"}, cert=("license/patchman.crt", "license/patchman.key"))
{ "username": "enduser1234", "redirect_to": "https://portal.patchman.co/t/login/token12345/" }
Patchman has many definition signatures to detect malware scripts, but it is inevitable that some malware may slip through. When you encounter such scripts, we would like to add it to our repository. This public API method allows you to submit malware samples to our reviewers, which may then result in adding it to our database.
Please try to be as descriptive as possible when submitting a file. Use the type field to describe in one or two words what you think the script is (e.g. phishing, spam, shell, etc) and the optional description field to add more context (e.g. observed behaviour, how you encountered it, etc).
malware
curl https://portal.patchman.co/api/v1/report/ \ -F report_type=malware \ -F file=@evil.php \ -F type=spam \ -F "description=Found this while..."
r = requests.post("https://portal.patchman.co/api/v1/report/", data={"report_type": "malware", "type": "spam", "description": "Found this while..."}, files={"file": ("evil.php", open("evil.php", "r"))})
You can manage user accounts for the Portal through the API, for example if you wish to integrate this with the central staff user account management of your organization.
Note: upon creation of a user account through the API, a confirmation e-mail with the user's randomly generated password will be sent to the e-mail address you provide. There is no way to specify the password yourself.
{ "url": "https://portal.patchman.co/api/v1/users/1/", "name": "John Doe", "email": "john@doe.com", "role": "manager" }
If your plan allows it, you can resell Patchman to your larger customers. Within Patchman, these are known as suborganizations. You can determine exactly which functionality of the product you want them to be able to tune themselves, while also keeping control through your own account. All billing will still pass through your own account.
{ "url": "https://portal.patchman.co/api/v1/suborganizations/1/", "users": "https://portal.patchman.co/api/v1/suborganizations/1/users/", "name": "Organization X", "email": "info@organizationx.com", "max_servers": 10, "max_physical_servers": 10, "max_virtual_servers": 10, "max_users": null, "can_add_servers": true, "can_change_servers": true, "can_change_policies": false, "can_access_event_log": true, "can_change_email_templates": false, "can_change_default_email_template": false, "can_end_user_login": true, "can_access_api": false }
Like your own organization, suborganizations require one or more user accounts that can access the Portal, manage settings and view detections. The management of suborganization users is exactly the same as user management for your own organization.
Note: upon creation of a user account through the API, a confirmation e-mail with the user's randomly generated password will be sent to the e-mail address you provide. There is no way to specify the password yourself.
{ "url": "https://portal.patchman.co/api/v1/suborganizations/1/users/1/", "name": "John Doe", "email": "john@doe.com", "role": "manager" }