Portus REST API
Introduction
We have been working on a REST API that can be used to operate Portus without needing to access the web UI, and we are already building some tooling like openSUSE/portusctl which already takes advantage of this new API.
Note though that we are doing organically. This means that we make no guarantees
over the stability of this version of the API (once we’ve learned what we need
from v1
, we will make these guarantees on a v2 version of the
API).
The specification listed below corresponds to the current state of the master branch, so the specification may vary from the v2.3 release. That being said, we are writing down the changes from the v2.3, so early users are not caught off guard. Besides this, take into account the following:
- You have to set the
Content-Type
and theAccept
headers toapplication/json
for every request. - Error messages are a bit chaotic (i.e. with different formats). We are tracking this on this issue.
Authentication
Authentication is done through application tokens. This way, you don’t compromise your password, and you can revoke it whenever you think it’s necessary.
Once you have created this application token, you will have to pass the
PORTUS-AUTH
header for every HTTP request that you perform. This header
follows this format: <username>:<application token>
. So, if your user name is
user
, and the application token you have created has the value
T7Dfuz4fsy1UVxNUKyac
, then you have to set this header with the value:
user:T7Dfuz4fsy1UVxNUKyac
. You can try that this is working by performing the
following HTTP request (where https://172.17.0.1
points to a Portus instance):
$ curl -X GET --header 'Accept: application/json' --header 'Portus-Auth: user:T7Dfuz4fsy1UVxNUKyac' 'https://172.17.0.1/api/v1/users'
If everything went correctly, then you will get a JSON response with all the users from your Portus instance.
Finally, portusctl does this
automatically for you if you provide the environment variables:
PORTUSCTL_API_SERVER
, PORTUSCTL_API_TOKEN
and PORTUSCTL_API_USER
. With
this in mind, the following is equivalent to the previously used curl command:
$ export PORTUSCTL_API_USER="user"
$ export PORTUSCTL_API_TOKEN="T7Dfuz4fsy1UVxNUKyac"
$ export PORTUSCTL_API_SERVER="https://172.17.0.1"
$ portusctl get users
Errors
Authorization and authentication
In this regard there are two status codes to be aware of:
401
: an authentication error. This means that you either forgot to provide thePORTUS-AUTH
header, or the given credentials are wrong.403
: an authorization error. This means that the user performing an action is not allowed to do it.
Data validation
In regards to data validation we differentiate between two kinds of errors. First of all, we have type errors like:
- Some mandatory fields are missing.
- Some fields have a wrong type (e.g. a boolean value was expected but a weird string was given).
These errors are responded with a 400
status code. The response body will be
then like this:
{
"message": "Reason for the error"
}
Finally, the other possible error is a semantic one: a given field has a wrong
format (e.g. bad user email), a field was expected to be unique but it wasn’t,
etc. These errors get back a 422
status code with the following response body:
{
"message": {
"<field1>": ["<error1>", "<error2>", ...],
...
}
}
Unknown route or method not allowed
A 404
is returned whenever an unknown route is provided. This can happen in
two ways:
- The given path is simply non-existent.
- The path required a resource identifier (e.g. a user ID), but an unknown ID was provided (e.g. there are no users with the provided ID).
Sometimes it’s not that the route does not exist, but that the given method is
now allowed at the moment. This can happen in some cases where the route is only
available under some conditions. In this situation, a 405
will be sent, with a
response body like so:
{
"message": "Reason for the method being disabled"
}
Endpoints
Users
POST /api/v1/users/{id}/application_tokens
Create user's token.
Parameters
- application (string, required): Application name. This parameter is part of the data to be sent as a form.
- id (integer, required): User ID. This parameter has to be included as part of the path.
Response Class (status: 201)
Format of the response:
Response Messages
400 |
401 |
403 |
422 |
GET /api/v1/users/{id}/application_tokens
Returns list of user's tokens.
Parameters
- id (integer, required): User ID. This parameter has to be included as part of the path.
Response Class (status: 200)
Format of the response:
Response Messages
401 |
403 |
404 |
DELETE /api/v1/users/application_tokens/{id}
Delete application token.
Parameters
- id (string, required): Token id. This parameter has to be included as part of the path.
Response Messages
204 |
401 |
403 |
404 |
POST /api/v1/users/bootstrap
Use this method to create the first admin user. The response will include an application token so you can use this user right away. This method should be used when bootstrapping a Portus instance by using the REST API. Last but not least, it will respond with a 405 if the `first_user_admin` configuration value has been disabled.
Parameters
- user[username] (string, required): User name. This parameter is part of the data to be sent as a form.
- user[email] (string, required): E-mail. This parameter is part of the data to be sent as a form.
- user[password] (string, required): Password. This parameter is part of the data to be sent as a form.
- user[display_name] (string): Display name. This parameter is part of the data to be sent as a form.
Response Class (status: 201)
Create the first admin user. Format of the response:
Response Messages
400 |
401 |
403 |
405 |
422 |
GET /api/v1/users
This will expose all users.
Parameters
- all (boolean): Ignores pagination. This parameter has to be set in the URL query.
- page (integer): Current page number. This parameter has to be set in the URL query.
- per_page (integer): Number of items per page. This parameter has to be set in the URL query.
- sort_attr (string): Current page number. This parameter has to be set in the URL query.
- sort_order (string): Number of items per page. This parameter has to be set in the URL query.
Response Class (status: 200)
Returns list of users. Format of the response:
Response Messages
401 |
403 |
POST /api/v1/users
Create new user.
Parameters
- user[username] (string, required): User name. This parameter is part of the data to be sent as a form.
- user[email] (string, required): E-mail. This parameter is part of the data to be sent as a form.
- user[password] (string, required): Password. This parameter is part of the data to be sent as a form.
- user[display_name] (string): Display name. This parameter is part of the data to be sent as a form.
- user[bot] (boolean): Whether this is a bot or not. This parameter is part of the data to be sent as a form.
Response Class (status: 201)
Format of the response:
Response Messages
400 |
401 |
403 |
422 |
DELETE /api/v1/users/{id}
Delete user.
Parameters
- id (integer, required): User ID. This parameter has to be included as part of the path.
Response Messages
204 |
401 |
403 |
404 |
PUT /api/v1/users/{id}
Update user.
Parameters
- user[username] (string): User name. This parameter is part of the data to be sent as a form.
- user[email] (string): E-mail. This parameter is part of the data to be sent as a form.
- user[password] (string): Password. This parameter is part of the data to be sent as a form.
- user[display_name] (string): Display name. This parameter is part of the data to be sent as a form.
- id (integer, required): User ID. This parameter has to be included as part of the path.
Response Class (status: 200)
Format of the response:
Response Messages
400 |
401 |
403 |
404 |
422 |
GET /api/v1/users/{id}
Show user by id or email.
Parameters
- id (string, required): User ID or email. This parameter has to be included as part of the path.
Response Class (status: 200)
Format of the response:
Response Messages
401 |
403 |
404 |
Health
GET /api/v1/health
Returns general metrics on the health of the system.
Response Class (status: 200)
Returns hash of metrics. Format of the response:
Response Messages
503 |
GET /api/v1/_ping
Returns 200 as a status code.
Response Messages
200 |
Namespaces
DELETE /api/v1/namespaces/{id}
Delete namespace.
Parameters
- id (integer, required): Namespace ID. This parameter has to be included as part of the path.
Response Messages
204 |
401 |
403 |
404 |
422 |
PUT /api/v1/namespaces/{id}
Update namespace.
Parameters
- namespace[name] (string): Namespace name. This parameter is part of the data to be sent as a form.
- namespace[description] (string): The description of the namespace. This parameter is part of the data to be sent as a form.
- namespace[team] (string): The ID and the name of the team containing this namespace. This parameter is part of the data to be sent as a form.
- namespace[visibility] (string): The visibility of namespaces by other people. This parameter is part of the data to be sent as a form.
- id (integer, required): Namespace ID. This parameter has to be included as part of the path.
Response Messages
200 |
400 |
401 |
403 |
404 |
422 |
GET /api/v1/namespaces/{id}
Show namespaces by id.
Parameters
- id (integer, required): Namespace ID. This parameter has to be included as part of the path.
Response Class (status: 200)
Format of the response:
Response Messages
401 |
403 |
404 |
POST /api/v1/namespaces
Create a namespace.
Parameters
- name (string, required): Namespace name. This parameter is part of the data to be sent as a form.
- team (string, required): Team name. This parameter is part of the data to be sent as a form.
- description (string): Team description. This parameter is part of the data to be sent as a form.
Response Class (status: 201)
Format of the response:
Response Messages
400 |
401 |
403 |
422 |
GET /api/v1/namespaces
This will expose all accessible namespaces by the user via either team membership or visibility. Keep in mind that if the user is an admin, this will return all the global, personal and other namespaces created by all the users.
Parameters
- all (boolean): Ignores pagination. This parameter has to be set in the URL query.
- page (integer): Current page number. This parameter has to be set in the URL query.
- per_page (integer): Number of items per page. This parameter has to be set in the URL query.
- sort_attr (string): Current page number. This parameter has to be set in the URL query.
- sort_order (string): Number of items per page. This parameter has to be set in the URL query.
Response Class (status: 200)
Returns a list of namespaces. Format of the response:
Response Messages
401 |
403 |
GET /api/v1/namespaces/validate
Validates the given namespace.
Parameters
- name (string, required): Name to be checked. This parameter has to be set in the URL query.
Response Class (status: 200)
Format of the response:
Response Messages
401 |
403 |
GET /api/v1/namespaces/{id}/repositories
Returns the list of the repositories for the given namespace.
Parameters
- id (integer, required): Namespace ID. This parameter has to be included as part of the path.
Response Class (status: 200)
Format of the response:
Response Messages
401 |
403 |
404 |
Registries
GET /api/v1/registries/validate
Besides containing the usual Status object, it adds the reachable validation to the `hostname` field in the `messages` hash. This validation returns a string containing the error as given by the registry. If empty then everything went well.
Parameters
- name (string): The name of the registry. This parameter has to be set in the URL query.
- hostname (string): The hostname of the registry. This parameter has to be set in the URL query.
- external_hostname (string): An external hostname of the registry, useful if behind a proxy with a different FQDN. This parameter has to be set in the URL query.
- use_ssl (boolean): Whether the registry uses SSL or not. This parameter has to be set in the URL query.
- only (array): Restrict which parameters are to be validated. This parameter is part of the data to be sent as a form.
Response Class (status: 200)
Validates the given registry. Format of the response:
Response Messages
401 |
403 |
PUT /api/v1/registries/{id}
Update registry.
Parameters
- registry[name] (string): The name of the registry. This parameter is part of the data to be sent as a form.
- registry[hostname] (string): The hostname of the registry. This parameter is part of the data to be sent as a form.
- registry[use_ssl] (boolean): Whether the registry uses SSL or not. This parameter is part of the data to be sent as a form.
- registry[external_hostname] (string): An external hostname of the registry, useful if behind a proxy with a different FQDN. This parameter is part of the data to be sent as a form.
- id (integer, required): . This parameter has to be included as part of the path.
Response Class (status: 200)
Format of the response:
Response Messages
400 |
401 |
403 |
404 |
422 |
POST /api/v1/registries
Allow users to create a registry. This will only work if no registry works yet.
Parameters
- registry[name] (string, required): The name of the registry. This parameter is part of the data to be sent as a form.
- registry[hostname] (string, required): The hostname of the registry. This parameter is part of the data to be sent as a form.
- registry[use_ssl] (boolean, required): Whether the registry uses SSL or not. This parameter is part of the data to be sent as a form.
- registry[external_hostname] (string): An external hostname of the registry, useful if behind a proxy with a different FQDN. This parameter is part of the data to be sent as a form.
Response Class (status: 201)
Create a registry. Format of the response:
Response Messages
400 |
401 |
403 |
422 |
GET /api/v1/registries
This will expose all accessible registries.
Response Class (status: 200)
Returns a list of registries. Format of the response:
Response Messages
401 |
403 |
Repositories
PUT /api/v1/repositories/{id}
Update team.
Parameters
- repository[description] (string): The description of the team. This parameter is part of the data to be sent as a form.
- id (integer, required): Team ID. This parameter has to be included as part of the path.
Response Messages
200 |
400 |
401 |
403 |
404 |
422 |
DELETE /api/v1/repositories/{id}
Delete repository.
Parameters
- id (integer, required): Repository ID. This parameter has to be included as part of the path.
Response Messages
204 |
401 |
403 |
404 |
422 |
GET /api/v1/repositories/{id}
Show repositories by id.
Parameters
- id (integer, required): Repository ID. This parameter has to be included as part of the path.
Response Class (status: 200)
Format of the response:
Response Messages
401 |
403 |
404 |
GET /api/v1/repositories
This will expose all repositories.
Parameters
- all (boolean): Ignores pagination. This parameter has to be set in the URL query.
- page (integer): Current page number. This parameter has to be set in the URL query.
- per_page (integer): Number of items per page. This parameter has to be set in the URL query.
- sort_attr (string): Current page number. This parameter has to be set in the URL query.
- sort_order (string): Number of items per page. This parameter has to be set in the URL query.
Response Class (status: 200)
Returns list of repositories. Format of the response:
Response Messages
401 |
403 |
GET /api/v1/repositories/{id}/tags/grouped
Returns the list of the tags for the given repository groupped by digest.
Parameters
- id (integer, required): Repository ID. This parameter has to be included as part of the path.
Response Class (status: 200)
Format of the response:
Response Messages
401 |
403 |
404 |
GET /api/v1/repositories/{id}/tags
Returns the list of the tags for the given repository.
Parameters
- id (integer, required): Repository ID. This parameter has to be included as part of the path.
Response Class (status: 200)
Format of the response:
Response Messages
401 |
403 |
404 |
GET /api/v1/repositories/{id}/tags/{tag_id}
Show tag by id.
Parameters
- id (integer, required): Repository ID. This parameter has to be included as part of the path.
- tag_id (string, required): Tag ID. This parameter has to be included as part of the path.
Response Class (status: 200)
Format of the response:
Response Messages
401 |
403 |
404 |
Tags
GET /api/v1/tags
This will expose all tags.
Parameters
- all (boolean): Ignores pagination. This parameter has to be set in the URL query.
- page (integer): Current page number. This parameter has to be set in the URL query.
- per_page (integer): Number of items per page. This parameter has to be set in the URL query.
- sort_attr (string): Current page number. This parameter has to be set in the URL query.
- sort_order (string): Number of items per page. This parameter has to be set in the URL query.
Response Class (status: 200)
Returns list of tags. Format of the response:
Response Messages
401 |
403 |
DELETE /api/v1/tags/{id}
Delete tag.
Parameters
- id (integer, required): Tag ID. This parameter has to be included as part of the path.
Response Messages
204 |
401 |
403 |
404 |
422 |
GET /api/v1/tags/{id}
Show tag by id.
Parameters
- id (integer, required): Tag ID. This parameter has to be included as part of the path.
Response Class (status: 200)
Format of the response:
Response Messages
401 |
403 |
404 |
Teams
POST /api/v1/teams/{id}/ldap_check
Disables any LDAP check for the team.
Parameters
- id (integer, required): Team ID. This parameter has to be included as part of the path.
Response Messages
201 |
400 |
401 |
403 |
404 |
405 |
DELETE /api/v1/teams/{id}
Deletes a team.
Parameters
- id (string, required): Team id. This parameter has to be included as part of the path.
- new_team (string): Team that will get the original namespaces from the deleted team. This parameter has to be set in the URL query.
Response Messages
400 |
401 |
204 |
403 |
404 |
422 |
PUT /api/v1/teams/{id}
Update team.
Parameters
- team[name] (string): Team name. This parameter is part of the data to be sent as a form.
- team[description] (string): The description of the team. This parameter is part of the data to be sent as a form.
- id (integer, required): Team ID. This parameter has to be included as part of the path.
Response Messages
200 |
400 |
401 |
403 |
404 |
422 |
GET /api/v1/teams/{id}
Show teams by id.
Parameters
- id (string, required): Team ID. This parameter has to be included as part of the path.
Response Class (status: 200)
Format of the response:
Response Messages
401 |
403 |
404 |
POST /api/v1/teams
Create a team.
Parameters
- name (string, required): Team name. This parameter is part of the data to be sent as a form.
- description (string): Team description. This parameter is part of the data to be sent as a form.
- owner_id (integer): Team owner. This parameter is part of the data to be sent as a form.
Response Class (status: 201)
Format of the response:
Response Messages
400 |
401 |
403 |
422 |
GET /api/v1/teams
This will expose all teams that the user is member of or has access to. That mean if the user is an admin, this will return all the teams created by all the users. If you want to check if the user is a member of a team, check the role attribute..
Parameters
- all (boolean): Ignores pagination. This parameter has to be set in the URL query.
- page (integer): Current page number. This parameter has to be set in the URL query.
- per_page (integer): Number of items per page. This parameter has to be set in the URL query.
- sort_attr (string): Current page number. This parameter has to be set in the URL query.
- sort_order (string): Number of items per page. This parameter has to be set in the URL query.
Response Class (status: 200)
Returns list of teams. Format of the response:
Response Messages
401 |
403 |
GET /api/v1/teams/{id}/namespaces
Returns the list of namespaces for the given team.
Parameters
- id (integer, required): Team ID. This parameter has to be included as part of the path.
Response Class (status: 200)
Format of the response:
Response Messages
401 |
403 |
404 |
POST /api/v1/teams/{id}/members
Adds a user as member in a team.
Parameters
- id (string, required): Team id. This parameter has to be included as part of the path.
- role (string, required): Team member role. This parameter is part of the data to be sent as a form.
- user (string, required): Team member username. This parameter is part of the data to be sent as a form.
Response Class (status: 201)
Format of the response:
Response Messages
401 |
403 |
404 |
GET /api/v1/teams/{id}/members
Returns the list of team members.
Parameters
- id (integer, required): Team ID. This parameter has to be included as part of the path.
Response Class (status: 200)
Format of the response:
Response Messages
401 |
403 |
404 |
PUT /api/v1/teams/{id}/members/{member_id}
Updates a member from a team.
Parameters
- id (string, required): Team id. This parameter has to be included as part of the path.
- member_id (integer, required): Team member id. This parameter has to be included as part of the path.
- role (string, required): Team member role. This parameter is part of the data to be sent as a form.
Response Class (status: 200)
Format of the response:
Response Messages
400 |
401 |
403 |
404 |
422 |
DELETE /api/v1/teams/{id}/members/{member_id}
Deletes a member from a team.
Parameters
- id (string, required): Team id. This parameter has to be included as part of the path.
- member_id (string, required): Team member id. This parameter has to be included as part of the path.
Response Messages
400 |
401 |
204 |
403 |
404 |
422 |
Vulnerabilities
POST /api/v1/vulnerabilities
Force the security scanner to go through all the tags again, even if they have been marked as scanned.
Response Messages
201 |
401 |
403 |
POST /api/v1/vulnerabilities/{id}
Force the security scanner to scan again a given tag,even if it was already marked as scanned.
Parameters
- id (integer, required): . This parameter has to be included as part of the path.
Response Messages
201 |
401 |
403 |
Version
GET /api/version
Returns the version of Portus and the supported API versions.
Response Class (status: 200)
Fetch the version of Portus. Format of the response: