Skip to content

Commit dec109a

Browse files
committed
Apply auth configuration in backend discoverer
The CLI backend discoverer now accepts authentication configuration and applies it to discovered backends during the discovery process. This change enables per-backend authentication by: - Adding authConfig parameter to NewCLIBackendDiscoverer constructor - Implementing resolveAuthConfig() to select backend-specific or default authentication settings with proper precedence - Populating Backend.AuthStrategy and Backend.AuthMetadata fields during backend creation Authentication configuration follows this precedence: 1. Backend-specific configuration (cfg.Backends[backendID]) 2. Default configuration (cfg.Default) 3. No authentication (if neither is configured) The populated authentication fields are later consumed when converting Backend instances to BackendTarget for use by the HTTP client's authRoundTripper.
1 parent f6b287a commit dec109a

File tree

2 files changed

+53
-10
lines changed

2 files changed

+53
-10
lines changed

pkg/vmcp/aggregator/cli_discoverer.go

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"github.com/stacklok/toolhive/pkg/groups"
99
"github.com/stacklok/toolhive/pkg/logger"
1010
"github.com/stacklok/toolhive/pkg/vmcp"
11+
"github.com/stacklok/toolhive/pkg/vmcp/config"
1112
"github.com/stacklok/toolhive/pkg/workloads"
1213
)
1314

