Files
zeekayandHanzo Dev 212410de59 The warehouse is reached as an IAM identity, never a password
A telemetry store now presents an IAM access token minted for the
datastore audience at every handshake, and has no other credential to
present. The token is the embedding process's identity, set by the host
rather than read from configuration: the standalone server mints its own
from IAM_CLIENT_ID and IAM_CLIENT_SECRET, and cloud hands the embed the
identity its o11y app already holds.

A DSN now says where the warehouse is and nothing else. One that names a
user or password is refused, and a store with no identity is not built.
Pooled connections live five minutes, so each replacement presents a
current token and a revoked identity keeps nothing for long.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-24 14:35:36 -07:00

86 lines
2.8 KiB
Go

package datastoretelemetrystore
import (
"bytes"
"context"
"net"
"testing"
"time"
"github.com/hanzoai/o11y/pkg/instrumentation/instrumentationtest"
"github.com/hanzoai/o11y/pkg/telemetrystore"
)
func config(dsn string, token func(context.Context) (string, error)) telemetrystore.Config {
return telemetrystore.Config{
Provider: "datastore",
Connection: telemetrystore.ConnectionConfig{MaxOpenConns: 1, MaxIdleConns: 1, DialTimeout: time.Second},
Datastore: telemetrystore.DatastoreConfig{DSN: dsn, Token: token},
}
}
func token(context.Context) (string, error) { return "iam.token.for-datastore", nil }
// The warehouse admits an IAM identity and nothing else, so a store with no
// identity to present is refused at construction rather than connected some
// other way.
func TestNoIdentityIsNoStore(t *testing.T) {
_, err := New(context.Background(), instrumentationtest.New().ToProviderSettings(), config("tcp://127.0.0.1:9000", nil))
if err == nil {
t.Fatal("a store with no IAM identity was built")
}
}
// A DSN says where the warehouse is. One that also says who is asking is the
// retired password path, and it is refused rather than half-honoured.
func TestADSNThatNamesACredentialIsRefused(t *testing.T) {
for _, dsn := range []string{
"tcp://default:[email protected]:9000",
"tcp://[email protected]:9000",
} {
if _, err := New(context.Background(), instrumentationtest.New().ToProviderSettings(), config(dsn, token)); err == nil {
t.Errorf("DSN %q carrying a credential built a store", dsn)
}
}
}
// With an identity and a bare address the store is built, and the handshake of
// every connection it opens carries the identity's token in the password field
// under the JWT marker — never a stored user or password.
func TestTheStorePresentsTheIdentity(t *testing.T) {
ln, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatal(err)
}
defer ln.Close()
hello := make(chan []byte, 1)
go func() {
c, err := ln.Accept()
if err != nil {
return
}
defer c.Close()
_ = c.SetReadDeadline(time.Now().Add(2 * time.Second))
buf := make([]byte, 4096)
n, _ := c.Read(buf)
hello <- buf[:n]
}()
s, err := New(context.Background(), instrumentationtest.New().ToProviderSettings(), config("tcp://"+ln.Addr().String(), token))
if err != nil {
t.Fatalf("build: %v", err)
}
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
_ = s.Datastore().Ping(ctx) // the fake answers nothing; the handshake is the point
select {
case h := <-hello:
if !bytes.Contains(h, []byte(" JWT AUTHENTICATION ")) || !bytes.Contains(h, []byte("iam.token.for-datastore")) {
t.Fatalf("the handshake carried %q; want the JWT marker and the identity's token", h)
}
case <-time.After(3 * time.Second):
t.Fatal("the store never dialed the warehouse")
}
}