~bigbes/sr-ht-dolt

ref: b4fd2233c89ca5c415284b61b83d41eb3d4982c1 sr-ht-dolt/remoteapi/keystore.go -rw-r--r-- 2.3 KiB
b4fd2233 — Eugene Blikh log: take the logrus bridge from auxilia 9 days ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
// Package remoteapi assembles dolt.sr.ht's remotesapi subsystem: the gRPC
// authentication/authorization interceptors, the importable remotesrv server
// that serves the bare NBS chunk stores, and the small separate
// CredentialsService (WhoAmI) server that backs `dolt login`.
//
// The two gRPC surfaces run on two ports (nginx path-routes between them):
//
//   - the remotesapi ChunkStoreService (clone/push data plane) on ListenAddr,
//     wrapped by our per-repo authz interceptors (see interceptors.go);
//   - the CredentialsService.WhoAmI RPC on CredsListenAddr (see credsvc.go),
//     which lets the dolt CLI discover which SourceHut user a keypair maps to
//     while it polls for the key to be associated through the web UI.
package remoteapi

import (
	"context"
	"database/sql"

	"sourcecraft.dev/bigbes/sr-ht-dolt/authn"
	"sourcecraft.dev/bigbes/sr-ht-dolt/db"
)

// keyStore adapts the SQL persistence layer (db.Store over the shared *sql.DB
// pool) to the authn.KeyStore interface the Bearer-JWT resolver consumes. It
// wraps the pool rather than a context-bound Store so it can be constructed once
// at startup and shared by both the interceptor path and the credentials
// service; each call binds a fresh db.Store to the pool (which manages
// connection lifetime) and threads ctx for cancellation.
type keyStore struct {
	db *sql.DB
}

var _ authn.KeyStore = (*keyStore)(nil)

// newKeyStore builds a keyStore over the shared database pool. pool must be
// non-nil.
func newKeyStore(pool *sql.DB) *keyStore {
	if pool == nil {
		panic("remoteapi: newKeyStore requires a non-nil *sql.DB")
	}
	return &keyStore{db: pool}
}

// ByKID resolves a dolt key id to the owner's raw Ed25519 public key and
// username, mapping the db layer's KeyAuth onto authn.KeyStore's contract. A
// missing key surfaces as db.ErrNotFound (returned unchanged), which the JWT
// resolver wraps into an invalid-token rejection.
func (k *keyStore) ByKID(ctx context.Context, kid string) (pubkey []byte, username string, err error) {
	ka, err := db.NewStore(k.db).KeyByKID(ctx, kid)
	if err != nil {
		return nil, "", err
	}
	return ka.PubKey, ka.Username, nil
}

// TouchLastUsed stamps the key's last_used column after a successful keypair
// authentication.
func (k *keyStore) TouchLastUsed(ctx context.Context, kid string) error {
	return db.NewStore(k.db).TouchKeyLastUsed(ctx, kid)
}