Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions go/apps/ctrl/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,6 @@ func Run(ctx context.Context, cfg Config) error {
return fmt.Errorf("unable to create vault service: %w", err)
}
}
// make go happy
_ = vaultSvc

// Initialize database
database, err := db.New(db.Config{
Expand Down Expand Up @@ -237,6 +235,7 @@ func Run(ctx context.Context, cfg Config) error {
Krane: kraneDeploymentClient,
BuildClient: buildService,
DefaultDomain: cfg.DefaultDomain,
Vault: vaultSvc,
})))

restateSrv.Bind(hydrav1.NewRoutingServiceServer(routing.New(routing.Config{
Expand Down
22 changes: 22 additions & 0 deletions go/apps/ctrl/services/deployment/create_deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
hydrav1 "github.com/unkeyed/unkey/go/gen/proto/hydra/v1"
"github.com/unkeyed/unkey/go/pkg/db"
"github.com/unkeyed/unkey/go/pkg/uid"
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/proto"
)

Expand Down Expand Up @@ -52,6 +53,26 @@ func (s *Service) CreateDeployment(
fmt.Errorf("failed to lookup environment: %w", err))
}

// Fetch environment variables and build secrets blob
envVars, err := db.Query.FindEnvironmentVariablesByEnvironmentId(ctx, s.db.RO(), env.ID)
if err != nil {
return nil, connect.NewError(connect.CodeInternal,
fmt.Errorf("failed to fetch environment variables: %w", err))
}

secretsConfig := &ctrlv1.SecretsConfig{
Secrets: make(map[string]string, len(envVars)),
}
for _, ev := range envVars {
secretsConfig.Secrets[ev.Key] = ev.Value
}

secretsBlob, err := protojson.Marshal(secretsConfig)
if err != nil {
return nil, connect.NewError(connect.CodeInternal,
fmt.Errorf("failed to marshal secrets config: %w", err))
}

// Get git branch name for the deployment
gitBranch := req.Msg.GetBranch()
if gitBranch == "" {
Expand Down Expand Up @@ -143,6 +164,7 @@ func (s *Service) CreateDeployment(
}`),
OpenapiSpec: sql.NullString{String: "", Valid: false},
GatewayConfig: env.GatewayConfig,
SecretsConfig: secretsBlob,
Status: db.DeploymentsStatusPending,
CreatedAt: now,
UpdatedAt: sql.NullInt64{Int64: now, Valid: true},
Expand Down
26 changes: 26 additions & 0 deletions go/apps/ctrl/workflows/deploy/deploy_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ import (
ctrlv1 "github.com/unkeyed/unkey/go/gen/proto/ctrl/v1"
hydrav1 "github.com/unkeyed/unkey/go/gen/proto/hydra/v1"
kranev1 "github.com/unkeyed/unkey/go/gen/proto/krane/v1"
vaultv1 "github.com/unkeyed/unkey/go/gen/proto/vault/v1"
"github.com/unkeyed/unkey/go/pkg/db"
"github.com/unkeyed/unkey/go/pkg/uid"
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/proto"
)

Expand Down Expand Up @@ -112,6 +114,29 @@ func (w *Workflow) Deploy(ctx restate.ObjectContext, req *hydrav1.DeployRequest)
return nil, err
}

// Unmarshal secrets config to get environment variables
var secretsConfig ctrlv1.SecretsConfig
if len(deployment.SecretsConfig) > 0 {
if err = protojson.Unmarshal(deployment.SecretsConfig, &secretsConfig); err != nil {
return nil, fmt.Errorf("failed to unmarshal secrets config: %w", err)
}
}

// Decrypt environment variables using the workspace's keyring
decryptedEnvVars := make(map[string]string, len(secretsConfig.GetSecrets()))
if w.vault != nil {
for key, encryptedValue := range secretsConfig.GetSecrets() {
decrypted, decryptErr := w.vault.Decrypt(ctx, &vaultv1.DecryptRequest{
Keyring: deployment.WorkspaceID,
Encrypted: encryptedValue,
})
if decryptErr != nil {
return nil, fmt.Errorf("failed to decrypt env var %s: %w", key, decryptErr)
}
decryptedEnvVars[key] = decrypted.GetPlaintext()
}
}

_, err = restate.Run(ctx, func(stepCtx restate.RunContext) (restate.Void, error) {
// Create deployment request

Expand All @@ -123,6 +148,7 @@ func (w *Workflow) Deploy(ctx restate.ObjectContext, req *hydrav1.DeployRequest)
Replicas: 1,
CpuMillicores: 512,
MemorySizeMib: 512,
EnvVars: decryptedEnvVars,
},
}))
if err != nil {
Expand Down
6 changes: 6 additions & 0 deletions go/apps/ctrl/workflows/deploy/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"github.com/unkeyed/unkey/go/gen/proto/krane/v1/kranev1connect"
"github.com/unkeyed/unkey/go/pkg/db"
"github.com/unkeyed/unkey/go/pkg/otel/logging"
"github.com/unkeyed/unkey/go/pkg/vault"
)

const hardcodedNamespace = "unkey"
Expand All @@ -27,6 +28,7 @@ type Workflow struct {
krane kranev1connect.DeploymentServiceClient
buildClient ctrlv1connect.BuildServiceClient
defaultDomain string
vault *vault.Service
}

var _ hydrav1.DeploymentServiceServer = (*Workflow)(nil)
Expand All @@ -47,6 +49,9 @@ type Config struct {

// DefaultDomain is the apex domain for generated deployment URLs (e.g., "unkey.app").
DefaultDomain string

// Vault provides encryption/decryption services for secrets.
Vault *vault.Service
}

// New creates a new deployment workflow instance.
Expand All @@ -58,5 +63,6 @@ func New(cfg Config) *Workflow {
krane: cfg.Krane,
buildClient: cfg.BuildClient,
defaultDomain: cfg.DefaultDomain,
vault: cfg.Vault,
}
}
Loading