The following items are new for Chef server 12.1:
- **chef-server-ctl key commands use the chef-client Chef::Key
object** The key rotation commands (`chef-server-ctl key`) for
`create`, `delete`, `edit`, `list`, and `show` keys for users and
clients. These were a preview in the Chef server 12.0.3 release, and
are now fully integrated.
- **New version headers for Chef Server API** The Chef server API uses
the `X-Ops-Server-API-Version` header to specify the version of the
API that is used as part of a request to the Chef server API.
- **New endpoints for policy and policy files** The Chef server API
adds the following endpoints: `/policies`, `/policy_groups`, and
`/POLICY_GROUP/policies/POLICY_NAME`.
- **New endpoints for client key management** The Chef server API adds
the following endpoints: `/clients/CLIENT/keys` and
`/clients/CLIENT/keys/KEY`.
- **New endpoints for user key management** The Chef server API adds
the following endpoints: `/user/USER/keys` and
`/user/USER/keys/KEY`.
- **New configuration setting** Use the `estatsd['protocol']` setting
to send application statistics with StatsD protocol formatting.
## Key Rotation
The `knife user` and `knife client` subcommands support key rotation.
Use the `create`, `delete`, `edit`, `list`, and `show` subcommands to
manage keys for users and clients, such as creating multiple expiring
keys for a single user and also for basic key management. See
/knife_user.html and /knife_client.html for more information about
these subcommands.
## X-Ops-Server-API-Version
Use `X-Ops-Server-API-Version` to specify the version of the Chef server
API. For example: `X-Ops-Server-API-Version: 1`.
`X-Ops-Server-API-Version: 0` is supported for use with the version 12
Chef server, but will be deprecated as part of the next major release.
## /clients/CLIENT/keys/
The `/clients/CLIENT/keys` endpoint has the following methods: `GET` and
`POST`.
### GET
The `GET` method is used to retrieve all of the named client's key
identifiers, associated URIs, and expiry states.
This method has no parameters.
**Request**
```none
GET /organizations/NAME/clients/CLIENT/keys
```
**Response**
The response is similar to:
```javascript
[
{ "name" : "default",
"uri" : "https://chef.example/organizations/example/clients/client1/keys/default",
"expired" : false },
{ "name" : "key1",
"uri" : "https://chef.example/organizations/example/clients/client1/keys/key1",
"expired" : true }
]
```
**Response Codes**
200 |
OK. The request was successful. |
401 |
Unauthorized. The user or client who made the request could not be authenticated. Verify the user/client name, and that the correct key was used to sign the request. |
403 |
Forbidden. The user who made the request is not authorized to perform the action. |
404 |
Not found. The requested object does not exist. |
### POST
The `POST` method is used to add a key for the specified client.
This method has no parameters.
**Request**
```none
POST /organizations/NAME/clients/CLIENT/keys
```
with a request body similar to:
```javascript
{
"name": "key1",
"public_key": "-------- BEGIN PUBLIC KEY ----and a valid key here",
"expiration_date": "infinity"
}
```
**Response**
The response is similar to:
```javascript
{
"uri": "https://chef.example/organizations/example/clients/client1/keys/key1"
}
```
**Response Codes**
201 |
Created. The object was created. |
401 |
Unauthorized. The user or client who made the request could not be authenticated. Verify the user/client name, and that the correct key was used to sign the request. |
403 |
Forbidden. The user who made the request is not authorized to perform the action. |
404 |
Not found. The requested object does not exist. |
## /clients/CLIENT/keys/KEY
The `/clients/CLIENT/keys/KEY` endpoint has the following methods:
`DELETE`, `GET`, and `PUT`.
### DELETE
The `DELETE` method is used to delete the specified key for the
specified client.
This method has no parameters.
**Request**
```none
DELETE /organizations/NAME/clients/CLIENT/keys/KEY
```
**Response**
The response returns the information about the deleted key and is
similar to:
```javascript
{
"name" : "default",
"public_key" : "-------- BEGIN PUBLIC KEY --------- ...",
"expiration_date" : "2020-12-31T00:00:00Z"
}
```
**Response Codes**
200 |
OK. The request was successful. |
401 |
Unauthorized. The user or client who made the request could not be authenticated. Verify the user/client name, and that the correct key was used to sign the request. |
403 |
Forbidden. The user who made the request is not authorized to perform the action. |
404 |
Not found. The requested object does not exist. |
### GET
The `GET` method is used to return details for a specific key for a
specific client.
This method has no parameters.
**Request**
```none
GET /organizations/NAME/clients/CLIENT/keys/KEY
```
**Response**
The response is similar to:
```javascript
{
"name" : "default",
"public_key" : "-------- BEGIN PUBLIC KEY --------- ...",
"expiration_date" : "2020-12-31T00:00:00Z"
}
```
**Response Codes**
200 |
OK. The request was successful. |
401 |
Unauthorized. The user or client who made the request could not be authenticated. Verify the user/client name, and that the correct key was used to sign the request. |
403 |
Forbidden. The user who made the request is not authorized to perform the action. |
404 |
Not found. The requested object does not exist. |
### PUT
The `PUT` method is used to update one or more properties for a specific
key for a specific client.
This method has no parameters.
**Request**
```none
PUT /organizations/NAME/clients/CLIENT/keys/KEY
```
with a request body similar to:
```javascript
{
"name" : "new_key_name",
"public_key" : "-------- BEGIN PUBLIC KEY ----and a valid key here",
"expiration_date" : "2020-12-31T00:00:00Z"
}
```
**Response**
The response contains the updated information for the key, and is
similar to:
```javascript
{
"name" : "new_key_name",
"public_key" : "-------- BEGIN PUBLIC KEY --------- ...",
"expiration_date" : "2020-12-31T00:00:00Z"
}
```
**Response Codes**
200 |
OK. The request was successful. |
201 |
Created. The object was created. |
401 |
Unauthorized. The user or client who made the request could not be authenticated. Verify the user/client name, and that the correct key was used to sign the request. |
403 |
Forbidden. The user who made the request is not authorized to perform the action. |
404 |
Not found. The requested object does not exist. |
## /user/USER/keys/
The `/users/USER/keys` endpoint has the following methods: `GET` and
`POST`.
### GET
The `GET` method is used to retrieve all of the named user's key
identifiers, associated URIs, and expiry states.
This method has no parameters.
**Request**
```none
GET /users/USER/keys/
```
**Response**
The response is similar to:
```javascript
[
{ "name" : "default",
"uri" : "https://chef.example/users/USER/keys/default",
"expired" : false },
{ "name" : "key1",
"uri" : "https://chef.example/users/USER/keys/key1",
"expired" : false}
]
```
**Response Codes**
200 |
OK. The request was successful. |
401 |
Unauthorized. The user or client who made the request could not be authenticated. Verify the user/client name, and that the correct key was used to sign the request. |
403 |
Forbidden. The user who made the request is not authorized to perform the action. |
404 |
Not found. The requested object does not exist. |
### POST
The `POST` method is used to add a key for the specified user.
This method has no parameters.
**Request**
```none
POST /users/USER/keys/
```
with a request body similar to:
```javascript
{
"name" : "key1",
"public_key" : "-------- BEGIN PUBLIC KEY ----and a valid key here",
"expiration_date" : "infinity"
}
```
**Response**
The response is similar to:
```javascript
{
"uri" : "https://chef.example/users/user1/keys/key1"
}
```
**Response Codes**
201 |
Created. The object was created. |
401 |
Unauthorized. The user or client who made the request could not be authenticated. Verify the user/client name, and that the correct key was used to sign the request. |
403 |
Forbidden. The user who made the request is not authorized to perform the action. |
404 |
Not found. The requested object does not exist. |
## /user/USER/keys/KEY
The `/users/USER/keys/KEY` endpoint has the following methods: `DELETE`,
`GET`, and `PUT`.
### DELETE
The `DELETE` method is used to delete the specified key for the
specified user.
This method has no parameters.
**Request**
```none
DELETE /users/USER/keys/KEY
```
**Response**
The response returns the information about the deleted key and is
similar to:
```javascript
{
"name" : "default",
"public_key" : "-------- BEGIN PUBLIC KEY --------- ...",
"expiration_date" : "2020-12-31T00:00:00Z"
}
```
**Response Codes**
200 |
OK. The request was successful. |
401 |
Unauthorized. The user or client who made the request could not be authenticated. Verify the user/client name, and that the correct key was used to sign the request. |
403 |
Forbidden. The user who made the request is not authorized to perform the action. |
404 |
Not found. The requested object does not exist. |
### GET
The `GET` method is used to return details for a specific key for a
specific user.
This method has no parameters.
**Request**
```none
GET /users/USER/keys/KEY
```
**Response**
The response is similar to:
```javascript
{
"name" : "default",
"public_key" : "-------- BEGIN PUBLIC KEY --------- ...",
"expiration_date" : "2020-12-31T00:00:00Z"
}
```
**Response Codes**
200 |
OK. The request was successful. |
401 |
Unauthorized. The user or client who made the request could not be authenticated. Verify the user/client name, and that the correct key was used to sign the request. |
403 |
Forbidden. The user who made the request is not authorized to perform the action. |
404 |
Not found. The requested object does not exist. |
### PUT
The `PUT` method is used to update one or more properties for a specific
key for a specific user.
This method has no parameters.
**Request**
```none
PUT /users/USER/keys/KEY
```
with a request body similar to:
```javascript
{
"name" : "new_key_name",
"public_key" : "-------- BEGIN PUBLIC KEY ----and a valid key here",
"expiration_date" : "2020-12-31T00:00:00Z"
}
```
**Response**
The response contains the updated information for the key, and is
similar to:
```javascript
{
"name" : "new_key_name",
"public_key" : "-------- BEGIN PUBLIC KEY --------- ...",
"expiration_date" : "2020-12-31T00:00:00Z"
}
```
**Response Codes**
200 |
OK. The request was successful. |
201 |
Created. The object was created. |
401 |
Unauthorized. The user or client who made the request could not be authenticated. Verify the user/client name, and that the correct key was used to sign the request. |
403 |
Forbidden. The user who made the request is not authorized to perform the action. |
404 |
Not found. The requested object does not exist. |
## /policies
The `/policies` endpoint has the following methods: `GET`.
### GET
The `GET` method is used to get a list of policies (including policy
revisions) from the Chef server.
This method has no parameters.
**Request**
```none
GET /organizations/NAME/policies
```
**Response**
The response groups policies by name and revision and is similar to:
```javascript
{
"aar": {
"uri": "https://chef.example/organizations/org1/policies/aar",
"revisions": {
"37f9b658cdd1d9319bac8920581723efcc2014304b5f3827ee0779e10ffbdcc9": {
},
"95040c199302c85c9ccf1bcc6746968b820b1fa25d92477ea2ec5386cd58b9c5": {
},
"d81e80ae9bb9778e8c4b7652d29b11d2111e763a840d0cadb34b46a8b2ca4347": {
}
}
},
"jenkins": {
"uri": "https://chef.example/organizations/org1/policies/jenkins",
"revisions": {
"613f803bdd035d574df7fa6da525b38df45a74ca82b38b79655efed8a189e073": {
},
"6fe753184c8946052d3231bb4212116df28d89a3a5f7ae52832ad408419dd5eb": {
},
"cc1a0801e75df1d1ea5b0d2c71ba7d31c539423b81478f65e6388b9ee415ad87": {
}
}
}
}
```
**Response Codes**
200 |
OK. The request was successful. |
403 |
Forbidden. The user who made the request is not authorized to perform the action. |
## /policy_groups
The `/policy_groups` endpoint has the following methods: `GET`.
Each node has a 1:many relationship with policy settings stored on the
Chef server. This relationship is based on the policy group to which the
node is associated, and then the policy settings assigned to that group:
- A policy is typically named after the functional role ahost
performs, such as "application server", "chat server", "load
balancer", and so on
- A policy group defines a set of hosts in a deployed units, typically
mapped to organizational requirements such as "dev", "test",
"staging", and "production", but can also be mapped to more detailed
requirements as needed
### GET
The `GET` method is used to retrieve all of the policy groups that are
stored on the Chef server.
This method has no parameters.
**Request**
```none
GET /organizations/NAME/policy_groups
```
**Response**
The response is similar to:
```javascript
{
"dev": {
"uri": "https://chef.example/organizations/org1/policy_groups/dev",
"policies": {
"aar": {
"revision_id": "95040c199302c85c9ccf1bcc6746968b820b1fa25d92477ea2ec5386cd58b9c5"
},
"jenkins": {
"revision_id": "613f803bdd035d574df7fa6da525b38df45a74ca82b38b79655efed8a189e073"
}
}
},
"production": {
"uri": "https://chef.example/organizations/org1/policy_groups/production",
"policies": {
"aar": {
"revision_id": "95040c199302c85c9ccf1bcc6746968b820b1fa25d92477ea2ec5386cd58b9c5"
}
}
}
}
```
**Response Codes**
200 |
OK. The request was successful. |
401 |
Unauthorized. The user or client who made the request could not be authenticated. Verify the user/client name, and that the correct key was used to sign the request. |
403 |
Forbidden. The user who made the request is not authorized to perform the action. |
404 |
Not found. The requested object does not exist. |
## /policies/NAME
The `/policies/NAME` endpoint has the following methods: `DELETE`,
`GET`, and `PUT`. These endpoints enable the management of policies as
they relate to a specific policy group.
Each node has a 1:many relationship with policy settings stored on the
Chef server. This relationship is based on the policy group to which the
node is associated, and then the policy settings assigned to that group:
- A policy is typically named after the functional role ahost
performs, such as "application server", "chat server", "load
balancer", and so on
- A policy group defines a set of hosts in a deployed units, typically
mapped to organizational requirements such as "dev", "test",
"staging", and "production", but can also be mapped to more detailed
requirements as needed
Each policy group and individual policy are separate objects for the
purposes of authentication. This enables each policy and policy group to
have restricted access, such as for specific nodes that handle sensitive
data or for specific production groups that require sign-off as part of
organizational requirements.
A requestor must have permission to both the policy and the policy group
in order for any action to be authorized.
### DELETE
The `DELETE` method is used to delete the association between a specific
policy document, specific policy group, and specific policy revision.
This method does not delete anything from the Chef server.
This method has no parameters.
**Request**
```none
DELETE /organizations/NAME/GROUP/policies/NAME
```
**Response**
The response returns the policy details and is similar to:
```javascript
{
"revision_id": "37f9b658cdd1d9319bac8920581723efcc2014304b5f3827ee0779e10ffbdcc9",
"name": "aar",
"run_list": [
"recipe[aar::default]"
],
"cookbook_locks": {
"aar": {
"version": "0.1.0",
"identifier": "29648fe36333f573d5fe038a53256e23733618aa",
"dotted_decimal_identifier": "11651043203167221.32604909279531813.121098535835818",
"source": "cookbooks/aar",
"cache_key": null,
"scm_info": {
"scm": "git",
"remote": null,
"revision": "a2c8cbb24a08625921d753cde36e8320465116c3",
"working_tree_clean": false,
"published": false,
"synchronized_remote_branches": [
]
},
"source_options": {
"path": "cookbooks/aar"
}
},
"apt": {
"version": "2.7.0",
"identifier": "16c57abbd056543f7d5a15dabbb03261024a9c5e",
"dotted_decimal_identifier": "6409580415309396.17870749399956400.55392231660638",
"cache_key": "apt-2.7.0-supermarket.chef.io",
"origin": "https://supermarket.chef.io/api/v1/cookbooks/apt/versions/2.7.0/download",
"source_options": {
"artifactserver": "https://supermarket.chef.io/api/v1/cookbooks/apt/versions/2.7.0/download",
"version": "2.7.0"
}
}
},
"default_attributes": {
},
"override_attributes": {
},
"solution_dependencies": {
"Policyfile": [
[
"aar",
">= 0.0.0"
],
[
"apt",
"= 2.7.0"
],
],
"dependencies": {
"apt (2.7.0)": [
],
"aar (0.1.0)": [
[
"apt",
">= 0.0.0"
]
]
}
}
}
```
**Response Codes**
200 |
OK. The request was successful. |
401 |
Unauthorized. The user or client who made the request could not be authenticated. Verify the user/client name, and that the correct key was used to sign the request. |
403 |
Forbidden. The user who made the request is not authorized to perform the action. |
404 |
Not found. The requested object does not exist. |
### GET
The `GET` method is used to return a policy document for a specific
policy group and policy.
This method has no parameters.
**Request**
```none
GET /organizations/NAME/GROUP/policies/NAME
```
**Response**
The response is similar to:
```javascript
{
"revision_id": "37f9b658cdd1d9319bac8920581723efcc2014304b5f3827ee0779e10ffbdcc9",
"name": "aar",
"run_list": [
"recipe[aar::default]"
],
"cookbook_locks": {
"aar": {
"version": "0.1.0",
"identifier": "29648fe36333f573d5fe038a53256e23733618aa",
"dotted_decimal_identifier": "11651043203167221.32604909279531813.121098535835818",
"source": "cookbooks/aar",
"cache_key": null,
"scm_info": {
"scm": "git",
"remote": null,
"revision": "a2c8cbb24a08625921d753cde36e8320465116c3",
"working_tree_clean": false,
"published": false,
"synchronized_remote_branches": [
]
},
"source_options": {
"path": "cookbooks/aar"
}
},
"apt": {
"version": "2.7.0",
"identifier": "16c57abbd056543f7d5a15dabbb03261024a9c5e",
"dotted_decimal_identifier": "6409580415309396.17870749399956400.55392231660638",
"cache_key": "apt-2.7.0-supermarket.chef.io",
"origin": "https://supermarket.chef.io/api/v1/cookbooks/apt/versions/2.7.0/download",
"source_options": {
"artifactserver": "https://supermarket.chef.io/api/v1/cookbooks/apt/versions/2.7.0/download",
"version": "2.7.0"
}
}
},
"default_attributes": {
},
"override_attributes": {
},
"solution_dependencies": {
"Policyfile": [
[
"aar",
">= 0.0.0"
],
[
"apt",
"= 2.7.0"
],
],
"dependencies": {
"apt (2.7.0)": [
],
"aar (0.1.0)": [
[
"apt",
">= 0.0.0"
]
]
}
}
}
```
**Response Codes**
200 |
OK. The request was successful. |
401 |
Unauthorized. The user or client who made the request could not be authenticated. Verify the user/client name, and that the correct key was used to sign the request. |
403 |
Forbidden. The user who made the request is not authorized to perform the action. |
404 |
Not found. The requested object does not exist. |
### PUT
The `PUT` method is used to create or update an association between a
specific policy document, specific policy group, and specific policy
revision.
This method has no parameters.
**Request**
```none
PUT /organizations/NAME/GROUP/policies/NAME
```
with a request body similar to:
```javascript
{
"revision_id": "37f9b658cdd1d9319bac8920581723efcc2014304b5f3827ee0779e10ffbdcc9",
"name": "aar",
"run_list": [
"recipe[aar::default]"
],
"cookbook_locks": {
"aar": {
"version": "0.1.0",
"identifier": "29648fe36333f573d5fe038a53256e23733618aa",
"dotted_decimal_identifier": "11651043203167221.32604909279531813.121098535835818",
"source": "cookbooks/aar",
"cache_key": null,
"scm_info": {
"scm": "git",
"remote": null,
"revision": "a2c8cbb24a08625921d753cde36e8320465116c3",
"working_tree_clean": false,
"published": false,
"synchronized_remote_branches": [
]
},
"source_options": {
"path": "cookbooks/aar"
}
},
"apt": {
"version": "2.7.0",
"identifier": "16c57abbd056543f7d5a15dabbb03261024a9c5e",
"dotted_decimal_identifier": "6409580415309396.17870749399956400.55392231660638",
"cache_key": "apt-2.7.0-supermarket.chef.io",
"origin": "https://supermarket.chef.io/api/v1/cookbooks/apt/versions/2.7.0/download",
"source_options": {
"artifactserver": "https://supermarket.chef.io/api/v1/cookbooks/apt/versions/2.7.0/download",
"version": "2.7.0"
}
}
},
"default_attributes": {
},
"override_attributes": {
},
"solution_dependencies": {
"Policyfile": [
[
"aar",
">= 0.0.0"
],
[
"apt",
"= 2.7.0"
],
],
"dependencies": {
"apt (2.7.0)": [
],
"aar (0.1.0)": [
[
"apt",
">= 0.0.0"
]
]
}
}
}
```
**Response**
The response returns the policy details and is similar to:
```javascript
{
"revision_id": "37f9b658cdd1d9319bac8920581723efcc2014304b5f3827ee0779e10ffbdcc9",
"name": "aar",
"run_list": [
"recipe[aar::default]"
],
"cookbook_locks": {
"aar": {
"version": "0.1.0",
"identifier": "29648fe36333f573d5fe038a53256e23733618aa",
"dotted_decimal_identifier": "11651043203167221.32604909279531813.121098535835818",
"source": "cookbooks/aar",
"cache_key": null,
"scm_info": {
"scm": "git",
"remote": null,
"revision": "a2c8cbb24a08625921d753cde36e8320465116c3",
"working_tree_clean": false,
"published": false,
"synchronized_remote_branches": [
]
},
"source_options": {
"path": "cookbooks/aar"
}
},
"apt": {
"version": "2.7.0",
"identifier": "16c57abbd056543f7d5a15dabbb03261024a9c5e",
"dotted_decimal_identifier": "6409580415309396.17870749399956400.55392231660638",
"cache_key": "apt-2.7.0-supermarket.chef.io",
"origin": "https://supermarket.chef.io/api/v1/cookbooks/apt/versions/2.7.0/download",
"source_options": {
"artifactserver": "https://supermarket.chef.io/api/v1/cookbooks/apt/versions/2.7.0/download",
"version": "2.7.0"
}
}
},
"default_attributes": {
},
"override_attributes": {
},
"solution_dependencies": {
"Policyfile": [
[
"aar",
">= 0.0.0"
],
[
"apt",
"= 2.7.0"
],
],
"dependencies": {
"apt (2.7.0)": [
],
"aar (0.1.0)": [
[
"apt",
">= 0.0.0"
]
]
}
}
}
```
**Response Codes**
200 |
OK. The request was successful. |
201 |
Created. The object was created. |
401 |
Unauthorized. The user or client who made the request could not be authenticated. Verify the user/client name, and that the correct key was used to sign the request. |
403 |
Forbidden. The user who made the request is not authorized to perform the action. |
404 |
Not found. The requested object does not exist. |
## New Config Settings
The following configuration settings are new for the Chef server:
estatsd['protocol'] |
Use to send application statistics with StatsD protocol formatting. Set this value to statsd to apply StatsD protocol formatting. |