feat: enable auth for local requests to Corrosion API (resolves #110)

This commit is contained in:
Pasha Sviderski
2026-05-26 10:07:12 +10:00
parent 26951773d1
commit 9424daff28
6 changed files with 138 additions and 27 deletions
+6 -1
View File
@@ -37,7 +37,12 @@ type GossipConfig struct {
}
type APIConfig struct {
Addr netip.AddrPort `toml:"addr"`
Addr netip.AddrPort `toml:"addr"`
Authz APIAuthzConfig `toml:"authz"`
}
type APIAuthzConfig struct {
BearerToken string `toml:"bearer-token"`
}
type AdminConfig struct {
+1 -1
View File
@@ -35,7 +35,7 @@ func WaitReady(ctx context.Context, dataDir string) error {
return fmt.Errorf("unmarshal config: %w", err)
}
corro, err := corrosion.NewAPIClient(config.API.Addr)
corro, err := corrosion.NewAPIClient(config.API.Addr, config.API.Authz.BearerToken)
if err != nil {
return fmt.Errorf("create corrosion API client: %w", err)
}
+22 -1
View File
@@ -35,6 +35,7 @@ import (
machinedocker "github.com/psviderski/uncloud/internal/machine/docker"
"github.com/psviderski/uncloud/internal/machine/network"
"github.com/psviderski/uncloud/internal/machine/store"
"github.com/psviderski/uncloud/internal/secret"
"github.com/psviderski/uncloud/pkg/api"
"github.com/psviderski/unregistry"
"github.com/siderolabs/grpc-proxy/proxy"
@@ -224,7 +225,21 @@ func NewMachine(config *Config) (*Machine, error) {
}
}
corro, err := corrosion.NewAPIClient(config.CorrosionAPIAddr)
// Generate and persist a token for Corrosion API if not already present in the state.
if len(state.CorrosionAPIToken) == 0 {
token, tErr := secret.New(16)
if tErr != nil {
return nil, fmt.Errorf("generate corrosion API token: %w", tErr)
}
state.CorrosionAPIToken = token
if err = state.Save(); err != nil {
return nil, fmt.Errorf("save machine state with corrosion API token: %w", err)
}
slog.Info("Generated Corrosion API bearer token.")
}
corro, err := corrosion.NewAPIClient(config.CorrosionAPIAddr, state.CorrosionAPIToken.String())
if err != nil {
return nil, fmt.Errorf("create corrosion API client: %w", err)
}
@@ -603,6 +618,9 @@ func listenUnixSocket(path string) (net.Listener, error) {
}
func (m *Machine) configureCorrosion() error {
if len(m.state.CorrosionAPIToken) == 0 {
return fmt.Errorf("corrosion API token not set in machine state")
}
if err := corroservice.MkDir(m.config.CorrosionDataDir, m.config.CorrosionUser); err != nil {
return fmt.Errorf("create corrosion data directory: %w", err)
}
@@ -639,6 +657,9 @@ func (m *Machine) configureCorrosion() error {
},
API: corroservice.APIConfig{
Addr: m.config.CorrosionAPIAddr,
Authz: corroservice.APIAuthzConfig{
BearerToken: m.state.CorrosionAPIToken.String(),
},
},
Admin: corroservice.AdminConfig{
Path: m.config.CorrosionAdminSockPath,
+3
View File
@@ -8,6 +8,7 @@ import (
"sync"
"github.com/psviderski/uncloud/internal/machine/network"
"github.com/psviderski/uncloud/internal/secret"
)
const (
@@ -28,6 +29,8 @@ type State struct {
// Per-actor vector (Corrosion actor UUID → max applied db_version) captured from an existing
// member at join time. Cleared once reached.
MinStoreVersion map[string]int64 `json:",omitempty"`
// CorrosionAPIToken authenticates requests to the local Corrosion API.
CorrosionAPIToken secret.Secret `json:",omitempty"`
// path is the file path config is read from and saved to.
path string