Consolidate client/API information to a new section (#630)
This commit is contained in:
1 parent
837e9eb0cc
commit
e162f9f183
7 files changed
+62
-73
No files matched your search
@@ -0,0 +1,80 @@
|
||||
---
|
||||
layout: docs
|
||||
page_title: API
|
||||
sidebar_title: API
|
||||
description: |-
|
||||
Boundary's HTTP API standards
|
||||
---
|
||||
|
||||
# API
|
||||
|
||||
Boundary's API is a a JSON-based HTTP API that adheres to a set of standards that are rigidly followed. At its core, it is a standards-compliant JSON API for both input and output.
|
||||
|
||||
Before reading this page, it is useful to understand Boundary's [domain model](/docs/concetps/domain-model) to be aware of the terminology used here.
|
||||
|
||||
Boundary's API is also described via OpenAPI v2; the version corresponding to any tag of Boundary's source code can be found in Boundary's [GitHub repository](https://github.com/hashicorp/boundary/blob/main/internal/gen/controller.swagger.json).
|
||||
|
||||
Boundary's current API version is 1; all API paths begin with `/v1/`.
|
||||
|
||||
## Status Codes
|
||||
|
||||
* `2XX`: Boundary returns a code between `200` and `299` on success. Generally this is `200`, but implementations should be prepared to accept any `2XX` status code as indicating success. If a call returns a `2XX` code that is not `200`, it will follow well-understood semantics for those status codes.
|
||||
* `400`: Boundary returns `400` when a command cannot be completed due to invalid user input, except for a properly-formatted identifier that does not map to an existing resource, which will return a `404` as discussed below.
|
||||
* `401`: Boundary returns `401` if no authentication token is provided or if the provided token is invalid. A valid token that simply does not have permission for a resource will return a `403` instead. A token that is invalid or missing, but where the anonymous user (`u_anon`) is able to successfully perform the action, will not return a `401` but instead will return the result of the action.
|
||||
* `403`: Boundary returns `403` if a provided token was valid but does not have the grants required to perform the requested action.
|
||||
* `404`: Boundary returns `404` if a resource cannot be found. Note that this happens _prior_ to authentication/authorization checking in nearly all cases as the resource information (such as its scope, available actions, etc.) is a required part of that check. As a result, an action against a resource that does not exist will return a `404` instead of a `401` or `403`. While this could be considered an information leak, since IDs are randomly generated and this only discloses whether an ID is valid, it's tolerable as it allows for far simpler and more robust client implementation.
|
||||
* `405`: Boundary returns a `405` to indicate that the method (HTTP verb or custom action) is not implemented for the given resource.
|
||||
* `500`: Boundary returns `500` if an error occurred that is not (directly) tied to invalid user input. If a `500` is generated, information about the error will be logged to Boundary's server log but is not generally provided to the client.
|
||||
|
||||
## Path Layout
|
||||
|
||||
Boundary follows a predictable path layout. There are two fundamental types of URL paths, each supporting a different set of operations.
|
||||
|
||||
### Collections
|
||||
|
||||
Collections of resources are top level paths with plural English names for the resource, e.g. `/roles` and `/hosts`. Collections support the following operations:
|
||||
|
||||
* Creation of new resources within that collection
|
||||
* Listing of resources within that collection
|
||||
|
||||
All collection operations require supplying the enclosing resource. Depending on the collection type, this will be one of the following:
|
||||
|
||||
* A scope, indicating the scope in which an operation should take place. For instance, a POST to `/roles` would need to indicate whether the role should be created within the `global` scope or some organization scope like `o_1234567890`.
|
||||
* A parent resource of the appropriate type. For instance, hosts and host sets are child resources of host catalogs. When creating a new host set within a host catalog, a POST to `/host-sets` would need to indicate the host catalog ID with which the host-set should be associated.
|
||||
|
||||
### Resources
|
||||
|
||||
Resources themselves are defined by ID specifiers within a collection path, e.g. `/roles/r_1234567890`. Resources support the following operations:
|
||||
|
||||
* Reading a resource's properties
|
||||
* Updating a resource's properties
|
||||
* Deleting a resource
|
||||
* Custom methods specific to a resource type
|
||||
|
||||
Depending on the resource type, various parameters may be available. Some are common across all resource types (e.g. `name` and `description`); others are available only for specific types. Further, some concrete-types of abstract resources include an opaque `attributes` JSON object with type-specific values.
|
||||
|
||||
For instance, an authentication method is an abstract type; a `password` authentication method is a concrete implementation of that type. When creating such an auth method, a `type` parameter will indicate that it should be the `password` type, while values specific to the `password` type auth method, such as minimum password length, will be contained within an `attributes` object.
|
||||
|
||||
## Methods
|
||||
|
||||
The following method conventions are used within Boundary's API:
|
||||
|
||||
### GET
|
||||
|
||||
`GET` is used for reading a resource or listing resources in a collection. The behavior depends on whether the `GET` is issued against a collection (`/roles`) or a singular resource (`/roles/r_1234567890`). In the former case it lists resources within the collection; in the latter it performs a read on that particular resource.
|
||||
|
||||
### POST
|
||||
|
||||
`POST` is used for creating a resource or performing custom actions against a resoruce. When creating a resource, `POST` is used against a collection (`/roles`). When performing a custom action, `POST` is used against a particular resource (`/roles/r_1234567890:set-principals`).
|
||||
|
||||
### PATCH
|
||||
|
||||
`PATCH` is used to update a resource's parameters. The following are behaviors to be aware of when using `PATCH`:
|
||||
|
||||
* In nearly all cases, a `version` parameter is required. This is used for check-and-set, to ensure that the update operation is being performed against a known resource. The version parameter is returned from a `GET` operation on the resource so the current version, along with the resource's other current values, can be looked up at any time.
|
||||
* Passing a JSON `null` for a parameter has the effect of reverting that parameter to its default. For some parameters (e.g. `name`) this will simply clear the value (as the default `name` for a resource is empty); for other parameters this will revert to the current defaults within Boundary.
|
||||
* All parameters specified as part of a `PATCH` operation will be considered to be parameters that should be updated.
|
||||
|
||||
### DELETE
|
||||
|
||||
`DELETE` is used for deleting a specific resource, and is only used against a particular resource path.
|
||||
@@ -0,0 +1,84 @@
|
||||
---
|
||||
layout: docs
|
||||
page_title: CLI
|
||||
sidebar_title: CLI
|
||||
description: |-
|
||||
Boundary's CLI behavior
|
||||
---
|
||||
|
||||
# CLI
|
||||
|
||||
Boundary's CLI has predictable behavior throughout its various commands. This page details the common patterns in used in order to help users make better use of the CLI.
|
||||
|
||||
## Completion
|
||||
|
||||
Before detailing how parameters work, it's useful to note that Boundary's CLI supports autocompletion, which allows tab completion of commands, flags, and in some cases the parameters to those flags.
|
||||
|
||||
This can be installed via the CLI itself:
|
||||
|
||||
`boundary config autocomplete install`
|
||||
|
||||
If you want to install it manually, for Bash, the following line in a `~/.bash_profile` or similar file will work:
|
||||
|
||||
`complete -C /path/to/boundary boundary`
|
||||
|
||||
## Parameter Handling
|
||||
|
||||
All parameters specified on the CLI are specified as a Go-style flag with a single dash, e.g. `-id`. The arguments to those flags can be specified via an equals sign, as in `-id=r_1234567890`, or a space, like `-id r_1234567890`.
|
||||
|
||||
To see available parameters, pass the `-h` flag to any command.
|
||||
|
||||
Flags are semi-position dependent. The flags must come _after_ the command definition, but are otherwise order independent.
|
||||
|
||||
For instance, the following are equivalent:
|
||||
|
||||
* `boundary roles create -scope-id global -name foo`
|
||||
* `boundary roles create -name foo -scope-id global`
|
||||
|
||||
But the following results in an error:
|
||||
|
||||
* `boundary roles -name foo -scope-id global create`
|
||||
|
||||
This applies to `-h` as well!
|
||||
|
||||
### Connection Options
|
||||
|
||||
Every command that results in an API call contains a set of flags that control connection options, which control TLS and other settings for the connection.
|
||||
|
||||
### Client Options
|
||||
|
||||
Every command that results in an API call contains a set of flags that control client options. Some notable options:
|
||||
|
||||
* `output-curl-string`: This will format the command that would have been run as a string using `curl` that can be used directly on the command line. This is a great way to discover how CLI functions map to API calls.
|
||||
* `token-name`: When the CLI authenticates, it stores the token in the platform-specific OS credential store. By using the `token-name` parameter, more than one token can be stored at a time. Specifying this parameter at authentication time uses the given name as part of the key for storage; specifying it for any other command will cause the corresponding token to be used for that call.
|
||||
* `recovery-config`: This is used to specify a configuration file that contains the information necessary to access a KMS configured to be used for the recovery workflow within a Boundary controller.
|
||||
|
||||
### Output Options
|
||||
|
||||
Nearly every command supports having its success output be formatted as JSON via `-format json`. For commands that result in an API call, the JSON output will be the exact output from the controller. If using the output of the CLI in scripts or as parameters to other tools, _always_ use formatted output. The default text output is meant for human users and the formatting or the information included within that output from the original JSON may change at any time.
|
||||
|
||||
## Mapping to Collections and Sub-Types
|
||||
|
||||
Generally speaking, Boundary's CLI commands map to the collections they operate on. For instance, when operating on roles, the command will be `boundary roles ...`.
|
||||
|
||||
As a result, the patterns for reading, deleting, and listing are predictable:
|
||||
|
||||
* `boundary <collection> read`
|
||||
* `boundary <collection> delete`
|
||||
* `boundary <collection> list`
|
||||
|
||||
`read` and `delete` will always operate on a particular resource identifier, so will always take in an `-id` parameter. `list` operates on collections so will either take a `-scope-id` parameter or, depending on type, a higher level resource identifier, e.g. `-auth-method-id`.
|
||||
|
||||
Creating and updating resources may take an extra parameter if the resource type is abstract, that is, if the type cannot be operated on directly but must be operated on through an implementation. As an example, a role is not an abstract type, and does not have various implementations of it. As a result, a role can be operated on directly:
|
||||
|
||||
* `boundary roles create`
|
||||
* `boundary roles update`.
|
||||
|
||||
However, a target can be one of many types of targets, and a concrete implementation of a target is a `tcp` type of target. Therefore an extra parameter is required when creating or updating a target:
|
||||
|
||||
* `boundary targets tcp create`
|
||||
* `boundary targets tcp update`
|
||||
|
||||
This allows the CLI to perform proper presentation and validation of parameters and functions for the given type.
|
||||
|
||||
Similar to `read`, `update` operates on an existing target so will always take an `-id` parameter. Similar to `list`, `create` operates on a collection so will either take a `-scope-id` parameter or a parameter defining the parent resource.
|
||||
@@ -0,0 +1,173 @@
|
||||
---
|
||||
layout: docs
|
||||
page_title: Go SDK
|
||||
sidebar_title: Go SDK
|
||||
description: |-
|
||||
Boundary's Go SDK
|
||||
---
|
||||
|
||||
# Go SDK
|
||||
|
||||
Boundary has a Go SDK that sports full coverage of Boundary's API. This SDK is mostly auto-generated so the patterns are predictable from package to package; for the most part, browsing [pkg.go.dev](https://pkg.go.dev/github.com/hashicorp/boundary/api) is a great way to get started.
|
||||
|
||||
Below, an example walks through using the SDK to authenticate against an auth method or perform recovery workflows. The patterns for creating a resource-typed client are the same across packages.
|
||||
|
||||
## Authenticating to Boundary with the Go SDK
|
||||
|
||||
Authenticating to Boundary starts with an [Auth Method](/docs/concepts/domain-model/auth-methods). An auth method provides
|
||||
the basic identity delegation needed for Boundary to generate a token for a client. There are two primary methods for
|
||||
authenticating to Boundary:
|
||||
|
||||
1. Via an authentication method
|
||||
1. Via the recovery KMS workflow
|
||||
|
||||
We'll cover how to authenticate to Boundary via both of these workflows.
|
||||
|
||||
### Authentication Method
|
||||
|
||||
This is the most common way for a client to authenticate to Boundary. To demonstrate this, we'll
|
||||
use the [authmethods](https://github.com/hashicorp/boundary/tree/main/api/authmethods) library to generate
|
||||
a valid token for a client in Go.
|
||||
|
||||
For this example, we're going to use the Password auth method. This example
|
||||
assumes there's already a valid user and an associated account in Boundary
|
||||
against which the client can authenticate. To simplify this example, we're
|
||||
assuming you're running a Boundary instance in dev mode, where the default auth
|
||||
method, login name, and password are pre-configured.
|
||||
|
||||
First, we need to create a client from the Boundary API and set the address to reach Boundary:
|
||||
|
||||
```go
|
||||
import github.com/boundary/api
|
||||
|
||||
// The default address points to the default dev mode address
|
||||
client, err := api.NewClient(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
```
|
||||
|
||||
The [authenticate
|
||||
method](https://github.com/hashicorp/boundary/blob/main/api/authmethods/authenticate.go)
|
||||
uses a basic `map[string]interface{}` to pass credential information, in order
|
||||
to eventually support multiple auth method types. For this example, we assume
|
||||
you're using the password auth method and so we're going to tailor a credentials
|
||||
object to pass this data as:
|
||||
|
||||
```go
|
||||
credentials := map[string]interface{}{
|
||||
"login_name": "admin",
|
||||
"password": "password",
|
||||
}
|
||||
```
|
||||
|
||||
Now let's create an auth method client using the base client from above:
|
||||
|
||||
```go
|
||||
import "github.com/boundary/api/authmethods"
|
||||
|
||||
am := authmethods.NewClient(client)
|
||||
```
|
||||
|
||||
~> This creates a shallow copy of the base client. Modifications made to the client via `am.ApiClient()` will not be reflected in the base client.
|
||||
|
||||
The last thing you'll need is the ID of the auth method in Boundary. You can get this on the CLI
|
||||
with:
|
||||
|
||||
```bash
|
||||
$ boundary auth-methods list
|
||||
|
||||
Auth Method information:
|
||||
ID: ampw_1234567890
|
||||
Description: Provides initial administrative authentication into Boundary
|
||||
Name: Generated global scope initial auth method
|
||||
Type: password
|
||||
Version: 1
|
||||
```
|
||||
|
||||
Note the ID in the output above, we're going to use that in the next step.
|
||||
|
||||
We can use the credentials object we created to execute `Authenticate()` on this client:
|
||||
|
||||
```go
|
||||
at, err := am.Authenticate(context.Background(), "ampw_1234567890", credentials)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
```
|
||||
|
||||
Lastly, let's update the original client with the token we got from the `Authenticate()` call:
|
||||
|
||||
```go
|
||||
// pass this client to any other resource specific API resources
|
||||
client.SetToken(at.Item.Token)
|
||||
```
|
||||
|
||||
Putting this all together:
|
||||
|
||||
```go
|
||||
import (
|
||||
github.com/boundary/api
|
||||
github.com/boundary/api/authmethods
|
||||
)
|
||||
|
||||
credentials := map[string]interface{}{
|
||||
"login_name": "admin",
|
||||
"password": "password",
|
||||
}
|
||||
|
||||
// The default address points to the default dev mode address
|
||||
client, err := api.NewClient(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
am := authmethods.NewClient(client)
|
||||
at, err := am.Authenticate(context.Background(), "ampw_1234567890", credentials)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// pass this client to any other resource specific API resources
|
||||
client.SetToken(at.Item.Token)
|
||||
```
|
||||
|
||||
### Recovery KMS Workflow
|
||||
|
||||
The recovery KMS workflow allows you to use a valid [KMS
|
||||
configuration](/docs/configuration/kms) to authenticate and authorize calls
|
||||
within the Boundary API. For this example, we're going to assume you've read the
|
||||
above and know how to get a base Boundary API client.
|
||||
|
||||
Lets start with a valid KMS configuration for recovery that uses a hard coded
|
||||
AEAD key as the basis. To authenticate with Boundary using this config we're
|
||||
assuming you have an instance of Boundary that declares this as the recovery KMS
|
||||
in the Boundary controller config as well.
|
||||
|
||||
```go
|
||||
import "github.com/hashicorp/boundary/sdk/wrapper"
|
||||
|
||||
const kmsConfig := `
|
||||
kms "aead" {
|
||||
purpose = "recovery"
|
||||
aead_type = "aes-gcm"
|
||||
key = "8fZBjCUfN0TzjEGLQldGY4+iE9AkOvCfjh7+p0GtRBQ="
|
||||
key_id = "recovery_kms"
|
||||
}
|
||||
`
|
||||
```
|
||||
|
||||
Now lets use this config to configure our Boundary API client:
|
||||
|
||||
```go
|
||||
w, err := wrapper.GetWrapperFromHcl(kmsConfig, "recovery")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client.SetRecoveryKmsWrapper(w)
|
||||
```
|
||||
|
||||
The client will now use the recovery KMS wrapper for all authenticated calls
|
||||
(even if you have previously set a token). You can remove it by instantiating a
|
||||
new client, or by passing `nil` into `SetRecoveryKmsWrapper`.
|
||||
@@ -0,0 +1,14 @@
|
||||
---
|
||||
layout: docs
|
||||
page_title: API/Clients
|
||||
sidebar_title: API/Clients
|
||||
description: |-
|
||||
An introduction to Boundary's API and clients.
|
||||
---
|
||||
|
||||
|
||||
# Clients
|
||||
|
||||
Boundary is a purely-API-driven system. This section contains information
|
||||
describing its API norms and the clients that HashiCorp provide (apart from the
|
||||
web UI), which include a CLI and a Go SDK.
|
||||
Reference in new issue
Block a user