diff --git a/docs/rest-api/examples.md b/docs/rest-api/examples.md deleted file mode 100644 index f4348907f..000000000 --- a/docs/rest-api/examples.md +++ /dev/null @@ -1,162 +0,0 @@ -# API Examples - -Supported HTTP methods: - -* `GET`: Retrieve an object or list of objects -* `POST`: Create a new object -* `PUT`: Update an existing object, all mandatory fields must be specified -* `PATCH`: Updates an existing object, only specifying the field to be changed -* `DELETE`: Delete an existing object - -To authenticate a request, attach your token in an `Authorization` header: - -``` -curl -H "Authorization: Token d2f763479f703d80de0ec15254237bc651f9cdc0" -``` - -## Retrieving a list of sites - -Send a `GET` request to the object list endpoint. The response contains a paginated list of JSON objects. - -``` -$ curl -H "Accept: application/json; indent=4" http://localhost/api/dcim/sites/ -{ - "count": 14, - "next": null, - "previous": null, - "results": [ - { - "id": 6, - "name": "Corporate HQ", - "slug": "corporate-hq", - "region": null, - "tenant": null, - "facility": "", - "asn": null, - "physical_address": "742 Evergreen Terrace, Springfield, USA", - "shipping_address": "", - "contact_name": "", - "contact_phone": "", - "contact_email": "", - "comments": "", - "custom_fields": {}, - "count_prefixes": 108, - "count_vlans": 46, - "count_racks": 8, - "count_devices": 254, - "count_circuits": 6 - }, - ... - ] -} -``` - -## Retrieving a single site by ID - -Send a `GET` request to the object detail endpoint. The response contains a single JSON object. - -``` -$ curl -H "Accept: application/json; indent=4" http://localhost/api/dcim/sites/6/ -{ - "id": 6, - "name": "Corporate HQ", - "slug": "corporate-hq", - "region": null, - "tenant": null, - "facility": "", - "asn": null, - "physical_address": "742 Evergreen Terrace, Springfield, USA", - "shipping_address": "", - "contact_name": "", - "contact_phone": "", - "contact_email": "", - "comments": "", - "custom_fields": {}, - "count_prefixes": 108, - "count_vlans": 46, - "count_racks": 8, - "count_devices": 254, - "count_circuits": 6 -} -``` - -## Creating a new site - -Send a `POST` request to the site list endpoint with token authentication and JSON-formatted data. Only mandatory fields are required. This example includes one non required field, "region." - -``` -$ curl -X POST -H "Authorization: Token d2f763479f703d80de0ec15254237bc651f9cdc0" -H "Content-Type: application/json" -H "Accept: application/json; indent=4" http://localhost:8000/api/dcim/sites/ --data '{"name": "My New Site", "slug": "my-new-site", "region": 5}' -{ - "id": 16, - "name": "My New Site", - "slug": "my-new-site", - "region": 5, - "tenant": null, - "facility": "", - "asn": null, - "physical_address": "", - "shipping_address": "", - "contact_name": "", - "contact_phone": "", - "contact_email": "", - "comments": "" -} -``` -Note that in this example we are creating a site bound to a region with the ID of 5. For write API actions (`POST`, `PUT`, and `PATCH`) the integer ID value is used for `ForeignKey` (related model) relationships, instead of the nested representation that is used in the `GET` (list) action. - -## Modify an existing site - -Make an authenticated `PUT` request to the site detail endpoint. As with a create (`POST`) request, all mandatory fields must be included. - -``` -$ curl -X PUT -H "Authorization: Token d2f763479f703d80de0ec15254237bc651f9cdc0" -H "Content-Type: application/json" -H "Accept: application/json; indent=4" http://localhost:8000/api/dcim/sites/16/ --data '{"name": "Renamed Site", "slug": "renamed-site"}' -``` - -## Modify an object by changing a field - -Make an authenticated `PATCH` request to the device endpoint. With `PATCH`, unlike `POST` and `PUT`, we only specify the field that is being changed. In this example, we add a serial number to a device. -``` -$ curl -X PATCH -H "Authorization: Token d2f763479f703d80de0ec15254237bc651f9cdc0" -H "Content-Type: application/json" -H "Accept: application/json; indent=4" http://localhost:8000/api/dcim/devices/2549/ --data '{"serial": "FTX1123A090"}' -``` - -## Delete an existing site - -Send an authenticated `DELETE` request to the site detail endpoint. - -``` -$ curl -v -X DELETE -H "Authorization: Token d2f763479f703d80de0ec15254237bc651f9cdc0" -H "Content-Type: application/json" -H "Accept: application/json; indent=4" http://localhost:8000/api/dcim/sites/16/ -* Connected to localhost (127.0.0.1) port 8000 (#0) -> DELETE /api/dcim/sites/16/ HTTP/1.1 -> User-Agent: curl/7.35.0 -> Host: localhost:8000 -> Authorization: Token d2f763479f703d80de0ec15254237bc651f9cdc0 -> Content-Type: application/json -> Accept: application/json; indent=4 -> -* HTTP 1.0, assume close after body -< HTTP/1.0 204 No Content -< Date: Mon, 20 Mar 2017 16:13:08 GMT -< Server: WSGIServer/0.1 Python/2.7.6 -< Vary: Accept, Cookie -< X-Frame-Options: SAMEORIGIN -< Allow: GET, PUT, PATCH, DELETE, OPTIONS -< -* Closing connection 0 -``` - -The response to a successful `DELETE` request will have code 204 (No Content); the body of the response will be empty. - - -## Bulk Object Creation - -The REST API supports the creation of multiple objects of the same type using a single `POST` request. For example, to create multiple devices: - -``` -curl -X POST -H "Authorization: Token " -H "Content-Type: application/json" -H "Accept: application/json; indent=4" http://localhost:8000/api/dcim/devices/ --data '[ -{"name": "device1", "device_type": 24, "device_role": 17, "site": 6}, -{"name": "device2", "device_type": 24, "device_role": 17, "site": 6}, -{"name": "device3", "device_type": 24, "device_role": 17, "site": 6}, -]' -``` - -Bulk creation is all-or-none: If any of the creations fails, the entire operation is rolled back. A successful response returns an HTTP code 201 and the body of the response will be a list/array of the objects created. \ No newline at end of file diff --git a/docs/rest-api/overview.md b/docs/rest-api/overview.md index f29919202..6c1f59daa 100644 --- a/docs/rest-api/overview.md +++ b/docs/rest-api/overview.md @@ -13,8 +13,11 @@ Additionally, the `OPTIONS` verb can be used to inspect a particular REST API en One of the primary benefits of a REST API is its human-friendliness. Because it utilizes HTTP and JSON, it's very easy to interact with NetBox data on the command line using common tools. For example, we can request an IP address from NetBox and output the JSON using `curl` and `jq`. The following command makes an HTTP `GET` request for information about a particular IP address, identified by its primary key, and uses `jq` to present the raw JSON data returned in a more human-friendly format. (Piping the output through `jq` isn't strictly required but makes it much easier to read.) +```no-highlight +curl -s http://netbox/api/ipam/ip-addresses/2954/ | jq '.' ``` -$ curl -s http://netbox/api/ipam/ip-addresses/2954/ | jq '.' + +```json { "id": 2954, "url": "http://netbox/api/ipam/ip-addresses/2954/", @@ -94,7 +97,7 @@ See the [filtering documentation](filtering.md) for more details. The REST API employs two types of serializers to represent model data: base serializers and nested serializers. The base serializer is used to present the complete view of a model. This includes all database table fields which comprise the model, and may include additional metadata. A base serializer includes relationships to parent objects, but **does not** include child objects. For example, the `VLANSerializer` includes a nested representation its parent VLANGroup (if any), but does not include any assigned Prefixes. -``` +```json { "id": 1048, "site": { @@ -134,7 +137,7 @@ Related objects (e.g. `ForeignKey` fields) are represented using nested serializ For example, when creating a new device, its rack can be specified by NetBox ID (PK): -``` +```json { "name": "MyNewDevice", "rack": 123, @@ -144,7 +147,7 @@ For example, when creating a new device, its rack can be specified by NetBox ID Or by a set of nested attributes which uniquely identify the rack: -``` +```json { "name": "MyNewDevice", "rack": { @@ -159,6 +162,53 @@ Or by a set of nested attributes which uniquely identify the rack: Note that if the provided parameters do not return exactly one object, a validation error is raised. +### Generic Relations + +Some objects within NetBox have attributes which can reference an object of multiple types, known as _generic relations_. For example, an IP address can be assigned to either a device interface _or_ a virtual machine interface. When making this assignment via the REST API, we must specify two attributes: + +* `assigned_object_type` - The content type of the assigned object, defined as `.` +* `assigned_object_id` - The assigned object's unique numeric ID + +Together, these values identify a unique object in NetBox. The assigned object (if any) is represented by the `assigned_object` attribute on the IP address model. + +```no-highlight +curl -X POST \ +-H "Authorization: Token $TOKEN" \ +-H "Content-Type: application/json" \ +-H "Accept: application/json; indent=4" \ +http://netbox/api/ipam/ip-addresses/ \ +--data '{ + "address": "192.0.2.1/24", + "assigned_object_type": "dcim.interface", + "assigned_object_id": 69023 +}' +``` + +```json +{ + "id": 56296, + "url": "http://netbox/api/ipam/ip-addresses/56296/", + "assigned_object_type": "dcim.interface", + "assigned_object_id": 69000, + "assigned_object": { + "id": 69000, + "url": "http://netbox/api/dcim/interfaces/69023/", + "device": { + "id": 2174, + "url": "http://netbox/api/dcim/devices/2174/", + "name": "device105", + "display_name": "device105" + }, + "name": "ge-0/0/0", + "cable": null, + "connection_status": null + }, + ... +} +``` + +If we wanted to assign this IP address to a virtual machine interface instead, we would have set `assigned_object_type` to `virtualization.vminterface` and updated the object ID appropriately. + ### Brief Format Most API endpoints support an optional "brief" format, which returns only a minimal representation of each object in the response. This is useful when you need only a list of available objects without any related data, such as when populating a drop-down list in a form. As an example, the default (complete) format of an IP address looks like this: @@ -262,7 +312,7 @@ http://netbox/api/dcim/devices/?limit=100 The response will return devices 1 through 100. The URL provided in the `next` attribute of the response will return devices 101 through 200: -``` +```json { "count": 2861, "next": "http://netbox/api/dcim/devices/?limit=100&offset=100", @@ -283,7 +333,7 @@ The maximum number of objects that can be returned is limited by the [`MAX_PAGE_ To query NetBox for a list of objects, make a `GET` request to the model's _list_ endpoint. Objects are listed under the response object's `results` parameter. ```no-highlight -$ curl -s -X GET http://netbox/api/ipam/ip-addresses/ | jq '.' +curl -s -X GET http://netbox/api/ipam/ip-addresses/ | jq '.' ``` ```json @@ -320,7 +370,7 @@ To query NetBox for a single object, make a `GET` request to the model's _detail Note that the trailing slash is required. Omitting this will return a 302 redirect. ```no-highlight -$ curl -s -X GET http://netbox/api/ipam/ip-addresses/5618/ | jq '.' +curl -s -X GET http://netbox/api/ipam/ip-addresses/5618/ | jq '.' ``` ```json @@ -333,7 +383,7 @@ $ curl -s -X GET http://netbox/api/ipam/ip-addresses/5618/ | jq '.' ### Creating a New Object -To create a new object, make a `POST` request to the model's _list_ endpoint with JSON data pertaining to the object being created. Note that a REST API token is required for all write operations; see the [authentication documentation](../authentication.md) for more information. Also be sure to set the `Content-Type` HTTP header to `application/json`. +To create a new object, make a `POST` request to the model's _list_ endpoint with JSON data pertaining to the object being created. Note that a REST API token is required for all write operations; see the [authentication documentation](../authentication/) for more information. Also be sure to set the `Content-Type` HTTP header to `application/json`. ```no-highlight curl -s -X POST \ @@ -375,12 +425,51 @@ http://netbox/api/ipam/prefixes/ \ } ``` -### Modifying an Object +### Creating Multiple Objects -To modify an object which has already been created, make a `PATCH` request to the model's `detail` endpoint specifying its unique numeric ID. Include any data which you wish to update on the object. As with object creation, the `Authorization` and `Content-Type` headers must also be specified. +To create multiple instances of a model using a single request, make a `POST` request to the model's _list_ endpoint with a list of JSON objects representing each instance to be created. If successful, the response will contain a list of the newly created instances. The example below illustrates the creation of three new sites. ```no-highlight -$ curl -s -X PATCH \ +curl -X POST -H "Authorization: Token $TOKEN" \ +-H "Content-Type: application/json" \ +-H "Accept: application/json; indent=4" \ +http://netbox/api/dcim/sites/ \ +--data '[ +{"name": "Site 1", "slug": "site-1", "region": {"name": "United States"}}, +{"name": "Site 2", "slug": "site-2", "region": {"name": "United States"}}, +{"name": "Site 3", "slug": "site-3", "region": {"name": "United States"}} +]' +``` + +```json +[ + { + "id": 21, + "url": "http://netbox/api/dcim/sites/21/", + "name": "Site 1", + ... + }, + { + "id": 22, + "url": "http://netbox/api/dcim/sites/22/", + "name": "Site 2", + ... + }, + { + "id": 23, + "url": "http://netbox/api/dcim/sites/23/", + "name": "Site 3", + ... + } +] +``` + +### Modifying an Object + +To modify an object which has already been created, make a `PATCH` request to the model's _detail_ endpoint specifying its unique numeric ID. Include any data which you wish to update on the object. As with object creation, the `Authorization` and `Content-Type` headers must also be specified. + +```no-highlight +curl -s -X PATCH \ > -H "Authorization: Token 98dbec0b912e5f3ddec7183c48e73b38fa9ca793" \ > -H "Content-Type: application/json" \ > http://netbox/api/ipam/prefixes/18691/ \ @@ -419,6 +508,9 @@ $ curl -s -X PATCH \ } ``` +!!! note "PUT versus PATCH" + The NetBox REST API support the use of either `PUT` or `PATCH` to modify an existing object. The difference is that a `PUT` request requires the user to specify a _complete_ representation of the object being modified, whereas a `PATCH` request need include only the attributes that are being updated. For most purposes, using `PATCH` is recommended. + ### Deleting an Object To delete an object from NetBox, make a `DELETE` request to the model's _detail_ endpoint specifying its unique numeric ID. The `Authorization` header must be included to specify an authorization token, however this type of request does not support passing any data in the body. diff --git a/docs/rest-api/working-with-secrets.md b/docs/rest-api/working-with-secrets.md index 129bd0855..dafbb7239 100644 --- a/docs/rest-api/working-with-secrets.md +++ b/docs/rest-api/working-with-secrets.md @@ -1,16 +1,19 @@ # Working with Secrets -As with most other objects, the NetBox API can be used to create, modify, and delete secrets. However, additional steps are needed to encrypt or decrypt secret data. +As with most other objects, the REST API can be used to view, create, modify, and delete secrets. However, additional steps are needed to encrypt or decrypt secret data. ## Generating a Session Key In order to encrypt or decrypt secret data, a session key must be attached to the API request. To generate a session key, send an authenticated request to the `/api/secrets/get-session-key/` endpoint with the private RSA key which matches your [UserKey](../../core-functionality/secrets/#user-keys). The private key must be POSTed with the name `private_key`. -``` -$ curl -X POST http://localhost:8000/api/secrets/get-session-key/ \ --H "Authorization: Token c639d619ecbeb1f3055c4141ba6870e20572edd7" \ +```no-highlight +$ curl -X POST http://netbox/api/secrets/get-session-key/ \ +-H "Authorization: Token $TOKEN" \ -H "Accept: application/json; indent=4" \ --data-urlencode "private_key@" +``` + +```json { "session_key": "dyEnxlc9lnGzaOAV1dV/xqYPV63njIbdZYOgnAlGPHk=" } @@ -19,94 +22,106 @@ $ curl -X POST http://localhost:8000/api/secrets/get-session-key/ \ !!! note To read the private key from a file, use the convention above. Alternatively, the private key can be read from an environment variable using `--data-urlencode "private_key=$PRIVATE_KEY"`. -The request uses your private key to unlock your stored copy of the master key and generate a session key which can be attached in the `X-Session-Key` header of future API requests. +The request uses the provided private key to unlock your stored copy of the master key and generate a temporary session key, which can be attached in the `X-Session-Key` header of future API requests. ## Retrieving Secrets A session key is not needed to retrieve unencrypted secrets: The secret is returned like any normal object with its `plaintext` field set to null. -``` -$ curl http://localhost:8000/api/secrets/secrets/2587/ \ --H "Authorization: Token c639d619ecbeb1f3055c4141ba6870e20572edd7" \ +```no-highlight +$ curl http://netbox/api/secrets/secrets/2587/ \ +-H "Authorization: Token $TOKEN" \ -H "Accept: application/json; indent=4" +``` + +```json { "id": 2587, + "url": "http://netbox/api/secrets/secrets/2587/", "device": { "id": 1827, - "url": "http://localhost:8000/api/dcim/devices/1827/", + "url": "http://netbox/api/dcim/devices/1827/", "name": "MyTestDevice", "display_name": "MyTestDevice" }, "role": { "id": 1, - "url": "http://localhost:8000/api/secrets/secret-roles/1/", + "url": "http://netbox/api/secrets/secret-roles/1/", "name": "Login Credentials", "slug": "login-creds" }, "name": "admin", "plaintext": null, "hash": "pbkdf2_sha256$1000$G6mMFe4FetZQ$f+0itZbAoUqW5pd8+NH8W5rdp/2QNLIBb+LGdt4OSKA=", + "tags": [], + "custom_fields": {}, "created": "2017-03-21", "last_updated": "2017-03-21T19:28:44.265582Z" } ``` -To decrypt a secret, we must include our session key in the `X-Session-Key` header: +To decrypt a secret, we must include our session key in the `X-Session-Key` header when sending the `GET` request: -``` -$ curl http://localhost:8000/api/secrets/secrets/2587/ \ --H "Authorization: Token c639d619ecbeb1f3055c4141ba6870e20572edd7" \ +```no-highlight +$ curl http://netbox/api/secrets/secrets/2587/ \ +-H "Authorization: Token $TOKEN" \ -H "Accept: application/json; indent=4" \ -H "X-Session-Key: dyEnxlc9lnGzaOAV1dV/xqYPV63njIbdZYOgnAlGPHk=" +``` + +```json { "id": 2587, + "url": "http://netbox/api/secrets/secrets/2587/", "device": { "id": 1827, - "url": "http://localhost:8000/api/dcim/devices/1827/", + "url": "http://netbox/api/dcim/devices/1827/", "name": "MyTestDevice", "display_name": "MyTestDevice" }, "role": { "id": 1, - "url": "http://localhost:8000/api/secrets/secret-roles/1/", + "url": "http://netbox/api/secrets/secret-roles/1/", "name": "Login Credentials", "slug": "login-creds" }, "name": "admin", "plaintext": "foobar", "hash": "pbkdf2_sha256$1000$G6mMFe4FetZQ$f+0itZbAoUqW5pd8+NH8W5rdp/2QNLIBb+LGdt4OSKA=", + "tags": [], + "custom_fields": {}, "created": "2017-03-21", "last_updated": "2017-03-21T19:28:44.265582Z" } ``` -Lists of secrets can be decrypted in this manner as well: +Multiple secrets within a list can be decrypted in this manner as well: -``` -$ curl http://localhost:8000/api/secrets/secrets/?limit=3 \ --H "Authorization: Token c639d619ecbeb1f3055c4141ba6870e20572edd7" \ +```no-highlight +$ curl http://netbox/api/secrets/secrets/?limit=3 \ +-H "Authorization: Token $TOKEN" \ -H "Accept: application/json; indent=4" \ -H "X-Session-Key: dyEnxlc9lnGzaOAV1dV/xqYPV63njIbdZYOgnAlGPHk=" +``` + +```json { "count": 3482, - "next": "http://localhost:8000/api/secrets/secrets/?limit=3&offset=3", + "next": "http://netbox/api/secrets/secrets/?limit=3&offset=3", "previous": null, "results": [ { "id": 2587, - ... "plaintext": "foobar", ... }, { "id": 2588, - ... "plaintext": "MyP@ssw0rd!", ... }, { "id": 2589, - ... "plaintext": "AnotherSecret!", ... }, @@ -114,25 +129,44 @@ $ curl http://localhost:8000/api/secrets/secrets/?limit=3 \ } ``` -## Creating Secrets +## Creating and Updating Secrets -Session keys are also used to decrypt new or modified secrets. This is done by setting the `plaintext` field of the submitted object: +Session keys are required when creating or modifying secrets. The secret's `plaintext` attribute is set to its non-encrypted value, and NetBox uses the session key to compute and store the encrypted value. -``` -$ curl -X POST http://localhost:8000/api/secrets/secrets/ \ +```no-highlight +$ curl -X POST http://netbox/api/secrets/secrets/ \ -H "Content-Type: application/json" \ --H "Authorization: Token c639d619ecbeb1f3055c4141ba6870e20572edd7" \ +-H "Authorization: Token $TOKEN" \ -H "Accept: application/json; indent=4" \ -H "X-Session-Key: dyEnxlc9lnGzaOAV1dV/xqYPV63njIbdZYOgnAlGPHk=" \ --data '{"device": 1827, "role": 1, "name": "backup", "plaintext": "Drowssap1"}' +``` + +```json { - "id": 2590, - "device": 1827, - "role": 1, + "id": 6194, + "url": "http://netbox/api/secrets/secrets/9194/", + "device": { + "id": 1827, + "url": "http://netbox/api/dcim/devices/1827/", + "name": "device43", + "display_name": "device43" + }, + "role": { + "id": 1, + "url": "http://netbox/api/secrets/secret-roles/1/", + "name": "Login Credentials", + "slug": "login-creds" + }, "name": "backup", - "plaintext": "Drowssap1" + "plaintext": "Drowssap1", + "hash": "pbkdf2_sha256$1000$J9db8sI5vBrd$IK6nFXnFl+K+nR5/KY8RSDxU1skYL8G69T5N3jZxM7c=", + "tags": [], + "custom_fields": {}, + "created": "2020-08-05", + "last_updated": "2020-08-05T16:51:14.990506Z" } ``` !!! note - Don't forget to include the `Content-Type: application/json` header when making a POST request. + Don't forget to include the `Content-Type: application/json` header when making a POST or PATCH request. diff --git a/mkdocs.yml b/mkdocs.yml index 477c8e653..a94aa3cc4 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -67,7 +67,6 @@ nav: - Filtering: 'rest-api/filtering.md' - Authentication: 'rest-api/authentication.md' - Working with Secrets: 'rest-api/working-with-secrets.md' - - Examples: 'rest-api/examples.md' - Development: - Introduction: 'development/index.md' - Style Guide: 'development/style-guide.md'