Skip to content
176 changes: 0 additions & 176 deletions cmd/thv/app/oauth_secret_test.go

This file was deleted.

85 changes: 2 additions & 83 deletions cmd/thv/app/run_flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"fmt"
"strings"
"time"

"github.com/spf13/cobra"

Expand All @@ -16,13 +15,12 @@ import (
"github.com/stacklok/toolhive/pkg/container/runtime"
"github.com/stacklok/toolhive/pkg/environment"
"github.com/stacklok/toolhive/pkg/ignore"
"github.com/stacklok/toolhive/pkg/logger"
"github.com/stacklok/toolhive/pkg/networking"
"github.com/stacklok/toolhive/pkg/oauth"
"github.com/stacklok/toolhive/pkg/process"
"github.com/stacklok/toolhive/pkg/registry"
"github.com/stacklok/toolhive/pkg/runner"
"github.com/stacklok/toolhive/pkg/runner/retriever"
"github.com/stacklok/toolhive/pkg/secrets"
"github.com/stacklok/toolhive/pkg/telemetry"
"github.com/stacklok/toolhive/pkg/transport"
"github.com/stacklok/toolhive/pkg/transport/types"
Expand Down Expand Up @@ -824,84 +822,5 @@ func createTelemetryConfig(otelEndpoint string, otelEnablePrometheusMetricsPath

// processOAuthClientSecret processes an OAuth client secret, converting plain text to secret reference if needed
func processOAuthClientSecret(clientSecret, workloadName string) (string, error) {
if clientSecret == "" {
return "", nil
}

// Check if it's already in CLI format (contains ",target=")
if _, err := secrets.ParseSecretParameter(clientSecret); err == nil {
// Already in CLI format, use as-is
return clientSecret, nil
}

// It's plain text, we must convert to secret reference
uniqueSecretName, err := findUniqueSecretName(workloadName)
if err != nil {
logger.Errorf("Failed to find unique secret name: %v", err)
return "", err
}

if err := storeSecretInManager(uniqueSecretName, clientSecret); err != nil {
logger.Errorf("Failed to store OAuth client secret: %v", err)
// This is a critical error - we cannot proceed without storing the secret
return "", err
}

// Return CLI format reference to the stored secret
return secrets.SecretParameter{Name: uniqueSecretName, Target: "oauth_secret"}.ToCLIString(), nil
}

// generateOAuthClientSecretName generates a base secret name for an OAuth client secret
func generateOAuthClientSecretName(workloadName string) string {
return fmt.Sprintf("OAUTH_CLIENT_SECRET_%s", workloadName)
}

// findUniqueSecretName finds a unique secret name, handling conflicts by appending timestamps
func findUniqueSecretName(workloadName string) (string, error) {
baseName := generateOAuthClientSecretName(workloadName)

// Get the secrets manager to check for existing secrets
secretManager, err := getSecretsManager()
if err != nil {
return "", fmt.Errorf("failed to get secrets manager: %w", err)
}

// Check if the base name is available
ctx := context.Background()
_, err = secretManager.GetSecret(ctx, baseName)
if err != nil {
// Secret doesn't exist, we can use the base name
return baseName, nil
}

// Secret exists, generate a unique name with timestamp
timestamp := time.Now().Unix()
uniqueName := fmt.Sprintf("%s-%d", baseName, timestamp)
return uniqueName, nil
}

// storeSecretInManager stores a secret in the configured secret manager
func storeSecretInManager(secretName, secretValue string) error {
// Use existing getSecretsManager function from secret.go
secretManager, err := getSecretsManager()
if err != nil {
return fmt.Errorf("failed to get secrets manager: %w", err)
}

// Check if the provider supports writing secrets
if !secretManager.Capabilities().CanWrite {
configProvider := cfg.NewDefaultProvider()
config := configProvider.GetConfig()
providerType, _ := config.Secrets.GetProviderType()
return fmt.Errorf("secrets provider %s does not support writing secrets (read-only)", providerType)
}

// Store the secret
ctx := context.Background()
if err := secretManager.SetSecret(ctx, secretName, secretValue); err != nil {
return fmt.Errorf("failed to store secret %s: %w", secretName, err)
}

logger.Debugf("Stored secret: %s", secretName)
return nil
return oauth.ProcessOAuthClientSecret(workloadName, clientSecret)
}
Loading
Loading