This adds support for encrypting and decrypting secrets. It implements the APIs required for unsealing. The APIs are not complete or compliant. Reviewed-on: #1 Squashed commit of the following: commitd77237aefeAuthor: C0ffeeCode <ritters_werth@outlook.com> Date: Wed Apr 2 18:59:33 2025 +0200 Refactor: Secret struct and feature-gates - Shamir and its dependencies behind a default feature - Secret has its own struct commit6eb02c8412Author: C0ffeeCode <ritters_werth@outlook.com> Date: Wed Apr 2 08:28:28 2025 +0200 Feat (sealing): Shamir Secret Sharing scheme commit5de9e1d74eAuthor: C0ffeeCode <ritters_werth@outlook.com> Date: Thu Mar 27 22:13:57 2025 +0100 Fix (sealing): Simple sealing with random nonce commit88ed714e22Author: C0ffeeCode <ritters_werth@outlook.com> Date: Thu Mar 27 17:13:48 2025 +0100 Feat (sealing): Simple Password sealing Password is generated on first startup. The password given to the user is not same as the one used to encrypt secrets commit4d342e8b99Author: C0ffeeCode <ritters_werth@outlook.com> Date: Wed Mar 26 21:51:27 2025 +0100 Feat (kv2): Support Sealing commit1accd45648Author: C0ffeeCode <ritters_werth@outlook.com> Date: Wed Mar 26 21:49:59 2025 +0100 WIP feat (sealing): Implement basic sealing functionality Currently, the key is just stored plainly in the database commit7949d64649Author: C0ffeeCode <ritters_werth@outlook.com> Date: Wed Mar 26 21:39:07 2025 +0100 Chore: Rename `DatabaseDriver` to `DbPool` and add a custom serde serializer `serialize_reject_none` as a utility
123 lines
3.9 KiB
Go
123 lines
3.9 KiB
Go
package tests
|
|
|
|
import (
|
|
"context"
|
|
"log"
|
|
"os"
|
|
"reflect"
|
|
"testing"
|
|
"time"
|
|
|
|
// "github.com/hashicorp/vault-client-go"
|
|
// "github.com/hashicorp/vault-client-go/schema"
|
|
vault "github.com/hashicorp/vault/api"
|
|
// vault "github.com/openbao/openbao/api/v2"
|
|
)
|
|
|
|
var Client *vault.Client
|
|
var ctx context.Context
|
|
|
|
func TestMain(m *testing.M) {
|
|
ctx = context.Background()
|
|
var err error
|
|
|
|
config := vault.DefaultConfig()
|
|
config.Address = "http://localhost:8200"
|
|
config.Timeout = 30 * time.Second
|
|
|
|
// prepare a client with the given base address
|
|
Client, err = vault.NewClient(config)
|
|
if err != nil {
|
|
log.Fatalf("unable to initialize Vault client: %v", err)
|
|
}
|
|
log.Println("client prepared")
|
|
|
|
// authenticate with a root token (insecure)
|
|
Client.SetToken("my-token")
|
|
|
|
exitCode := m.Run() // run all tests and get code
|
|
os.Exit(exitCode)
|
|
}
|
|
|
|
// Requires in-code portions
|
|
// func TestUnseal(t *testing.T) {
|
|
// abc := []string{
|
|
// "eyJpIjpbMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwxXSwidiI6WzE4OCw2NiwxMTksMTQ0LDE1OSw3MCw4NiwxMTUsMTIwLDI1MywxMjQsOTYsMTM5LDk0LDQ1LDE2NiwyMTMsMzYsMTE1LDU4LDg5LDE0OCw2MCwyOCwxNTAsMTE2LDU3LDg5LDIwMCw5NywxNDYsMjEzXX0=",
|
|
// "eyJpIjpbMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwyXSwidiI6WzE1OCwyNDQsNzEsOTUsMTIyLDEzOCwyNDEsMjEzLDQ1LDE1NiwxMTgsNCwxNzYsNiwxNTcsMTkyLDE2MSwxNjEsNDMsMTc1LDE5NSw4NywxODAsMTAwLDE1NiwxNCwxNDgsMTUsMTc4LDkwLDY3LDExOF19",
|
|
// }
|
|
// for i := range abc {
|
|
// if _, err := Client.Sys().Unseal(abc[i]); err != nil {
|
|
// t.Fatal("Error unsealing", err)
|
|
// }
|
|
|
|
// }
|
|
// }
|
|
|
|
func kv2Write(t *testing.T, mount string, path string) {
|
|
data := map[string]any{
|
|
"password1": "123abc",
|
|
"password2": "horse horse horse battery staple correct",
|
|
}
|
|
t.Logf("Attempting to write to KV2 %s path %s:\t", mount, path)
|
|
v, err := Client.KVv2(mount).Put(ctx, path, data)
|
|
if err != nil {
|
|
t.Fatal("ERROR writing secret:\n\t", err)
|
|
}
|
|
t.Log("Success (unchecked)\n\t", v)
|
|
|
|
res, err := Client.KVv2(mount).Get(ctx, path)
|
|
if err != nil {
|
|
t.Fatal("ERROR checking/reading secret (request failed)\n\t", err)
|
|
}
|
|
if !reflect.DeepEqual(res.Data, data) {
|
|
t.Fatal("AAAAH", res.Data)
|
|
t.Fatalf("ERROR secret received does not match what was outght to be written.\n\tWritten: %s\n\tReceived: %s\n", data, res.Data)
|
|
// t.Fatal("\tWritten: ", newVar.Data)
|
|
// t.Fatal("\tReceived:", res.Data.Data)
|
|
}
|
|
t.Logf("SUCCESS writing to KV2 %s path %s\n", mount, path)
|
|
}
|
|
|
|
func kv2Delete(t *testing.T, mount string, path string) {
|
|
err := Client.KVv2(mount).Delete(ctx, path) // currently disregarding modifier options
|
|
if err != nil {
|
|
log.Fatal("ERROR deleting secret:\n\t", err)
|
|
}
|
|
res, err := Client.KVv2(mount).Get(ctx, path)
|
|
if res != nil || err == nil {
|
|
t.Fatal("ERROR checking/reading secret (request failed)\n\t", res, err)
|
|
}
|
|
t.Logf("SUCCESS deleting KV2 secret %s path %s\n", mount, path)
|
|
}
|
|
|
|
// https://developer.hashicorp.com/vault/api-docs/secret/kv/kv-v2#create-update-secret
|
|
// @Philip der Path steht in der KvV2Write Methode
|
|
func TestWriteSecret(t *testing.T) {
|
|
// Apparently used as a default if mountpath is an empty string (client library)
|
|
var mountpath = "/kv-v2"
|
|
var mountpath2 = "/some"
|
|
|
|
// Path foo
|
|
t.Logf("Writing to first KV2 engine at %s...", mountpath)
|
|
kv2Write(t, mountpath, "foo")
|
|
kv2Write(t, mountpath, "bar")
|
|
t.Logf("Writing to second KV2 engine at %s...", mountpath2)
|
|
kv2Write(t, mountpath2, "foo")
|
|
kv2Write(t, mountpath2, "bar")
|
|
t.Logf("Deleting...")
|
|
kv2Delete(t, mountpath, "foo")
|
|
}
|
|
|
|
// func TestDeleteSecret(t *testing.T) {
|
|
// _, err := client.Secrets.KvV2Delete(ctx, "foo") // currently disregarding modifier options
|
|
// if err != nil {
|
|
// log.Fatal("kv2: Failed to delete secret:\n\t", err)
|
|
// }
|
|
// }
|
|
|
|
// func TestReadSecret(t *testing.T) {
|
|
// _, err := client.Secrets.KvV2Read(ctx, "bar")
|
|
// if err != nil {
|
|
// log.Fatal("kv2: Failed to read secret:\n\t", err)
|
|
// }
|
|
// }
|