Consul is a tool for service discovery and configuration. It provides a way to discover services and manage configurations in a distributed system.
Vault is a service that help us to manage secrets and protect sensitive data. It provides a secure way to store and access secrets like API keys, passwords, certificates, etc.
Both are similar tools provided by HashiCorp Where we can access the services using the HTTP API.
Let’s see how we can connect to Consul and Vault using Golang.
Prerequisites
- Consul & Vault server running
docker compose file to run
services:
vault:
image: hashicorp/vault
container_name: vault
ports:
- 8200:8200 # Expose Vault's UI and API port
environment:
- VAULT_DEV_ROOT_TOKEN_ID=myroot
cap_add:
- IPC_LOCK # Required for Vault to lock memory
volumes:
- ./vault-data:/vault/file # Persist Vault data
consul:
image: hashicorp/consul
container_name: consul
ports:
- 8500:8500 # Expose Consul's UI and API port
Create some values in Consul
docker exec -it consul_container consul kv put config/myapp '{"host": "http://localhost"}'
Create some secrets in Vault
docker exec -it -e VAULT_ADDR=http://127.0.0.1:8200 -e VAULT_TOKEN=myroot vault_container vault kv put secret/myapp username=admin password=admin123
Connecting to Consul and Vault using Golang
We need to install the client package to connect to Consul and Vault.
go get github.com/hashicorp/consul/api
go get github.com/hashicorp/vault/api
Here is an example code to connect to Vault using Golang.
package main
import (
"context"
"encoding/json"
"log"
consul "github.com/hashicorp/consul/api"
vault "github.com/hashicorp/vault/api"
)
func vaultRead() {
config := vault.DefaultConfig()
config.Address = "http://127.0.0.1:8200"
client, err := vault.NewClient(config)
if err != nil {
log.Fatalf("unable to initialize Vault client: %v", err)
}
// Authenticate
client.SetToken("myroot")
ctx := context.Background()
// Read a secret
secret, err := client.KVv2("secret").Get(ctx, "myapp")
if err != nil {
log.Fatalf("unable to read secret: %v", err)
}
value, ok := secret.Data["username"].(string)
if !ok {
log.Fatalf("unable to read username: %v", err)
}
log.Println("Username:", value)
// Username: admin
}
type ConsulConfig struct {
Host string `json:"host"`
}
func consulRead() {
// Connect to Consul
config := consul.DefaultConfig()
config.Address = "http://127.0.0.1:8500"
// Create a new client
client, err := consul.NewClient(config)
if err != nil {
log.Fatalf("unable to initialize Vault client: %v", err)
}
// Read a value
pair, _, err := client.KV().Get("config/myapp", nil)
if err != nil {
log.Fatalf("unable to read secret: %v", err)
}
log.Println("Host:", string(pair.Value))
var consulConfig ConsulConfig
if err := json.Unmarshal(pair.Value, &consulConfig); err != nil {
log.Fatalf("unable to unmarshal Consul config: %v", err)
}
log.Println("Host:", consulConfig.Host)
// Host: http://localhost
}
func main() {
vaultRead()
consulRead()
}
It’s pretty simple to connect to Consul and Vault using Golang. We can use the client packages provided by HashiCorp to connect to the services.
The http api by Consul and Vault is simple to use and we can easily connect to the services using Golang clients provided by HashiCorp.
That’s it. We have seen how to connect to Consul and Vault using Golang.