@@ -16,14 +17,23 @@ import (
1617
type cliBackendDiscoverer struct {
1718
workloadsManager workloads.Manager
1819
groupsManager groups.Manager
20+
authConfig *config.OutgoingAuthConfig
1921
}
2022

2123
// NewCLIBackendDiscoverer creates a new CLI-based backend discoverer.
2224
// It discovers workloads from Docker/Podman containers managed by ToolHive.
23-
func NewCLIBackendDiscoverer(workloadsManager workloads.Manager, groupsManager groups.Manager) BackendDiscoverer {
25+
//
26+
// The authConfig parameter configures authentication for discovered backends.
27+
// If nil, backends will have no authentication configured.
28+
func NewCLIBackendDiscoverer(
29+
workloadsManager workloads.Manager,
30+
groupsManager groups.Manager,
31+
authConfig *config.OutgoingAuthConfig,
32+
) BackendDiscoverer {
2433
return &cliBackendDiscoverer{
2534
workloadsManager: workloadsManager,
2635
groupsManager: groupsManager,
36+
authConfig: authConfig,
2737
}
2838
}
2939

@@ -92,6 +102,16 @@ func (d *cliBackendDiscoverer) Discover(ctx context.Context, groupRef string) ([
92102
Metadata: make(map[string]string),
93103
}
94104

105+
// Apply authentication configuration if provided
106+
if d.authConfig != nil {
107+
authStrategy, authMetadata := d.resolveAuthConfig(name)
108+
backend.AuthStrategy = authStrategy
109+
backend.AuthMetadata = authMetadata
110+
if authStrategy != "" {
111+
logger.Debugf("Backend %s configured with auth strategy: %s", name, authStrategy)
112+
}
113+
}
114+
95115
// Copy user labels to metadata first
96116
for k, v := range workload.Labels {
97117
backend.Metadata[k] = v
@@ -116,6 +136,29 @@ func (d *cliBackendDiscoverer) Discover(ctx context.Context, groupRef string) ([
116136
return backends, nil
117137
}
118138

139+
// resolveAuthConfig determines the authentication strategy and metadata for a backend.
140+
// It checks for backend-specific configuration first, then falls back to default.
141+
func (d *cliBackendDiscoverer) resolveAuthConfig(backendID string) (string, map[string]any) {
142+
if d.authConfig == nil {
143+
return "", nil
144+
}
145+
146+
// Check for backend-specific configuration
147+
if strategy, exists := d.authConfig.Backends[backendID]; exists && strategy != nil {
148+
logger.Debugf("Using backend-specific auth strategy for %s: %s", backendID, strategy.Type)
149+
return strategy.Type, strategy.Metadata
150+
}
151+
152+
// Fall back to default configuration
153+
if d.authConfig.Default != nil {
154+
logger.Debugf("Using default auth strategy for %s: %s", backendID, d.authConfig.Default.Type)
155+
return d.authConfig.Default.Type, d.authConfig.Default.Metadata
156+
}
157+
158+
// No authentication configured
159+
return "", nil
160+
}
161+
119162
// mapWorkloadStatusToHealth converts a workload status to a backend health status.
120163
func mapWorkloadStatusToHealth(status rt.WorkloadStatus) vmcp.BackendHealthStatus {
121164
switch status {

pkg/vmcp/aggregator/cli_discoverer_test.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ func TestCLIBackendDiscoverer_Discover(t *testing.T) {
4545
mockWorkloads.EXPECT().GetWorkload(gomock.Any(), "workload1").Return(workload1, nil)
4646
mockWorkloads.EXPECT().GetWorkload(gomock.Any(), "workload2").Return(workload2, nil)
4747

48-
discoverer := NewCLIBackendDiscoverer(mockWorkloads, mockGroups)
48+
discoverer := NewCLIBackendDiscoverer(mockWorkloads, mockGroups, nil)
4949
backends, err := discoverer.Discover(context.Background(), testGroupName)
5050

5151
require.NoError(t, err)
@@ -79,7 +79,7 @@ func TestCLIBackendDiscoverer_Discover(t *testing.T) {
7979
mockWorkloads.EXPECT().GetWorkload(gomock.Any(), "running-workload").Return(runningWorkload, nil)
8080
mockWorkloads.EXPECT().GetWorkload(gomock.Any(), "stopped-workload").Return(stoppedWorkload, nil)
8181

82-
discoverer := NewCLIBackendDiscoverer(mockWorkloads, mockGroups)
82+
discoverer := NewCLIBackendDiscoverer(mockWorkloads, mockGroups, nil)
8383
backends, err := discoverer.Discover(context.Background(), testGroupName)
8484

8585
require.NoError(t, err)
@@ -108,7 +108,7 @@ func TestCLIBackendDiscoverer_Discover(t *testing.T) {
108108
mockWorkloads.EXPECT().GetWorkload(gomock.Any(), "workload1").Return(workloadWithURL, nil)
109109
mockWorkloads.EXPECT().GetWorkload(gomock.Any(), "workload2").Return(workloadWithoutURL, nil)
110110

111-
discoverer := NewCLIBackendDiscoverer(mockWorkloads, mockGroups)
111+
discoverer := NewCLIBackendDiscoverer(mockWorkloads, mockGroups, nil)
112112
backends, err := discoverer.Discover(context.Background(), testGroupName)
113113

114114
require.NoError(t, err)
@@ -133,7 +133,7 @@ func TestCLIBackendDiscoverer_Discover(t *testing.T) {
133133
mockWorkloads.EXPECT().GetWorkload(gomock.Any(), "workload1").Return(workload1, nil)
134134
mockWorkloads.EXPECT().GetWorkload(gomock.Any(), "workload2").Return(workload2, nil)
135135

136-
discoverer := NewCLIBackendDiscoverer(mockWorkloads, mockGroups)
136+
discoverer := NewCLIBackendDiscoverer(mockWorkloads, mockGroups, nil)
137137
backends, err := discoverer.Discover(context.Background(), testGroupName)
138138

139139
require.NoError(t, err)
@@ -150,7 +150,7 @@ func TestCLIBackendDiscoverer_Discover(t *testing.T) {
150150

151151
mockGroups.EXPECT().Exists(gomock.Any(), "nonexistent-group").Return(false, nil)
152152

153-
discoverer := NewCLIBackendDiscoverer(mockWorkloads, mockGroups)
153+
discoverer := NewCLIBackendDiscoverer(mockWorkloads, mockGroups, nil)
154154
backends, err := discoverer.Discover(context.Background(), "nonexistent-group")
155155

156156
require.Error(t, err)
@@ -168,7 +168,7 @@ func TestCLIBackendDiscoverer_Discover(t *testing.T) {
168168

169169
mockGroups.EXPECT().Exists(gomock.Any(), testGroupName).Return(false, errors.New("database error"))
170170

171-
discoverer := NewCLIBackendDiscoverer(mockWorkloads, mockGroups)
171+
discoverer := NewCLIBackendDiscoverer(mockWorkloads, mockGroups, nil)
172172
backends, err := discoverer.Discover(context.Background(), testGroupName)
173173

174174
require.Error(t, err)
@@ -187,7 +187,7 @@ func TestCLIBackendDiscoverer_Discover(t *testing.T) {
187187
mockGroups.EXPECT().Exists(gomock.Any(), "empty-group").Return(true, nil)
188188
mockWorkloads.EXPECT().ListWorkloadsInGroup(gomock.Any(), "empty-group").Return([]string{}, nil)
189189

190-
discoverer := NewCLIBackendDiscoverer(mockWorkloads, mockGroups)
190+
discoverer := NewCLIBackendDiscoverer(mockWorkloads, mockGroups, nil)
191191
backends, err := discoverer.Discover(context.Background(), "empty-group")
192192

193193
require.NoError(t, err)
@@ -214,7 +214,7 @@ func TestCLIBackendDiscoverer_Discover(t *testing.T) {
214214
mockWorkloads.EXPECT().GetWorkload(gomock.Any(), "stopped1").Return(stoppedWorkload, nil)
215215
mockWorkloads.EXPECT().GetWorkload(gomock.Any(), "error1").Return(errorWorkload, nil)
216216

217-
discoverer := NewCLIBackendDiscoverer(mockWorkloads, mockGroups)
217+
discoverer := NewCLIBackendDiscoverer(mockWorkloads, mockGroups, nil)
218218
backends, err := discoverer.Discover(context.Background(), testGroupName)
219219

220220
require.NoError(t, err)
@@ -240,7 +240,7 @@ func TestCLIBackendDiscoverer_Discover(t *testing.T) {
240240
mockWorkloads.EXPECT().GetWorkload(gomock.Any(), "failing-workload").
241241
Return(core.Workload{}, errors.New("workload query failed"))
242242

243-
discoverer := NewCLIBackendDiscoverer(mockWorkloads, mockGroups)
243+
discoverer := NewCLIBackendDiscoverer(mockWorkloads, mockGroups, nil)
244244
backends, err := discoverer.Discover(context.Background(), testGroupName)
245245

246246
require.NoError(t, err)

0 commit comments

Comments
 (0)