Define a configuration for the secrets engine
In the Define a backend for the secrets engine tutorial, you configured the secrets engine to retrieve attributes and create a new client to access your target API.
In this tutorial, you will create a configuration schema for your
secrets engine. The configuration will include attributes passed
through the config
path of the secrets engine.
To do this, you will:
- Set up your development environment.
You will clone the HashiCups secrets engine repository. This contains many of the interfaces and objects you need to create a secrets engine. - Define the fields for the secrets engine's configuration.
You will define a set of fields that a Vault operator passes to configure the secrets engine. - Implement read for the secrets engine's configuration.
You will implement a method to handle reading the configuration from the secrets engine backend. - Implement create and update for the secrets engine's configuration.
You will implement a method to handle writing the configuration to the secrets engine backend. - Implement delete for the secrets engine's configuration.
You will implement a method to handle deletion of the configuration from the secrets engine backend. - Add the configuration path to the backend.
You will update the backend to add a new API path for the configuration. - Explore unit tests that verify the configuration path.
You will examine unit tests that check that Vault can create, read, update, and delete the secrets engine configuration.
Prerequisites
- Golang 1.16+ installed and configured.
- Vault 1.8+ CLI installed locally.
Note
Complete the tutorial to define the backend for the secrets engine.
Set up your development environment
Clone the learn-vault-plugin-secrets-hashicups repository.
Change into the repository directory.
Note
If you are stuck in this tutorial, refer to the
vault-plugin-secrets-hashicups/solution
directory.
Define the fields for the secrets engine's configuration
Open path_config.go
. The file contains all of the objects
and methods related to setting up the config
path for
the secrets engine.
Note
Replace the methods and structs in the scaffold with the embedded code examples.
The file should already include implementation for the following:
configStoragePath
: defines theconfig
path for the secrets engine's configuration.hashiCupsConfig
: defines a configuration object with username, password, and URL to the target API (HashiCups).getConfig
: passes the context and storage path for Vault to store thehashiCupsConfig
into theconfig
path for the secrets engine.
However, the pathConfig
method returns an object with empty fields.
These attributes defined framework.Path
extend the Vault API for
the secrets engine's config
path.
Replace the pathConfig
method in the scaffold.
You must define the Fields
that extend the Vault config
endpoint. They must
match the attributes in hashiCupsConfig
. Each field attribute must include the following:
Type
: All of the attributes forhashiCupsConfig
useType.String
. You can find a list of types in the Vault SDK documentation.Description
: Purpose of the attributeRequired
: Used for OpenAPI output. Whether or not a Vault operator must define the attribute when configuring the secrets engine. You must enforce it in the handler of your secrets engine, the schema will not enforce it for you!DisplayAttr
: Used for OpenAPI output. Includes name and whether or not it should be output based on the value inSensitive
.
1 2 3 4 5 6 7 8 9 1011121314151617181920212223242526272829303132333435363738
The pathConfig
includes additional attributes for the configuration, such
as ExistenceCheck
. ExistenceCheck
calls the pathConfigExistenceCheck
function,
which verifies whether or not the configuration already exists in Vault.
Note
Adding an ExistenceCheck
will affect your Vault
access control list (ACL) policy
for the secrets engine. When you define the ExistenceCheck
for the configuration,
a Vault operator setting up the secrets engine must have the create
capability
to add the configuration.
1 2 3 4 5 6 7 8 9 1011121314151617181920212223242526272829303132333435363738394041424344454647
The path includes attributes for help text, such as HelpSynopsis
and HelpDescription
.
The help text describes the attributes someone needs to configure the secrets engine.
1 2 3 4 5 6 7 8 9 10111213141516171819202122232425262728293031323334353637383940414243444546474849
Implement read for the secrets engine's configuration
Open path_config.go
. The file contains all of the objects
and methods related to setting up the config
path for
the secrets engine.
Note
Replace the methods and structs in the scaffold with the embedded code examples.
The Operations
field in the pathConfig
method starts empty.
You need to add methods to the Operations
field to tell Vault
how to handle creating, reading, updating, and deleting information
at the config
path.
Note
When you build a secrets engine and define its configuration, you need to implement operations to read, create, update and delete information at each API path you define for the secrets engine.
Create a new method named pathConfigRead
in path_config.go
.
The method reads the configuration and outputs non-sensitive fields,
specifically the HashiCups username and URL.
Under the Operations
field, add logical.ReadOperation
to the list
of OperationHandler
and callback to pathConfigRead
. The secrets engine
responds to a read operation from Vault with this method.
1 2 3 4 5 6 7 8 9 101112131415161718192021222324252627282930313233343536373839404142
Implement create and update for the secrets engine's configuration
Open path_config.go
. The file contains all of the objects
and methods related to setting up the config
path for
the secrets engine.
Note
Replace the methods and structs in the scaffold with the embedded code examples.
Create a new method named pathConfigWrite
in path_config.go
.
The method accounts for specific logic, including:
- If the configuration does not exist and you need to update it, the handler throws an error.
- Verify you passed a username, URL, and password for the target API
to the configuration using the
GetOk
method. You useGetOk
to enforce required attributes during aCreateOperation
. - Write the new or updated configuration using
Storage.Put
. - Reset the configuration so Vault picks up the new configuration.
Under the Operations
field, add logical.CreateOperation
and
logical.UpdateOperation
to the list of OperationHandler
.
Both operations should callback to pathConfigWrite
.
1 2 3 4 5 6 7 8 9 101112131415161718192021222324252627282930313233343536373839404142434445464748
Note
For most secrets engines, you can consolidate handling for create and update of fields. Ensure that the method runs idempotently (repeatedly running the function does not change the fields, unless you make changes).
Implement delete for the secrets engine's configuration
Open path_config.go
. The file contains all of the objects
and methods related to setting up the config
path for
the secrets engine.
Note
Replace the methods and structs in the scaffold with the embedded code examples.
Create a new method named pathConfigDelete
in path_config.go
.
The method deletes the configuration from the secrets engine backend
and resets the secrets engine.
123456789
Under the Operations
field, add logical.DeleteOperation
to the list of OperationHandler
. It should callback to pathConfigDelete
.
1 2 3 4 5 6 7 8 9 101112131415161718192021222324252627282930313233343536373839404142434445464748495051
Add the configuration path to the backend
For each API path you extend on the secrets engine, you must add it to the secrets engine backend.
Note
Replace the methods and structs in the scaffold with the embedded code examples.
Open backend.go
and replace backend
to add pathConfig
to the list
of valid paths for the backend.
1 2 3 4 5 6 7 8 9 1011121314151617181920212223
Note
If you do not add your path to the backend object,
you will get an error of unsupported path
in your tests
and compiled plugin.
Explore unit tests that verify the configuration path
The Vault Plugin SDK includes a testing framework for unit and acceptance tests.
- Unit tests: Use mocks to verify the functionality of the secrets engine
- Acceptance tests: Require a Vault instance, an active target API endpoint, and binary for the secrets engine.
You can write a set of unit tests to pass in fields and mock the Vault backend. The tests verify secrets engine creates, reads, updates, and deletes the configuration.
Open backend_test.go
and examine getTestBackend
. The method
mocks a backend object using the Vault Plugin SDK. It references the
interfaces in the HashiCups backend Factory
.
1 2 3 4 5 6 7 8 9 101112131415
Note
You can reuse getTestBackend
for your own secrets engine. Return
your secrets engine's backend object instead of hashiCupsBackend
.
Open path_config_test.go
. The file includes a set of
constants that you will pass as configuration fields for the config
path.
The HashiCups configuration requires username, password, and URL. The unit
tests will not issue requests to the API endpoint.
Examine the method TestConfig
. It creates the mock backend
with getTestBackend
and runs a series of tests creating,
reading, updating, and deleting the configuration using the
constants.
Examine testConfigCreate
as an example. It calls the
mock backend with a logical.CreateOperation
at the path,
config
. The data includes the configuration fields defined
as constants, such as username, password, and URL.
1 2 3 4 5 6 7 8 9 1011121314151617
TestConfig
runs the tests sequentially and passes the same
storage object between tests. You should write your test sequence as follows:
- Create the configuration.
- Read the configuration to test if the create succeeded.
- Update the configuration.
- Read the configuration to test if the update succeeded.
- Delete the configuration.
- Check for errors.
Open a terminal and make sure your working directory uses
the plugins/vault-plugin-secrets-hashicups
.
Run the configuration path tests in your terminal. The tests should pass.
Next steps
Congratulations! You added the config
path to your secrets engine.
If you are stuck in this tutorial, refer to the
plugins/vault-plugin-secrets-hashicups/solution
directory.
- To learn more about Vault plugins, refer to the Vault Plugin System Documentation.
- Define your secrets engine's roles in the next tutorial.