diff --git a/api/gen/proto/go/teleport/workloadidentity/v1/attrs.pb.go b/api/gen/proto/go/teleport/workloadidentity/v1/attrs.pb.go index b21cf026a023c..b54cd9792d956 100644 --- a/api/gen/proto/go/teleport/workloadidentity/v1/attrs.pb.go +++ b/api/gen/proto/go/teleport/workloadidentity/v1/attrs.pb.go @@ -210,7 +210,11 @@ type WorkloadAttrsUnix struct { // The primary user ID of the workload process. Gid uint32 `protobuf:"varint,3,opt,name=gid,proto3" json:"gid,omitempty"` // The primary group ID of the workload process. - Uid uint32 `protobuf:"varint,4,opt,name=uid,proto3" json:"uid,omitempty"` + Uid uint32 `protobuf:"varint,4,opt,name=uid,proto3" json:"uid,omitempty"` + // The path to the workload process binary. + BinaryPath *string `protobuf:"bytes,5,opt,name=binary_path,json=binaryPath,proto3,oneof" json:"binary_path,omitempty"` + // The hex-encoded SHA256 hash of the workload process binary. + BinaryHash *string `protobuf:"bytes,6,opt,name=binary_hash,json=binaryHash,proto3,oneof" json:"binary_hash,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -273,6 +277,20 @@ func (x *WorkloadAttrsUnix) GetUid() uint32 { return 0 } +func (x *WorkloadAttrsUnix) GetBinaryPath() string { + if x != nil && x.BinaryPath != nil { + return *x.BinaryPath + } + return "" +} + +func (x *WorkloadAttrsUnix) GetBinaryHash() string { + if x != nil && x.BinaryHash != nil { + return *x.BinaryHash + } + return "" +} + // Attributes sourced from the Podman workload attestor. type WorkloadAttrsPodman struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -939,150 +957,157 @@ var file_teleport_workloadidentity_v1_attrs_proto_rawDesc = string([]byte{ 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x44, 0x69, 0x67, 0x65, 0x73, - 0x74, 0x22, 0x65, 0x0a, 0x11, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x74, 0x74, - 0x72, 0x73, 0x55, 0x6e, 0x69, 0x78, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, - 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, - 0x65, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x03, 0x70, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0d, 0x52, 0x03, 0x67, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0d, 0x52, 0x03, 0x75, 0x69, 0x64, 0x22, 0xe0, 0x01, 0x0a, 0x13, 0x57, 0x6f, 0x72, + 0x74, 0x22, 0xd1, 0x01, 0x0a, 0x11, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x74, + 0x74, 0x72, 0x73, 0x55, 0x6e, 0x69, 0x78, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x74, 0x74, 0x65, 0x73, + 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x61, 0x74, 0x74, 0x65, 0x73, + 0x74, 0x65, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x03, 0x70, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x03, 0x67, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x75, 0x69, 0x64, 0x12, 0x24, 0x0a, 0x0b, 0x62, 0x69, 0x6e, + 0x61, 0x72, 0x79, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, + 0x52, 0x0a, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x50, 0x61, 0x74, 0x68, 0x88, 0x01, 0x01, 0x12, + 0x24, 0x0a, 0x0b, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x0a, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x48, 0x61, + 0x73, 0x68, 0x88, 0x01, 0x01, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, + 0x5f, 0x70, 0x61, 0x74, 0x68, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, + 0x5f, 0x68, 0x61, 0x73, 0x68, 0x22, 0xe0, 0x01, 0x0a, 0x13, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, + 0x61, 0x64, 0x41, 0x74, 0x74, 0x72, 0x73, 0x50, 0x6f, 0x64, 0x6d, 0x61, 0x6e, 0x12, 0x1a, 0x0a, + 0x08, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x08, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x64, 0x12, 0x58, 0x0a, 0x09, 0x63, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x74, + 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, + 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, + 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x74, 0x74, 0x72, 0x73, 0x50, 0x6f, 0x64, 0x6d, 0x61, 0x6e, 0x43, + 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, + 0x6e, 0x65, 0x72, 0x12, 0x4b, 0x0a, 0x03, 0x70, 0x6f, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x34, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x77, 0x6f, 0x72, 0x6b, + 0x6c, 0x6f, 0x61, 0x64, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, + 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x74, 0x74, 0x72, 0x73, 0x50, 0x6f, 0x64, + 0x6d, 0x61, 0x6e, 0x50, 0x6f, 0x64, 0x48, 0x00, 0x52, 0x03, 0x70, 0x6f, 0x64, 0x88, 0x01, 0x01, + 0x42, 0x06, 0x0a, 0x04, 0x5f, 0x70, 0x6f, 0x64, 0x22, 0x86, 0x02, 0x0a, 0x1c, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x74, 0x74, 0x72, 0x73, 0x50, 0x6f, 0x64, 0x6d, 0x61, 0x6e, - 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x08, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x64, 0x12, 0x58, 0x0a, 0x09, - 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x3a, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x6c, - 0x6f, 0x61, 0x64, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x57, - 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x74, 0x74, 0x72, 0x73, 0x50, 0x6f, 0x64, 0x6d, - 0x61, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x09, 0x63, 0x6f, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x4b, 0x0a, 0x03, 0x70, 0x6f, 0x64, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x77, + 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, + 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x69, 0x6d, + 0x61, 0x67, 0x65, 0x12, 0x5e, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x03, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x46, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x74, 0x74, 0x72, 0x73, - 0x50, 0x6f, 0x64, 0x6d, 0x61, 0x6e, 0x50, 0x6f, 0x64, 0x48, 0x00, 0x52, 0x03, 0x70, 0x6f, 0x64, - 0x88, 0x01, 0x01, 0x42, 0x06, 0x0a, 0x04, 0x5f, 0x70, 0x6f, 0x64, 0x22, 0x86, 0x02, 0x0a, 0x1c, - 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x74, 0x74, 0x72, 0x73, 0x50, 0x6f, 0x64, - 0x6d, 0x61, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, + 0x50, 0x6f, 0x64, 0x6d, 0x61, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, + 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, + 0x65, 0x6c, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x64, 0x69, 0x67, + 0x65, 0x73, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x6d, 0x61, 0x67, 0x65, + 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, + 0x01, 0x22, 0xc1, 0x01, 0x0a, 0x16, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x74, + 0x74, 0x72, 0x73, 0x50, 0x6f, 0x64, 0x6d, 0x61, 0x6e, 0x50, 0x6f, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x5e, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, - 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x46, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x74, - 0x74, 0x72, 0x73, 0x50, 0x6f, 0x64, 0x6d, 0x61, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, - 0x65, 0x72, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, - 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, - 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x6d, - 0x61, 0x67, 0x65, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, - 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x3a, 0x02, 0x38, 0x01, 0x22, 0xc1, 0x01, 0x0a, 0x16, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, - 0x64, 0x41, 0x74, 0x74, 0x72, 0x73, 0x50, 0x6f, 0x64, 0x6d, 0x61, 0x6e, 0x50, 0x6f, 0x64, 0x12, - 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x12, 0x58, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x02, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x77, + 0x12, 0x58, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x40, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x77, 0x6f, 0x72, 0x6b, + 0x6c, 0x6f, 0x61, 0x64, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, + 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x74, 0x74, 0x72, 0x73, 0x50, 0x6f, 0x64, + 0x6d, 0x61, 0x6e, 0x50, 0x6f, 0x64, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, + 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x8b, 0x01, 0x0a, 0x13, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, + 0x61, 0x64, 0x41, 0x74, 0x74, 0x72, 0x73, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x12, 0x1a, 0x0a, + 0x08, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x08, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x64, 0x12, 0x58, 0x0a, 0x09, 0x63, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x74, + 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, + 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, + 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x74, 0x74, 0x72, 0x73, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x43, + 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, + 0x6e, 0x65, 0x72, 0x22, 0x86, 0x02, 0x0a, 0x1c, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, + 0x41, 0x74, 0x74, 0x72, 0x73, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6d, 0x61, 0x67, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x5e, + 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x46, + 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, + 0x61, 0x64, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, + 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x74, 0x74, 0x72, 0x73, 0x44, 0x6f, 0x63, 0x6b, 0x65, + 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, + 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x21, + 0x0a, 0x0c, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x44, 0x69, 0x67, 0x65, 0x73, + 0x74, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, + 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x4c, 0x0a, 0x14, + 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x74, 0x74, 0x72, 0x73, 0x53, 0x79, 0x73, + 0x74, 0x65, 0x6d, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x64, + 0x12, 0x18, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x22, 0x8f, 0x03, 0x0a, 0x0d, 0x57, + 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x74, 0x74, 0x72, 0x73, 0x12, 0x43, 0x0a, 0x04, + 0x75, 0x6e, 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x74, 0x65, 0x6c, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x69, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, + 0x61, 0x64, 0x41, 0x74, 0x74, 0x72, 0x73, 0x55, 0x6e, 0x69, 0x78, 0x52, 0x04, 0x75, 0x6e, 0x69, + 0x78, 0x12, 0x55, 0x0a, 0x0a, 0x6b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, + 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, + 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x74, 0x74, + 0x72, 0x73, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x52, 0x0a, 0x6b, 0x75, + 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x12, 0x49, 0x0a, 0x06, 0x70, 0x6f, 0x64, 0x6d, + 0x61, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x69, 0x64, 0x65, 0x6e, + 0x74, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, + 0x41, 0x74, 0x74, 0x72, 0x73, 0x50, 0x6f, 0x64, 0x6d, 0x61, 0x6e, 0x52, 0x06, 0x70, 0x6f, 0x64, + 0x6d, 0x61, 0x6e, 0x12, 0x49, 0x0a, 0x06, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x74, 0x74, 0x72, 0x73, - 0x50, 0x6f, 0x64, 0x6d, 0x61, 0x6e, 0x50, 0x6f, 0x64, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x1a, 0x39, 0x0a, - 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, - 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x8b, 0x01, 0x0a, 0x13, 0x57, 0x6f, 0x72, - 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x74, 0x74, 0x72, 0x73, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, - 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x08, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x64, 0x12, 0x58, 0x0a, 0x09, - 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x3a, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x6c, + 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x52, 0x06, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x12, 0x4c, + 0x0a, 0x07, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x32, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x57, - 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x74, 0x74, 0x72, 0x73, 0x44, 0x6f, 0x63, 0x6b, - 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x09, 0x63, 0x6f, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x22, 0x86, 0x02, 0x0a, 0x1c, 0x57, 0x6f, 0x72, 0x6b, 0x6c, - 0x6f, 0x61, 0x64, 0x41, 0x74, 0x74, 0x72, 0x73, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x43, 0x6f, - 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x69, - 0x6d, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x69, 0x6d, 0x61, 0x67, - 0x65, 0x12, 0x5e, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x46, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x77, 0x6f, 0x72, - 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, - 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x74, 0x74, 0x72, 0x73, 0x44, 0x6f, - 0x63, 0x6b, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x4c, 0x61, - 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, - 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, - 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x44, 0x69, - 0x67, 0x65, 0x73, 0x74, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, - 0x4c, 0x0a, 0x14, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x74, 0x74, 0x72, 0x73, - 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x74, 0x74, 0x65, 0x73, - 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x61, 0x74, 0x74, 0x65, 0x73, - 0x74, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x22, 0x8f, 0x03, - 0x0a, 0x0d, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x74, 0x74, 0x72, 0x73, 0x12, - 0x43, 0x0a, 0x04, 0x75, 0x6e, 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, - 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, - 0x64, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, - 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x74, 0x74, 0x72, 0x73, 0x55, 0x6e, 0x69, 0x78, 0x52, 0x04, - 0x75, 0x6e, 0x69, 0x78, 0x12, 0x55, 0x0a, 0x0a, 0x6b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, - 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, + 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x74, 0x74, 0x72, 0x73, 0x53, 0x79, 0x73, 0x74, + 0x65, 0x6d, 0x64, 0x52, 0x07, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x22, 0xb3, 0x02, 0x0a, + 0x09, 0x55, 0x73, 0x65, 0x72, 0x41, 0x74, 0x74, 0x72, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x15, + 0x0a, 0x06, 0x69, 0x73, 0x5f, 0x62, 0x6f, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, + 0x69, 0x73, 0x42, 0x6f, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x62, 0x6f, 0x74, 0x5f, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x62, 0x6f, 0x74, 0x4e, 0x61, 0x6d, 0x65, + 0x12, 0x26, 0x0a, 0x0f, 0x62, 0x6f, 0x74, 0x5f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, + 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x62, 0x6f, 0x74, 0x49, 0x6e, + 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x4b, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, + 0x6c, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x69, 0x64, 0x65, 0x6e, - 0x74, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, - 0x41, 0x74, 0x74, 0x72, 0x73, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x52, - 0x0a, 0x6b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x12, 0x49, 0x0a, 0x06, 0x70, - 0x6f, 0x64, 0x6d, 0x61, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x74, 0x65, - 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x69, - 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, - 0x6f, 0x61, 0x64, 0x41, 0x74, 0x74, 0x72, 0x73, 0x50, 0x6f, 0x64, 0x6d, 0x61, 0x6e, 0x52, 0x06, - 0x70, 0x6f, 0x64, 0x6d, 0x61, 0x6e, 0x12, 0x49, 0x0a, 0x06, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x74, - 0x74, 0x72, 0x73, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x52, 0x06, 0x64, 0x6f, 0x63, 0x6b, 0x65, - 0x72, 0x12, 0x4c, 0x0a, 0x07, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x77, 0x6f, - 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x76, - 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x74, 0x74, 0x72, 0x73, 0x53, - 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x52, 0x07, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x22, - 0xb3, 0x02, 0x0a, 0x09, 0x55, 0x73, 0x65, 0x72, 0x41, 0x74, 0x74, 0x72, 0x73, 0x12, 0x12, 0x0a, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x12, 0x15, 0x0a, 0x06, 0x69, 0x73, 0x5f, 0x62, 0x6f, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x05, 0x69, 0x73, 0x42, 0x6f, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x62, 0x6f, 0x74, 0x5f, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x62, 0x6f, 0x74, 0x4e, - 0x61, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x62, 0x6f, 0x74, 0x5f, 0x69, 0x6e, 0x73, 0x74, 0x61, - 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x62, 0x6f, - 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x4b, 0x0a, 0x06, 0x6c, - 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x74, 0x65, - 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x69, - 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x41, - 0x74, 0x74, 0x72, 0x73, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x30, 0x0a, 0x06, 0x74, 0x72, 0x61, 0x69, - 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, - 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x72, 0x61, 0x69, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x61, - 0x69, 0x74, 0x52, 0x06, 0x74, 0x72, 0x61, 0x69, 0x74, 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, - 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xca, 0x01, 0x0a, 0x05, 0x41, 0x74, 0x74, 0x72, 0x73, 0x12, - 0x47, 0x0a, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x2b, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x77, 0x6f, 0x72, - 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, - 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x74, 0x74, 0x72, 0x73, 0x52, 0x08, - 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x3b, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x41, 0x74, 0x74, 0x72, 0x73, 0x52, - 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x3b, 0x0a, 0x04, 0x6a, 0x6f, 0x69, 0x6e, 0x18, 0x03, 0x20, + 0x74, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x41, 0x74, 0x74, 0x72, + 0x73, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, + 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x30, 0x0a, 0x06, 0x74, 0x72, 0x61, 0x69, 0x74, 0x73, 0x18, + 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, + 0x2e, 0x74, 0x72, 0x61, 0x69, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x61, 0x69, 0x74, 0x52, + 0x06, 0x74, 0x72, 0x61, 0x69, 0x74, 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, + 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, + 0x38, 0x01, 0x22, 0xca, 0x01, 0x0a, 0x05, 0x41, 0x74, 0x74, 0x72, 0x73, 0x12, 0x47, 0x0a, 0x08, + 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, + 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, + 0x61, 0x64, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, + 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x41, 0x74, 0x74, 0x72, 0x73, 0x52, 0x08, 0x77, 0x6f, 0x72, + 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x3b, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, - 0x76, 0x31, 0x2e, 0x4a, 0x6f, 0x69, 0x6e, 0x41, 0x74, 0x74, 0x72, 0x73, 0x52, 0x04, 0x6a, 0x6f, - 0x69, 0x6e, 0x42, 0x64, 0x5a, 0x62, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x67, 0x72, 0x61, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x74, - 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x65, 0x6e, 0x2f, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x74, 0x79, 0x2f, 0x76, 0x31, 0x3b, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x69, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x41, 0x74, 0x74, 0x72, 0x73, 0x52, 0x04, 0x75, 0x73, + 0x65, 0x72, 0x12, 0x3b, 0x0a, 0x04, 0x6a, 0x6f, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x27, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x77, 0x6f, 0x72, 0x6b, + 0x6c, 0x6f, 0x61, 0x64, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2e, 0x76, 0x31, 0x2e, + 0x4a, 0x6f, 0x69, 0x6e, 0x41, 0x74, 0x74, 0x72, 0x73, 0x52, 0x04, 0x6a, 0x6f, 0x69, 0x6e, 0x42, + 0x64, 0x5a, 0x62, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, + 0x61, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x6c, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x77, + 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x2f, + 0x76, 0x31, 0x3b, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x69, 0x64, 0x65, 0x6e, 0x74, + 0x69, 0x74, 0x79, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, }) var ( @@ -1152,6 +1177,7 @@ func file_teleport_workloadidentity_v1_attrs_proto_init() { } file_teleport_workloadidentity_v1_join_attrs_proto_init() file_teleport_workloadidentity_v1_attrs_proto_msgTypes[0].OneofWrappers = []any{} + file_teleport_workloadidentity_v1_attrs_proto_msgTypes[2].OneofWrappers = []any{} file_teleport_workloadidentity_v1_attrs_proto_msgTypes[3].OneofWrappers = []any{} type x struct{} out := protoimpl.TypeBuilder{ diff --git a/api/proto/teleport/workloadidentity/v1/attrs.proto b/api/proto/teleport/workloadidentity/v1/attrs.proto index 9851e16870a4e..ed99ca764f03c 100644 --- a/api/proto/teleport/workloadidentity/v1/attrs.proto +++ b/api/proto/teleport/workloadidentity/v1/attrs.proto @@ -59,6 +59,10 @@ message WorkloadAttrsUnix { uint32 gid = 3; // The primary group ID of the workload process. uint32 uid = 4; + // The path to the workload process binary. + optional string binary_path = 5; + // The hex-encoded SHA256 hash of the workload process binary. + optional string binary_hash = 6; } // Attributes sourced from the Podman workload attestor. diff --git a/lib/tbot/config/service_spiffe_workload_api_test.go b/lib/tbot/config/service_spiffe_workload_api_test.go index 46de57dd58d13..109b820a9aaeb 100644 --- a/lib/tbot/config/service_spiffe_workload_api_test.go +++ b/lib/tbot/config/service_spiffe_workload_api_test.go @@ -124,6 +124,27 @@ func TestSPIFFEWorkloadAPIService_CheckAndSetDefaults(t *testing.T) { }, } }, + want: &SPIFFEWorkloadAPIService{ + JWTSVIDTTL: time.Minute, + Listen: "unix:///var/run/spiffe.sock", + SVIDs: []SVIDRequestWithRules{ + { + SVIDRequest: SVIDRequest{ + Path: "/foo", + Hint: "hint", + SANS: SVIDRequestSANs{ + DNS: []string{"example.com"}, + IP: []string{"10.0.0.1", "10.42.0.1"}, + }, + }, + }, + }, + Attestors: workloadattest.Config{ + Unix: workloadattest.UnixAttestorConfig{ + BinaryHashMaxSizeBytes: workloadattest.DefaultBinaryHashMaxBytes, + }, + }, + }, }, { name: "missing path", diff --git a/lib/tbot/config/service_workload_identity_api_test.go b/lib/tbot/config/service_workload_identity_api_test.go index b1d6645dd9e57..99cabd26a52a1 100644 --- a/lib/tbot/config/service_workload_identity_api_test.go +++ b/lib/tbot/config/service_workload_identity_api_test.go @@ -74,6 +74,17 @@ func TestWorkloadIdentityAPIService_CheckAndSetDefaults(t *testing.T) { Listen: "tcp://0.0.0.0:4040", } }, + want: &WorkloadIdentityAPIService{ + Selector: WorkloadIdentitySelector{ + Name: "my-workload-identity", + }, + Listen: "tcp://0.0.0.0:4040", + Attestors: workloadattest.Config{ + Unix: workloadattest.UnixAttestorConfig{ + BinaryHashMaxSizeBytes: workloadattest.DefaultBinaryHashMaxBytes, + }, + }, + }, }, { name: "valid with labels", @@ -87,6 +98,19 @@ func TestWorkloadIdentityAPIService_CheckAndSetDefaults(t *testing.T) { Listen: "tcp://0.0.0.0:4040", } }, + want: &WorkloadIdentityAPIService{ + Selector: WorkloadIdentitySelector{ + Labels: map[string][]string{ + "key": {"value"}, + }, + }, + Listen: "tcp://0.0.0.0:4040", + Attestors: workloadattest.Config{ + Unix: workloadattest.UnixAttestorConfig{ + BinaryHashMaxSizeBytes: workloadattest.DefaultBinaryHashMaxBytes, + }, + }, + }, }, { name: "missing selectors", diff --git a/lib/tbot/config/testdata/TestBotConfig_YAML/standard_config.golden b/lib/tbot/config/testdata/TestBotConfig_YAML/standard_config.golden index 5d3ee7a7400d9..d8f91a65e602c 100644 --- a/lib/tbot/config/testdata/TestBotConfig_YAML/standard_config.golden +++ b/lib/tbot/config/testdata/TestBotConfig_YAML/standard_config.golden @@ -48,6 +48,7 @@ services: enabled: false systemd: enabled: false + unix: {} - type: example message: llama - type: ssh-multiplexer @@ -78,6 +79,7 @@ services: enabled: false systemd: enabled: false + unix: {} selector: name: my-workload-identity - type: workload-identity-jwt diff --git a/lib/tbot/config/testdata/TestSPIFFEWorkloadAPIService_YAML/full.golden b/lib/tbot/config/testdata/TestSPIFFEWorkloadAPIService_YAML/full.golden index cbe7f5cc19fdd..b3587f03cc375 100644 --- a/lib/tbot/config/testdata/TestSPIFFEWorkloadAPIService_YAML/full.golden +++ b/lib/tbot/config/testdata/TestSPIFFEWorkloadAPIService_YAML/full.golden @@ -36,4 +36,5 @@ attestors: enabled: false systemd: enabled: false + unix: {} jwt_svid_ttl: 5m0s diff --git a/lib/tbot/config/testdata/TestSPIFFEWorkloadAPIService_YAML/minimal.golden b/lib/tbot/config/testdata/TestSPIFFEWorkloadAPIService_YAML/minimal.golden index 053f664554039..9954657bf6c04 100644 --- a/lib/tbot/config/testdata/TestSPIFFEWorkloadAPIService_YAML/minimal.golden +++ b/lib/tbot/config/testdata/TestSPIFFEWorkloadAPIService_YAML/minimal.golden @@ -11,3 +11,4 @@ attestors: enabled: false systemd: enabled: false + unix: {} diff --git a/lib/tbot/config/testdata/TestWorkloadIdentityAPIService_YAML/full.golden b/lib/tbot/config/testdata/TestWorkloadIdentityAPIService_YAML/full.golden index 751f9ccdffe97..13b8eafe4b1c2 100644 --- a/lib/tbot/config/testdata/TestWorkloadIdentityAPIService_YAML/full.golden +++ b/lib/tbot/config/testdata/TestWorkloadIdentityAPIService_YAML/full.golden @@ -15,5 +15,6 @@ attestors: enabled: false systemd: enabled: false + unix: {} selector: name: my-workload-identity diff --git a/lib/tbot/config/testdata/TestWorkloadIdentityAPIService_YAML/minimal.golden b/lib/tbot/config/testdata/TestWorkloadIdentityAPIService_YAML/minimal.golden index 1e456b4fb2729..36cebd027dd5b 100644 --- a/lib/tbot/config/testdata/TestWorkloadIdentityAPIService_YAML/minimal.golden +++ b/lib/tbot/config/testdata/TestWorkloadIdentityAPIService_YAML/minimal.golden @@ -9,5 +9,6 @@ attestors: enabled: false systemd: enabled: false + unix: {} selector: name: my-workload-identity diff --git a/lib/tbot/workloadidentity/workloadattest/attest.go b/lib/tbot/workloadidentity/workloadattest/attest.go index 32c994841d39a..24f6248f18bf9 100644 --- a/lib/tbot/workloadidentity/workloadattest/attest.go +++ b/lib/tbot/workloadidentity/workloadattest/attest.go @@ -48,6 +48,7 @@ type Config struct { Podman PodmanAttestorConfig `yaml:"podman"` Docker DockerAttestorConfig `yaml:"docker"` Systemd SystemdAttestorConfig `yaml:"systemd"` + Unix UnixAttestorConfig `yaml:"unix"` } func (c *Config) CheckAndSetDefaults() error { @@ -60,6 +61,9 @@ func (c *Config) CheckAndSetDefaults() error { if err := c.Docker.CheckAndSetDefaults(); err != nil { return trace.Wrap(err, "validating docker") } + if err := c.Unix.CheckAndSetDefaults(); err != nil { + return trace.Wrap(err, "validating unix") + } return nil } @@ -67,7 +71,7 @@ func (c *Config) CheckAndSetDefaults() error { func NewAttestor(log *slog.Logger, cfg Config) (*Attestor, error) { att := &Attestor{ log: log, - unix: NewUnixAttestor(), + unix: NewUnixAttestor(cfg.Unix, log), } if cfg.Kubernetes.Enabled { att.kubernetes = NewKubernetesAttestor(cfg.Kubernetes, log) diff --git a/lib/tbot/workloadidentity/workloadattest/unix.go b/lib/tbot/workloadidentity/workloadattest/unix.go index a0fc277ca4393..a7b0a2aaa8b04 100644 --- a/lib/tbot/workloadidentity/workloadattest/unix.go +++ b/lib/tbot/workloadidentity/workloadattest/unix.go @@ -20,6 +20,11 @@ package workloadattest import ( "context" + "crypto/sha256" + "encoding/hex" + "errors" + "io" + "log/slog" "github.com/gravitational/trace" "github.com/shirou/gopsutil/v4/process" @@ -27,13 +32,58 @@ import ( workloadidentityv1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/workloadidentity/v1" ) +// DefaultBinaryHashMaxBytes is default value for BinaryHashMaxSizeBytes. +const DefaultBinaryHashMaxBytes = 1 << 30 // 1GiB + +// UnixAttestorConfig holds the configuration for the Unix workload attestor. +type UnixAttestorConfig struct { + // BinaryHashMaxSize is the maximum number of bytes that will be read from + // a process' binary to calculate its SHA256 checksum. If the binary is + // larger than this, the `binary_hash` attribute will be empty (to prevent + // DoS attacks). + // + // Defaults to 1GiB. Set it to -1 to make it unlimited. + BinaryHashMaxSizeBytes int64 `yaml:"binary_hash_max_size_bytes,omitempty"` +} + +func (u *UnixAttestorConfig) CheckAndSetDefaults() error { + if u.BinaryHashMaxSizeBytes == 0 { + u.BinaryHashMaxSizeBytes = DefaultBinaryHashMaxBytes + } + if u.BinaryHashMaxSizeBytes < -1 { + return trace.BadParameter("binary_hash_max_size_bytes must be -1 (unlimited), 0 (default), or greater") + } + return nil +} + // UnixAttestor attests a process id to a Unix process. type UnixAttestor struct { + cfg UnixAttestorConfig + log *slog.Logger + os UnixOS +} + +// UnixOS is a handle on the operating system-specific features used by the Unix +// workload attestor. +type UnixOS interface { + // ExePath returns the filesystem path of the given process' executable. + ExePath(ctx context.Context, proc *process.Process) (string, error) + + // OpenExe opens the given process' executable for reading. + // + // Use this rather than `os.Open(ExePath(proc))` because operating systems + // like Linux provide ways to read the original executable when the file on + // disk is replaced or modified. + OpenExe(ctx context.Context, proc *process.Process) (io.ReadCloser, error) } // NewUnixAttestor returns a new UnixAttestor. -func NewUnixAttestor() *UnixAttestor { - return &UnixAttestor{} +func NewUnixAttestor(cfg UnixAttestorConfig, log *slog.Logger) *UnixAttestor { + return &UnixAttestor{ + cfg: cfg, + log: log, + os: unixOS, + } } // Attest attests a process id to a Unix process. @@ -89,5 +139,58 @@ func (a *UnixAttestor) Attest(ctx context.Context, pid int) (*workloadidentityv1 att.Uid = uids[1] } + path, err := a.os.ExePath(ctx, p) + switch { + case trace.IsNotFound(err): + // We could not find the executable because we're in a different mount namespace. + case err != nil: + a.log.ErrorContext(ctx, "Failed to find workload executable", "error", err) + default: + att.BinaryPath = &path + } + + exe, err := a.os.OpenExe(ctx, p) + if err != nil { + a.log.ErrorContext(ctx, "Failed to open workload executable for hashing", "error", err) + return att, nil + } + defer func() { _ = exe.Close() }() + + hash := sha256.New() + if _, err := copyAtMost(hash, exe, a.cfg.BinaryHashMaxSizeBytes); err != nil { + a.log.ErrorContext(ctx, "Failed to hash workload executable", "error", err) + return att, nil + } + sum := hex.EncodeToString(hash.Sum(nil)) + att.BinaryHash = &sum + return att, nil } + +// copyAtMost copies at most n bytes from src to dst. If src contains more than +// n bytes, a LimitExceeded error will be returned. +func copyAtMost(dst io.Writer, src io.Reader, n int64) (int64, error) { + // -1 is unlimited. + if n == -1 { + return io.Copy(dst, src) + } + + copied, err := io.CopyN(dst, src, n) + switch { + case errors.Is(err, io.EOF): + return copied, nil + case err != nil: + return 0, err + } + + // Try to read one more byte to see if we reached the end of src. + _, err = src.Read([]byte{0}) + switch { + case errors.Is(err, io.EOF): + return copied, nil + case err != nil: + return 0, err + default: + return 0, trace.LimitExceeded("input is larger than limit (%d)", n) + } +} diff --git a/lib/tbot/workloadidentity/workloadattest/unix_linux.go b/lib/tbot/workloadidentity/workloadattest/unix_linux.go new file mode 100644 index 0000000000000..35a7938199cab --- /dev/null +++ b/lib/tbot/workloadidentity/workloadattest/unix_linux.go @@ -0,0 +1,61 @@ +//go:build linux + +/* + * Teleport + * Copyright (C) 2025 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package workloadattest + +import ( + "context" + "io" + "os" + "path/filepath" + "strconv" + + "github.com/shirou/gopsutil/v4/process" +) + +var unixOS UnixOS = linux{} + +type linux struct{} + +func (l linux) ExePath(ctx context.Context, proc *process.Process) (string, error) { + return proc.ExeWithContext(ctx) +} + +func (l linux) OpenExe(ctx context.Context, proc *process.Process) (io.ReadCloser, error) { + // On Linux, `/proc//exe` is a symlink to the *inode* of the process' + // executable rather than a simple path, this means it won't change even if + // you replace the file on disk. + // + // In other words, during a rolling deployment the binary's hash won't change + // until the process has actually been restarted - which is desirable. + // + // With one important caveat: network filesystems typically do not guarantee + // inode stability, so if the process' binary is on a network mount, it's + // possible the hash won't match the binary the process is actually running. + return os.Open(l.procPath(strconv.Itoa(int(proc.Pid)), "exe")) +} + +func (l linux) procPath(parts ...string) string { + base := os.Getenv("HOST_PROC") + if base == "" { + base = "/proc" + } + return filepath.Join(append([]string{base}, parts...)...) +} diff --git a/lib/tbot/workloadidentity/workloadattest/unix_other.go b/lib/tbot/workloadidentity/workloadattest/unix_other.go new file mode 100644 index 0000000000000..d926d9ff58a86 --- /dev/null +++ b/lib/tbot/workloadidentity/workloadattest/unix_other.go @@ -0,0 +1,46 @@ +//go:build !linux + +/* + * Teleport + * Copyright (C) 2025 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package workloadattest + +import ( + "context" + "io" + "os" + + "github.com/shirou/gopsutil/v4/process" +) + +var unixOS UnixOS = nonLinux{} + +// nonLinux implements the UnixOS interface for non-Linux systems. +type nonLinux struct{} + +func (nonLinux) ExePath(ctx context.Context, proc *process.Process) (string, error) { + return proc.ExeWithContext(ctx) +} + +func (n nonLinux) OpenExe(ctx context.Context, proc *process.Process) (io.ReadCloser, error) { + path, err := n.ExePath(ctx, proc) + if err != nil { + return nil, err + } + return os.Open(path) +} diff --git a/lib/tbot/workloadidentity/workloadattest/unix_test.go b/lib/tbot/workloadidentity/workloadattest/unix_test.go index a14be0c1a8619..6447aebfe11e5 100644 --- a/lib/tbot/workloadidentity/workloadattest/unix_test.go +++ b/lib/tbot/workloadidentity/workloadattest/unix_test.go @@ -19,15 +19,23 @@ package workloadattest import ( + "bytes" "context" + "io" "os" + "strings" "testing" "github.com/google/go-cmp/cmp" + "github.com/gravitational/trace" + "github.com/shirou/gopsutil/v4/process" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "google.golang.org/protobuf/proto" "google.golang.org/protobuf/testing/protocmp" workloadidentityv1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/workloadidentity/v1" + "github.com/gravitational/teleport/lib/utils" ) func TestUnixAttestor_Attest(t *testing.T) { @@ -38,13 +46,102 @@ func TestUnixAttestor_Attest(t *testing.T) { uid := os.Getuid() gid := os.Getgid() - attestor := NewUnixAttestor() + attestor := NewUnixAttestor( + UnixAttestorConfig{BinaryHashMaxSizeBytes: -1}, + utils.NewSlogLoggerForTests(), + ) + attestor.os = testOS{ + exePath: func(context.Context, *process.Process) (string, error) { + return "/path/to/executable", nil + }, + openExe: func(context.Context, *process.Process) (io.ReadCloser, error) { + return io.NopCloser(strings.NewReader(`hello world`)), nil + }, + } + att, err := attestor.Attest(ctx, pid) require.NoError(t, err) - require.Empty(t, cmp.Diff(&workloadidentityv1pb.WorkloadAttrsUnix{ - Attested: true, - Pid: int32(pid), - Uid: uint32(uid), - Gid: uint32(gid), - }, att, protocmp.Transform())) + require.Empty(t, + cmp.Diff( + &workloadidentityv1pb.WorkloadAttrsUnix{ + Attested: true, + Pid: int32(pid), + Uid: uint32(uid), + Gid: uint32(gid), + BinaryPath: proto.String("/path/to/executable"), + BinaryHash: proto.String("b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"), + }, + att, + protocmp.Transform(), + ), + ) +} + +func TestUnixAttestor_BinaryTooLarge(t *testing.T) { + t.Parallel() + ctx := context.Background() + + attestor := NewUnixAttestor( + UnixAttestorConfig{BinaryHashMaxSizeBytes: 1024}, + utils.NewSlogLoggerForTests(), + ) + attestor.os = testOS{ + exePath: func(context.Context, *process.Process) (string, error) { + return "/path/to/executable", nil + }, + openExe: func(context.Context, *process.Process) (io.ReadCloser, error) { + var exe [2048]byte + return io.NopCloser(bytes.NewReader(exe[:])), nil + }, + } + + att, err := attestor.Attest(ctx, os.Getpid()) + require.NoError(t, err) + require.Nil(t, att.BinaryHash) +} + +type testOS struct { + exePath func(context.Context, *process.Process) (string, error) + openExe func(context.Context, *process.Process) (io.ReadCloser, error) +} + +func (t testOS) ExePath(ctx context.Context, proc *process.Process) (string, error) { + return t.exePath(ctx, proc) +} + +func (t testOS) OpenExe(ctx context.Context, proc *process.Process) (io.ReadCloser, error) { + return t.openExe(ctx, proc) +} + +func Test_copyAtMost(t *testing.T) { + t.Run("n > len(src)", func(t *testing.T) { + var dst bytes.Buffer + src := bytes.NewReader([]byte{1, 2, 3}) + + copied, err := copyAtMost(&dst, src, 5) + require.NoError(t, err) + + assert.Equal(t, int64(3), copied) + assert.Equal(t, []byte{1, 2, 3}, dst.Bytes()) + }) + + t.Run("n == len(src)", func(t *testing.T) { + var dst bytes.Buffer + src := bytes.NewReader([]byte{1, 2, 3}) + + copied, err := copyAtMost(&dst, src, 3) + require.NoError(t, err) + + assert.Equal(t, int64(3), copied) + assert.Equal(t, []byte{1, 2, 3}, dst.Bytes()) + }) + + t.Run("n < len(src)", func(t *testing.T) { + var dst bytes.Buffer + src := bytes.NewReader([]byte{1, 2, 3}) + + _, err := copyAtMost(&dst, src, 1) + require.Error(t, err) + assert.True(t, trace.IsLimitExceeded(err)) + }) }