diff --git a/apps/dashboard/gen/proto/krane/v1/deployment_pb.ts b/apps/dashboard/gen/proto/krane/v1/deployment_pb.ts index 576bb40a60..f921f410d3 100644 --- a/apps/dashboard/gen/proto/krane/v1/deployment_pb.ts +++ b/apps/dashboard/gen/proto/krane/v1/deployment_pb.ts @@ -10,7 +10,7 @@ import type { Message } from "@bufbuild/protobuf"; * Describes the file krane/v1/deployment.proto. */ export const file_krane_v1_deployment: GenFile = /*@__PURE__*/ - fileDesc("ChlrcmFuZS92MS9kZXBsb3ltZW50LnByb3RvEghrcmFuZS52MSKPAQoRRGVwbG95bWVudFJlcXVlc3QSEQoJbmFtZXNwYWNlGAEgASgJEhUKDWRlcGxveW1lbnRfaWQYAiABKAkSDQoFaW1hZ2UYAyABKAkSEAoIcmVwbGljYXMYBCABKA0SFgoOY3B1X21pbGxpY29yZXMYBSABKA0SFwoPbWVtb3J5X3NpemVfbWliGAYgASgEIkoKF0NyZWF0ZURlcGxveW1lbnRSZXF1ZXN0Ei8KCmRlcGxveW1lbnQYASABKAsyGy5rcmFuZS52MS5EZXBsb3ltZW50UmVxdWVzdCJGChhDcmVhdGVEZXBsb3ltZW50UmVzcG9uc2USKgoGc3RhdHVzGAEgASgOMhoua3JhbmUudjEuRGVwbG95bWVudFN0YXR1cyJKChdVcGRhdGVEZXBsb3ltZW50UmVxdWVzdBIvCgpkZXBsb3ltZW50GAEgASgLMhsua3JhbmUudjEuRGVwbG95bWVudFJlcXVlc3QiKwoYVXBkYXRlRGVwbG95bWVudFJlc3BvbnNlEg8KB3BvZF9pZHMYASADKAkiQwoXRGVsZXRlRGVwbG95bWVudFJlcXVlc3QSEQoJbmFtZXNwYWNlGAEgASgJEhUKDWRlcGxveW1lbnRfaWQYAiABKAkiGgoYRGVsZXRlRGVwbG95bWVudFJlc3BvbnNlIkAKFEdldERlcGxveW1lbnRSZXF1ZXN0EhEKCW5hbWVzcGFjZRgBIAEoCRIVCg1kZXBsb3ltZW50X2lkGAIgASgJIj4KFUdldERlcGxveW1lbnRSZXNwb25zZRIlCglpbnN0YW5jZXMYAiADKAsyEi5rcmFuZS52MS5JbnN0YW5jZSJTCghJbnN0YW5jZRIKCgJpZBgBIAEoCRIPCgdhZGRyZXNzGAIgASgJEioKBnN0YXR1cxgDIAEoDjIaLmtyYW5lLnYxLkRlcGxveW1lbnRTdGF0dXMqlgEKEERlcGxveW1lbnRTdGF0dXMSIQodREVQTE9ZTUVOVF9TVEFUVVNfVU5TUEVDSUZJRUQQABIdChlERVBMT1lNRU5UX1NUQVRVU19QRU5ESU5HEAESHQoZREVQTE9ZTUVOVF9TVEFUVVNfUlVOTklORxACEiEKHURFUExPWU1FTlRfU1RBVFVTX1RFUk1JTkFUSU5HEAMymwIKEURlcGxveW1lbnRTZXJ2aWNlElkKEENyZWF0ZURlcGxveW1lbnQSIS5rcmFuZS52MS5DcmVhdGVEZXBsb3ltZW50UmVxdWVzdBoiLmtyYW5lLnYxLkNyZWF0ZURlcGxveW1lbnRSZXNwb25zZRJQCg1HZXREZXBsb3ltZW50Eh4ua3JhbmUudjEuR2V0RGVwbG95bWVudFJlcXVlc3QaHy5rcmFuZS52MS5HZXREZXBsb3ltZW50UmVzcG9uc2USWQoQRGVsZXRlRGVwbG95bWVudBIhLmtyYW5lLnYxLkRlbGV0ZURlcGxveW1lbnRSZXF1ZXN0GiIua3JhbmUudjEuRGVsZXRlRGVwbG95bWVudFJlc3BvbnNlQpgBCgxjb20ua3JhbmUudjFCD0RlcGxveW1lbnRQcm90b1ABWjZnaXRodWIuY29tL3Vua2V5ZWQvdW5rZXkvZ28vZ2VuL3Byb3RvL2tyYW5lL3YxO2tyYW5ldjGiAgNLWFiqAghLcmFuZS5WMcoCCEtyYW5lXFYx4gIUS3JhbmVcVjFcR1BCTWV0YWRhdGHqAglLcmFuZTo6VjFiBnByb3RvMw"); + fileDesc("ChlrcmFuZS92MS9kZXBsb3ltZW50LnByb3RvEghrcmFuZS52MSL7AQoRRGVwbG95bWVudFJlcXVlc3QSEQoJbmFtZXNwYWNlGAEgASgJEhUKDWRlcGxveW1lbnRfaWQYAiABKAkSDQoFaW1hZ2UYAyABKAkSEAoIcmVwbGljYXMYBCABKA0SFgoOY3B1X21pbGxpY29yZXMYBSABKA0SFwoPbWVtb3J5X3NpemVfbWliGAYgASgEEjoKCGVudl92YXJzGAcgAygLMigua3JhbmUudjEuRGVwbG95bWVudFJlcXVlc3QuRW52VmFyc0VudHJ5Gi4KDEVudlZhcnNFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAk6AjgBIkoKF0NyZWF0ZURlcGxveW1lbnRSZXF1ZXN0Ei8KCmRlcGxveW1lbnQYASABKAsyGy5rcmFuZS52MS5EZXBsb3ltZW50UmVxdWVzdCJGChhDcmVhdGVEZXBsb3ltZW50UmVzcG9uc2USKgoGc3RhdHVzGAEgASgOMhoua3JhbmUudjEuRGVwbG95bWVudFN0YXR1cyJKChdVcGRhdGVEZXBsb3ltZW50UmVxdWVzdBIvCgpkZXBsb3ltZW50GAEgASgLMhsua3JhbmUudjEuRGVwbG95bWVudFJlcXVlc3QiKwoYVXBkYXRlRGVwbG95bWVudFJlc3BvbnNlEg8KB3BvZF9pZHMYASADKAkiQwoXRGVsZXRlRGVwbG95bWVudFJlcXVlc3QSEQoJbmFtZXNwYWNlGAEgASgJEhUKDWRlcGxveW1lbnRfaWQYAiABKAkiGgoYRGVsZXRlRGVwbG95bWVudFJlc3BvbnNlIkAKFEdldERlcGxveW1lbnRSZXF1ZXN0EhEKCW5hbWVzcGFjZRgBIAEoCRIVCg1kZXBsb3ltZW50X2lkGAIgASgJIj4KFUdldERlcGxveW1lbnRSZXNwb25zZRIlCglpbnN0YW5jZXMYAiADKAsyEi5rcmFuZS52MS5JbnN0YW5jZSJTCghJbnN0YW5jZRIKCgJpZBgBIAEoCRIPCgdhZGRyZXNzGAIgASgJEioKBnN0YXR1cxgDIAEoDjIaLmtyYW5lLnYxLkRlcGxveW1lbnRTdGF0dXMqlgEKEERlcGxveW1lbnRTdGF0dXMSIQodREVQTE9ZTUVOVF9TVEFUVVNfVU5TUEVDSUZJRUQQABIdChlERVBMT1lNRU5UX1NUQVRVU19QRU5ESU5HEAESHQoZREVQTE9ZTUVOVF9TVEFUVVNfUlVOTklORxACEiEKHURFUExPWU1FTlRfU1RBVFVTX1RFUk1JTkFUSU5HEAMymwIKEURlcGxveW1lbnRTZXJ2aWNlElkKEENyZWF0ZURlcGxveW1lbnQSIS5rcmFuZS52MS5DcmVhdGVEZXBsb3ltZW50UmVxdWVzdBoiLmtyYW5lLnYxLkNyZWF0ZURlcGxveW1lbnRSZXNwb25zZRJQCg1HZXREZXBsb3ltZW50Eh4ua3JhbmUudjEuR2V0RGVwbG95bWVudFJlcXVlc3QaHy5rcmFuZS52MS5HZXREZXBsb3ltZW50UmVzcG9uc2USWQoQRGVsZXRlRGVwbG95bWVudBIhLmtyYW5lLnYxLkRlbGV0ZURlcGxveW1lbnRSZXF1ZXN0GiIua3JhbmUudjEuRGVsZXRlRGVwbG95bWVudFJlc3BvbnNlQpgBCgxjb20ua3JhbmUudjFCD0RlcGxveW1lbnRQcm90b1ABWjZnaXRodWIuY29tL3Vua2V5ZWQvdW5rZXkvZ28vZ2VuL3Byb3RvL2tyYW5lL3YxO2tyYW5ldjGiAgNLWFiqAghLcmFuZS5WMcoCCEtyYW5lXFYx4gIUS3JhbmVcVjFcR1BCTWV0YWRhdGHqAglLcmFuZTo6VjFiBnByb3RvMw"); /** * @generated from message krane.v1.DeploymentRequest @@ -45,6 +45,14 @@ export type DeploymentRequest = Message<"krane.v1.DeploymentRequest"> & { * @generated from field: uint64 memory_size_mib = 6; */ memorySizeMib: bigint; + + /** + * Environment variables to inject into the container. + * Keys are variable names, values are the (decrypted) values. + * + * @generated from field: map env_vars = 7; + */ + envVars: { [key: string]: string }; }; /** diff --git a/go/apps/krane/backend/docker/deployment_create.go b/go/apps/krane/backend/docker/deployment_create.go index 4bc1ba9a9e..e75bb9f611 100644 --- a/go/apps/krane/backend/docker/deployment_create.go +++ b/go/apps/krane/backend/docker/deployment_create.go @@ -47,6 +47,14 @@ func (d *docker) CreateDeployment(ctx context.Context, req *connect.Request[kran cpuNanos := int64(deployment.GetCpuMillicores()) * 1_000_000 // Convert millicores to nanoseconds memoryBytes := int64(deployment.GetMemorySizeMib()) * 1024 * 1024 //nolint:gosec // Intentional conversion + // Build environment variables list + env := []string{ + fmt.Sprintf("DEPLOYMENT_ID=%s", deployment.GetDeploymentId()), + } + for k, v := range deployment.GetEnvVars() { + env = append(env, fmt.Sprintf("%s=%s", k, v)) + } + //nolint:exhaustruct // Docker SDK types have many optional fields containerConfig := &container.Config{ Image: deployment.GetImage(), @@ -55,9 +63,7 @@ func (d *docker) CreateDeployment(ctx context.Context, req *connect.Request[kran "unkey.managed.by": "krane", }, ExposedPorts: exposedPorts, - Env: []string{ - fmt.Sprintf("DEPLOYMENT_ID=%s", deployment.GetDeploymentId()), - }, + Env: env, } //nolint:exhaustruct // Docker SDK types have many optional fields diff --git a/go/apps/krane/backend/kubernetes/deployment_create.go b/go/apps/krane/backend/kubernetes/deployment_create.go index 5b1421485a..a35ba29f6d 100644 --- a/go/apps/krane/backend/kubernetes/deployment_create.go +++ b/go/apps/krane/backend/kubernetes/deployment_create.go @@ -156,6 +156,9 @@ func (k *k8s) CreateDeployment(ctx context.Context, req *connect.Request[kranev1 Annotations: map[string]string{}, }, Spec: corev1.PodSpec{ + // Use a restricted service account with no API access + ServiceAccountName: "customer-workload", + AutomountServiceAccountToken: ptr.P(false), ImagePullSecrets: func() []corev1.LocalObjectReference { // Only add imagePullSecrets if using Depot registry @@ -179,6 +182,20 @@ func (k *k8s) CreateDeployment(ctx context.Context, req *connect.Request[kranev1 Protocol: corev1.ProtocolTCP, }, }, + Env: func() []corev1.EnvVar { + envVars := req.Msg.GetDeployment().GetEnvVars() + if len(envVars) == 0 { + return nil + } + env := make([]corev1.EnvVar, 0, len(envVars)) + for k, v := range envVars { + env = append(env, corev1.EnvVar{ + Name: k, + Value: v, + }) + } + return env + }(), Resources: corev1.ResourceRequirements{ // nolint: exhaustive Requests: corev1.ResourceList{ diff --git a/go/gen/proto/krane/v1/deployment.pb.go b/go/gen/proto/krane/v1/deployment.pb.go index b50ddc814d..75463ddfe8 100644 --- a/go/gen/proto/krane/v1/deployment.pb.go +++ b/go/gen/proto/krane/v1/deployment.pb.go @@ -81,6 +81,9 @@ type DeploymentRequest struct { Replicas uint32 `protobuf:"varint,4,opt,name=replicas,proto3" json:"replicas,omitempty"` CpuMillicores uint32 `protobuf:"varint,5,opt,name=cpu_millicores,json=cpuMillicores,proto3" json:"cpu_millicores,omitempty"` MemorySizeMib uint64 `protobuf:"varint,6,opt,name=memory_size_mib,json=memorySizeMib,proto3" json:"memory_size_mib,omitempty"` + // Environment variables to inject into the container. + // Keys are variable names, values are the (decrypted) values. + EnvVars map[string]string `protobuf:"bytes,7,rep,name=env_vars,json=envVars,proto3" json:"env_vars,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -157,6 +160,13 @@ func (x *DeploymentRequest) GetMemorySizeMib() uint64 { return 0 } +func (x *DeploymentRequest) GetEnvVars() map[string]string { + if x != nil { + return x.EnvVars + } + return nil +} + type CreateDeploymentRequest struct { state protoimpl.MessageState `protogen:"open.v1"` Deployment *DeploymentRequest `protobuf:"bytes,1,opt,name=deployment,proto3" json:"deployment,omitempty"` @@ -581,14 +591,18 @@ var File_krane_v1_deployment_proto protoreflect.FileDescriptor const file_krane_v1_deployment_proto_rawDesc = "" + "\n" + - "\x19krane/v1/deployment.proto\x12\bkrane.v1\"\xd7\x01\n" + + "\x19krane/v1/deployment.proto\x12\bkrane.v1\"\xd8\x02\n" + "\x11DeploymentRequest\x12\x1c\n" + "\tnamespace\x18\x01 \x01(\tR\tnamespace\x12#\n" + "\rdeployment_id\x18\x02 \x01(\tR\fdeploymentId\x12\x14\n" + "\x05image\x18\x03 \x01(\tR\x05image\x12\x1a\n" + "\breplicas\x18\x04 \x01(\rR\breplicas\x12%\n" + "\x0ecpu_millicores\x18\x05 \x01(\rR\rcpuMillicores\x12&\n" + - "\x0fmemory_size_mib\x18\x06 \x01(\x04R\rmemorySizeMib\"V\n" + + "\x0fmemory_size_mib\x18\x06 \x01(\x04R\rmemorySizeMib\x12C\n" + + "\benv_vars\x18\a \x03(\v2(.krane.v1.DeploymentRequest.EnvVarsEntryR\aenvVars\x1a:\n" + + "\fEnvVarsEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"V\n" + "\x17CreateDeploymentRequest\x12;\n" + "\n" + "deployment\x18\x01 \x01(\v2\x1b.krane.v1.DeploymentRequestR\n" + @@ -638,7 +652,7 @@ func file_krane_v1_deployment_proto_rawDescGZIP() []byte { } var file_krane_v1_deployment_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_krane_v1_deployment_proto_msgTypes = make([]protoimpl.MessageInfo, 10) +var file_krane_v1_deployment_proto_msgTypes = make([]protoimpl.MessageInfo, 11) var file_krane_v1_deployment_proto_goTypes = []any{ (DeploymentStatus)(0), // 0: krane.v1.DeploymentStatus (*DeploymentRequest)(nil), // 1: krane.v1.DeploymentRequest @@ -651,24 +665,26 @@ var file_krane_v1_deployment_proto_goTypes = []any{ (*GetDeploymentRequest)(nil), // 8: krane.v1.GetDeploymentRequest (*GetDeploymentResponse)(nil), // 9: krane.v1.GetDeploymentResponse (*Instance)(nil), // 10: krane.v1.Instance + nil, // 11: krane.v1.DeploymentRequest.EnvVarsEntry } var file_krane_v1_deployment_proto_depIdxs = []int32{ - 1, // 0: krane.v1.CreateDeploymentRequest.deployment:type_name -> krane.v1.DeploymentRequest - 0, // 1: krane.v1.CreateDeploymentResponse.status:type_name -> krane.v1.DeploymentStatus - 1, // 2: krane.v1.UpdateDeploymentRequest.deployment:type_name -> krane.v1.DeploymentRequest - 10, // 3: krane.v1.GetDeploymentResponse.instances:type_name -> krane.v1.Instance - 0, // 4: krane.v1.Instance.status:type_name -> krane.v1.DeploymentStatus - 2, // 5: krane.v1.DeploymentService.CreateDeployment:input_type -> krane.v1.CreateDeploymentRequest - 8, // 6: krane.v1.DeploymentService.GetDeployment:input_type -> krane.v1.GetDeploymentRequest - 6, // 7: krane.v1.DeploymentService.DeleteDeployment:input_type -> krane.v1.DeleteDeploymentRequest - 3, // 8: krane.v1.DeploymentService.CreateDeployment:output_type -> krane.v1.CreateDeploymentResponse - 9, // 9: krane.v1.DeploymentService.GetDeployment:output_type -> krane.v1.GetDeploymentResponse - 7, // 10: krane.v1.DeploymentService.DeleteDeployment:output_type -> krane.v1.DeleteDeploymentResponse - 8, // [8:11] is the sub-list for method output_type - 5, // [5:8] is the sub-list for method input_type - 5, // [5:5] is the sub-list for extension type_name - 5, // [5:5] is the sub-list for extension extendee - 0, // [0:5] is the sub-list for field type_name + 11, // 0: krane.v1.DeploymentRequest.env_vars:type_name -> krane.v1.DeploymentRequest.EnvVarsEntry + 1, // 1: krane.v1.CreateDeploymentRequest.deployment:type_name -> krane.v1.DeploymentRequest + 0, // 2: krane.v1.CreateDeploymentResponse.status:type_name -> krane.v1.DeploymentStatus + 1, // 3: krane.v1.UpdateDeploymentRequest.deployment:type_name -> krane.v1.DeploymentRequest + 10, // 4: krane.v1.GetDeploymentResponse.instances:type_name -> krane.v1.Instance + 0, // 5: krane.v1.Instance.status:type_name -> krane.v1.DeploymentStatus + 2, // 6: krane.v1.DeploymentService.CreateDeployment:input_type -> krane.v1.CreateDeploymentRequest + 8, // 7: krane.v1.DeploymentService.GetDeployment:input_type -> krane.v1.GetDeploymentRequest + 6, // 8: krane.v1.DeploymentService.DeleteDeployment:input_type -> krane.v1.DeleteDeploymentRequest + 3, // 9: krane.v1.DeploymentService.CreateDeployment:output_type -> krane.v1.CreateDeploymentResponse + 9, // 10: krane.v1.DeploymentService.GetDeployment:output_type -> krane.v1.GetDeploymentResponse + 7, // 11: krane.v1.DeploymentService.DeleteDeployment:output_type -> krane.v1.DeleteDeploymentResponse + 9, // [9:12] is the sub-list for method output_type + 6, // [6:9] is the sub-list for method input_type + 6, // [6:6] is the sub-list for extension type_name + 6, // [6:6] is the sub-list for extension extendee + 0, // [0:6] is the sub-list for field type_name } func init() { file_krane_v1_deployment_proto_init() } @@ -682,7 +698,7 @@ func file_krane_v1_deployment_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_krane_v1_deployment_proto_rawDesc), len(file_krane_v1_deployment_proto_rawDesc)), NumEnums: 1, - NumMessages: 10, + NumMessages: 11, NumExtensions: 0, NumServices: 1, }, diff --git a/go/proto/krane/v1/deployment.proto b/go/proto/krane/v1/deployment.proto index 88302b7b42..96b3fca2ff 100644 --- a/go/proto/krane/v1/deployment.proto +++ b/go/proto/krane/v1/deployment.proto @@ -24,6 +24,10 @@ message DeploymentRequest { uint32 replicas = 4; uint32 cpu_millicores = 5; uint64 memory_size_mib = 6; + + // Environment variables to inject into the container. + // Keys are variable names, values are the (decrypted) values. + map env_vars = 7; } message CreateDeploymentRequest {