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))
+ })
}