June 20-22 Announcing HashiConf Europe full schedule: keynotes, sessions, labs & more Register Now
  • Infrastructure
    • terraform
    • packer
  • Networking
    • consul
  • Security
    • vault
    • boundary
  • Applications
    • nomad
    • waypoint
    • vagrant
  • HashiCorp Cloud Platform

    A fully managed platform to automate infrastructure on any cloud with HashiCorp products.

    • consul
    • terraform
    • vault
    • packerbeta
    Visit cloud.hashicorp.com
  • Overview
  • Tutorials
  • Docs
  • API
  • Community
GitHub—Stars on GitHub
Download
    • v0.8.x (latest)
    • v0.7.x
    • v0.6.x
    • v0.5.x
    • v0.4.x
    • v0.3.x
    • v0.2.x
    • v0.1.x
  • What is Boundary?
    • Overview
      • Overview
      • Production
    • Run and Login
    • Connect to Target
    • Overview
    • Non-Dev Environments
    • Systemd Install
    • Postgres Install
    • High Availability Install
    • Reference Architectures
    • Overview
    • API
    • CLI
    • Go SDK
    • Desktop
    • Desktop
    • Overview
    • Service Discovery
      • Overview
        • Overview
        • Assignable Permissions
        • Permission Grant Formats
        • Resource Table
      • Data Encryption
      • Connections/TLS
      • Overview
      • Accounts
      • Auth Methods
      • Credentials
      • Credential Libraries
      • Credential Stores
      • Groups
      • Hosts
      • Host Catalogs
      • Host Sets
      • Managed Groups
      • Scopes
      • Sessions
      • Session Connections
      • Targets
      • Roles
      • Users
      • Overview
      • OIDC Managed Groups
      • Resource Listing
      • Worker Tags
      • Events
    • Overview
    • Building
    • Developing the UI

    • Overview
      • Overview
      • TCP
      • Unix
      • Overview
      • AEAD
      • AWS KMS
      • AliCloud KMS
      • Azure Key Vault
      • GCP Cloud KMS
      • OCI KMS
      • Vault Transit
    • controller
    • worker
      • Overview
      • Common Sink Parameters
      • File Sink
      • Stderr Sink
    • plugins
    • Overview
    • Metrics
    • Health Endpoint
  • Common Workflows
    • Overview
    • Manage Roles
    • Manage Scopes
    • Manage Sessions
    • Manage Targets
    • Manage Users and Groups
    • Workflow SSH Proxy

  • Roadmap
    • Overview
    • v0.8.0
    • v0.7.0
    • v0.6.0
    • v0.5.0
    • v0.4.0
    • v0.3.0
    • v0.2.0
    • v0.1.0
Type '/' to Search

»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 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. 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 auth method
  2. Via the recovery KMS workflow

We'll cover how to authenticate to Boundary via both of these workflows.

»Auth Method

This is the most common way for a client to authenticate to Boundary. To demonstrate this, we'll use the 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:

// The default address points to the default dev mode address
client, err := api.NewClient(nil)
if err != nil {
  return err
}
// The default address points to the default dev mode address
client, err := api.NewClient(nil)
if err != nil {
  return err
}

The authenticate method 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 create an attributes map to pass this data:

credentials := map[string]interface{}{
  "login_name": "admin",
  "password":   "password",
}
credentials := map[string]interface{}{
  "login_name": "admin",
  "password":   "password",
}

Now let's create an auth method client using the base client from above:

amClient := authmethods.NewClient(client)
amClient := 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:

$ 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
$ 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:

authenticationResult, err := amClient.Authenticate(context.Background(), "ampw_1234567890", "login", credentials)
if err != nil {
  return err
}
authenticationResult, err := amClient.Authenticate(context.Background(), "ampw_1234567890", "login", credentials)
if err != nil {
  return err
}

Lastly, let's update the original client with the token we got from the Authenticate() call:

// pass this client to any other resource specific API resources
client.SetToken(fmt.Sprint(authenticationResult.Attributes["token"]))
// pass this client to any other resource specific API resources
client.SetToken(fmt.Sprint(authenticationResult.Attributes["token"]))

Putting this all together:

import (
  "context"

  "github.com/hashicorp/boundary/api"
  "github.com/hashicorp/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
}

amClient := authmethods.NewClient(client)
authenticationResult, err := amClient.Authenticate(context.Background(), "ampw_1234567890", "login", credentials)
if err != nil {
  return err
}

// pass this client to any other resource specific API resources
client.SetToken(fmt.Sprint(authenticationResult.Attributes["token"]))
import (
  "context"

  "github.com/hashicorp/boundary/api"
  "github.com/hashicorp/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
}

amClient := authmethods.NewClient(client)
authenticationResult, err := amClient.Authenticate(context.Background(), "ampw_1234567890", "login", credentials)
if err != nil {
  return err
}

// pass this client to any other resource specific API resources
client.SetToken(fmt.Sprint(authenticationResult.Attributes["token"]))

»Recovery KMS Workflow

The recovery KMS workflow allows you to use a valid KMS configuration 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.

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"
}
`
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:

w, err := wrapper.GetWrapperFromHcl(kmsConfig, "recovery")
if err != nil {
  return err
}

client.SetRecoveryKmsWrapper(w)
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.

Putting this all together:

import (
  "context"

  "github.com/hashicorp/boundary/api"
  "github.com/hashicorp/boundary/sdk/wrapper"
)

const kmsConfig = `
kms "aead" {
    purpose = "recovery"
    aead_type = "aes-gcm"
    key = "8fZBjCUfN0TzjEGLQldGY4+iE9AkOvCfjh7+p0GtRBQ="
    key_id = "recovery_kms"
}
`

// The default address points to the default dev mode address
client, err := api.NewClient(nil)
if err != nil {
  return err
}

w, err := wrapper.GetWrapperFromHcl(kmsConfig, "recovery")
if err != nil {
  return err
}

client.SetRecoveryKmsWrapper(w)
import (
  "context"

  "github.com/hashicorp/boundary/api"
  "github.com/hashicorp/boundary/sdk/wrapper"
)

const kmsConfig = `
kms "aead" {
    purpose = "recovery"
    aead_type = "aes-gcm"
    key = "8fZBjCUfN0TzjEGLQldGY4+iE9AkOvCfjh7+p0GtRBQ="
    key_id = "recovery_kms"
}
`

// The default address points to the default dev mode address
client, err := api.NewClient(nil)
if err != nil {
  return err
}

w, err := wrapper.GetWrapperFromHcl(kmsConfig, "recovery")
if err != nil {
  return err
}

client.SetRecoveryKmsWrapper(w)
github logoEdit this page
DocsLearnPrivacySecurityPress KitConsent Manager