From bdf3ce0bf4c1ec3bb05babdd5ae00d7335791252 Mon Sep 17 00:00:00 2001 From: Nic Klaassen Date: Thu, 6 Nov 2025 12:30:16 -0800 Subject: [PATCH 1/2] azure join message types --- .../go/teleport/join/v1/joinservice.pb.go | 425 ++++++++++++++---- api/proto/teleport/join/v1/joinservice.proto | 38 ++ lib/join/internal/messages/messages.go | 42 ++ lib/join/joinv1/messages.go | 34 +- lib/join/joinv1/messages_azure.go | 70 +++ lib/join/joinv1/messages_test.go | 16 + 6 files changed, 526 insertions(+), 99 deletions(-) create mode 100644 lib/join/joinv1/messages_azure.go diff --git a/api/gen/proto/go/teleport/join/v1/joinservice.pb.go b/api/gen/proto/go/teleport/join/v1/joinservice.pb.go index e69d9b34c318a..fac060e57af67 100644 --- a/api/gen/proto/go/teleport/join/v1/joinservice.pb.go +++ b/api/gen/proto/go/teleport/join/v1/joinservice.pb.go @@ -93,7 +93,7 @@ func (x GivingUp_Reason) Number() protoreflect.EnumNumber { // Deprecated: Use GivingUp_Reason.Descriptor instead. func (GivingUp_Reason) EnumDescriptor() ([]byte, []int) { - return file_teleport_join_v1_joinservice_proto_rawDescGZIP(), []int{24, 0} + return file_teleport_join_v1_joinservice_proto_rawDescGZIP(), []int{27, 0} } // ClientInit is the first message sent from the client during the join process, it @@ -1572,6 +1572,168 @@ func (x *TPMSolution) GetSolution() []byte { return nil } +// AzureInit is sent from the client in response to the ServerInit message for +// the Azure join method. +// +// The Azure method join flow is: +// 1. client->server: ClientInit +// 2. client<-server: ServerInit +// 3. client->server: AzureInit +// 4. client<-server: AzureChallenge +// 5. client->server: AzureChallengeSolution +// 6. client<-server: Result +type AzureInit struct { + state protoimpl.MessageState `protogen:"open.v1"` + // ClientParams holds parameters for the specific type of client trying to join. + ClientParams *ClientParams `protobuf:"bytes,1,opt,name=client_params,json=clientParams,proto3" json:"client_params,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AzureInit) Reset() { + *x = AzureInit{} + mi := &file_teleport_join_v1_joinservice_proto_msgTypes[23] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AzureInit) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AzureInit) ProtoMessage() {} + +func (x *AzureInit) ProtoReflect() protoreflect.Message { + mi := &file_teleport_join_v1_joinservice_proto_msgTypes[23] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AzureInit.ProtoReflect.Descriptor instead. +func (*AzureInit) Descriptor() ([]byte, []int) { + return file_teleport_join_v1_joinservice_proto_rawDescGZIP(), []int{23} +} + +func (x *AzureInit) GetClientParams() *ClientParams { + if x != nil { + return x.ClientParams + } + return nil +} + +// AzureChallenge is sent from the server in response to the AzureInit message from the client. +// The client is expected to respond with a AzureChallengeSolution. +type AzureChallenge struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Challenge is a a crypto-random string that should be included by the + // client in the challenge response message. + Challenge string `protobuf:"bytes,1,opt,name=challenge,proto3" json:"challenge,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AzureChallenge) Reset() { + *x = AzureChallenge{} + mi := &file_teleport_join_v1_joinservice_proto_msgTypes[24] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AzureChallenge) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AzureChallenge) ProtoMessage() {} + +func (x *AzureChallenge) ProtoReflect() protoreflect.Message { + mi := &file_teleport_join_v1_joinservice_proto_msgTypes[24] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AzureChallenge.ProtoReflect.Descriptor instead. +func (*AzureChallenge) Descriptor() ([]byte, []int) { + return file_teleport_join_v1_joinservice_proto_rawDescGZIP(), []int{24} +} + +func (x *AzureChallenge) GetChallenge() string { + if x != nil { + return x.Challenge + } + return "" +} + +// AzureChallengeSolution must be sent from the client in response to the +// AzureChallenge message. +type AzureChallengeSolution struct { + state protoimpl.MessageState `protogen:"open.v1"` + // AttestedData is a signed JSON document from an Azure VM's attested data + // metadata endpoint used to prove the identity of a joining node. It must + // include the challenge string as the nonce. + AttestedData []byte `protobuf:"bytes,1,opt,name=attested_data,json=attestedData,proto3" json:"attested_data,omitempty"` + // AccessToken is a JWT signed by Azure, used to prove the identity of a + // joining node. + AccessToken string `protobuf:"bytes,2,opt,name=access_token,json=accessToken,proto3" json:"access_token,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AzureChallengeSolution) Reset() { + *x = AzureChallengeSolution{} + mi := &file_teleport_join_v1_joinservice_proto_msgTypes[25] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AzureChallengeSolution) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AzureChallengeSolution) ProtoMessage() {} + +func (x *AzureChallengeSolution) ProtoReflect() protoreflect.Message { + mi := &file_teleport_join_v1_joinservice_proto_msgTypes[25] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AzureChallengeSolution.ProtoReflect.Descriptor instead. +func (*AzureChallengeSolution) Descriptor() ([]byte, []int) { + return file_teleport_join_v1_joinservice_proto_rawDescGZIP(), []int{25} +} + +func (x *AzureChallengeSolution) GetAttestedData() []byte { + if x != nil { + return x.AttestedData + } + return nil +} + +func (x *AzureChallengeSolution) GetAccessToken() string { + if x != nil { + return x.AccessToken + } + return "" +} + // ChallengeSolution holds a solution to a challenge issued by the server. type ChallengeSolution struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -1582,6 +1744,7 @@ type ChallengeSolution struct { // *ChallengeSolution_IamChallengeSolution // *ChallengeSolution_OracleChallengeSolution // *ChallengeSolution_TpmSolution + // *ChallengeSolution_AzureChallengeSolution Payload isChallengeSolution_Payload `protobuf_oneof:"payload"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache @@ -1589,7 +1752,7 @@ type ChallengeSolution struct { func (x *ChallengeSolution) Reset() { *x = ChallengeSolution{} - mi := &file_teleport_join_v1_joinservice_proto_msgTypes[23] + mi := &file_teleport_join_v1_joinservice_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1601,7 +1764,7 @@ func (x *ChallengeSolution) String() string { func (*ChallengeSolution) ProtoMessage() {} func (x *ChallengeSolution) ProtoReflect() protoreflect.Message { - mi := &file_teleport_join_v1_joinservice_proto_msgTypes[23] + mi := &file_teleport_join_v1_joinservice_proto_msgTypes[26] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1614,7 +1777,7 @@ func (x *ChallengeSolution) ProtoReflect() protoreflect.Message { // Deprecated: Use ChallengeSolution.ProtoReflect.Descriptor instead. func (*ChallengeSolution) Descriptor() ([]byte, []int) { - return file_teleport_join_v1_joinservice_proto_rawDescGZIP(), []int{23} + return file_teleport_join_v1_joinservice_proto_rawDescGZIP(), []int{26} } func (x *ChallengeSolution) GetPayload() isChallengeSolution_Payload { @@ -1669,6 +1832,15 @@ func (x *ChallengeSolution) GetTpmSolution() *TPMSolution { return nil } +func (x *ChallengeSolution) GetAzureChallengeSolution() *AzureChallengeSolution { + if x != nil { + if x, ok := x.Payload.(*ChallengeSolution_AzureChallengeSolution); ok { + return x.AzureChallengeSolution + } + } + return nil +} + type isChallengeSolution_Payload interface { isChallengeSolution_Payload() } @@ -1693,6 +1865,10 @@ type ChallengeSolution_TpmSolution struct { TpmSolution *TPMSolution `protobuf:"bytes,5,opt,name=tpm_solution,json=tpmSolution,proto3,oneof"` } +type ChallengeSolution_AzureChallengeSolution struct { + AzureChallengeSolution *AzureChallengeSolution `protobuf:"bytes,6,opt,name=azure_challenge_solution,json=azureChallengeSolution,proto3,oneof"` +} + func (*ChallengeSolution_BoundKeypairChallengeSolution) isChallengeSolution_Payload() {} func (*ChallengeSolution_BoundKeypairRotationResponse) isChallengeSolution_Payload() {} @@ -1703,6 +1879,8 @@ func (*ChallengeSolution_OracleChallengeSolution) isChallengeSolution_Payload() func (*ChallengeSolution_TpmSolution) isChallengeSolution_Payload() {} +func (*ChallengeSolution_AzureChallengeSolution) isChallengeSolution_Payload() {} + // GivingUp should be sent by clients that fail to complete the join flow so // that the Auth service can log an informative error message. type GivingUp struct { @@ -1717,7 +1895,7 @@ type GivingUp struct { func (x *GivingUp) Reset() { *x = GivingUp{} - mi := &file_teleport_join_v1_joinservice_proto_msgTypes[24] + mi := &file_teleport_join_v1_joinservice_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1729,7 +1907,7 @@ func (x *GivingUp) String() string { func (*GivingUp) ProtoMessage() {} func (x *GivingUp) ProtoReflect() protoreflect.Message { - mi := &file_teleport_join_v1_joinservice_proto_msgTypes[24] + mi := &file_teleport_join_v1_joinservice_proto_msgTypes[27] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1742,7 +1920,7 @@ func (x *GivingUp) ProtoReflect() protoreflect.Message { // Deprecated: Use GivingUp.ProtoReflect.Descriptor instead. func (*GivingUp) Descriptor() ([]byte, []int) { - return file_teleport_join_v1_joinservice_proto_rawDescGZIP(), []int{24} + return file_teleport_join_v1_joinservice_proto_rawDescGZIP(), []int{27} } func (x *GivingUp) GetReason() GivingUp_Reason { @@ -1774,6 +1952,7 @@ type JoinRequest struct { // *JoinRequest_OidcInit // *JoinRequest_OracleInit // *JoinRequest_TpmInit + // *JoinRequest_AzureInit Payload isJoinRequest_Payload `protobuf_oneof:"payload"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache @@ -1781,7 +1960,7 @@ type JoinRequest struct { func (x *JoinRequest) Reset() { *x = JoinRequest{} - mi := &file_teleport_join_v1_joinservice_proto_msgTypes[25] + mi := &file_teleport_join_v1_joinservice_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1793,7 +1972,7 @@ func (x *JoinRequest) String() string { func (*JoinRequest) ProtoMessage() {} func (x *JoinRequest) ProtoReflect() protoreflect.Message { - mi := &file_teleport_join_v1_joinservice_proto_msgTypes[25] + mi := &file_teleport_join_v1_joinservice_proto_msgTypes[28] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1806,7 +1985,7 @@ func (x *JoinRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use JoinRequest.ProtoReflect.Descriptor instead. func (*JoinRequest) Descriptor() ([]byte, []int) { - return file_teleport_join_v1_joinservice_proto_rawDescGZIP(), []int{25} + return file_teleport_join_v1_joinservice_proto_rawDescGZIP(), []int{28} } func (x *JoinRequest) GetPayload() isJoinRequest_Payload { @@ -1906,6 +2085,15 @@ func (x *JoinRequest) GetTpmInit() *TPMInit { return nil } +func (x *JoinRequest) GetAzureInit() *AzureInit { + if x != nil { + if x, ok := x.Payload.(*JoinRequest_AzureInit); ok { + return x.AzureInit + } + } + return nil +} + type isJoinRequest_Payload interface { isJoinRequest_Payload() } @@ -1950,6 +2138,10 @@ type JoinRequest_TpmInit struct { TpmInit *TPMInit `protobuf:"bytes,10,opt,name=tpm_init,json=tpmInit,proto3,oneof"` } +type JoinRequest_AzureInit struct { + AzureInit *AzureInit `protobuf:"bytes,11,opt,name=azure_init,json=azureInit,proto3,oneof"` +} + func (*JoinRequest_ClientInit) isJoinRequest_Payload() {} func (*JoinRequest_TokenInit) isJoinRequest_Payload() {} @@ -1970,6 +2162,8 @@ func (*JoinRequest_OracleInit) isJoinRequest_Payload() {} func (*JoinRequest_TpmInit) isJoinRequest_Payload() {} +func (*JoinRequest_AzureInit) isJoinRequest_Payload() {} + // ServerInit is the first message sent from the server in response to the // ClientInit message. type ServerInit struct { @@ -1985,7 +2179,7 @@ type ServerInit struct { func (x *ServerInit) Reset() { *x = ServerInit{} - mi := &file_teleport_join_v1_joinservice_proto_msgTypes[26] + mi := &file_teleport_join_v1_joinservice_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1997,7 +2191,7 @@ func (x *ServerInit) String() string { func (*ServerInit) ProtoMessage() {} func (x *ServerInit) ProtoReflect() protoreflect.Message { - mi := &file_teleport_join_v1_joinservice_proto_msgTypes[26] + mi := &file_teleport_join_v1_joinservice_proto_msgTypes[29] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2010,7 +2204,7 @@ func (x *ServerInit) ProtoReflect() protoreflect.Message { // Deprecated: Use ServerInit.ProtoReflect.Descriptor instead. func (*ServerInit) Descriptor() ([]byte, []int) { - return file_teleport_join_v1_joinservice_proto_rawDescGZIP(), []int{26} + return file_teleport_join_v1_joinservice_proto_rawDescGZIP(), []int{29} } func (x *ServerInit) GetJoinMethod() string { @@ -2037,6 +2231,7 @@ type Challenge struct { // *Challenge_IamChallenge // *Challenge_OracleChallenge // *Challenge_TpmEncryptedCredential + // *Challenge_AzureChallenge Payload isChallenge_Payload `protobuf_oneof:"payload"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache @@ -2044,7 +2239,7 @@ type Challenge struct { func (x *Challenge) Reset() { *x = Challenge{} - mi := &file_teleport_join_v1_joinservice_proto_msgTypes[27] + mi := &file_teleport_join_v1_joinservice_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2056,7 +2251,7 @@ func (x *Challenge) String() string { func (*Challenge) ProtoMessage() {} func (x *Challenge) ProtoReflect() protoreflect.Message { - mi := &file_teleport_join_v1_joinservice_proto_msgTypes[27] + mi := &file_teleport_join_v1_joinservice_proto_msgTypes[30] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2069,7 +2264,7 @@ func (x *Challenge) ProtoReflect() protoreflect.Message { // Deprecated: Use Challenge.ProtoReflect.Descriptor instead. func (*Challenge) Descriptor() ([]byte, []int) { - return file_teleport_join_v1_joinservice_proto_rawDescGZIP(), []int{27} + return file_teleport_join_v1_joinservice_proto_rawDescGZIP(), []int{30} } func (x *Challenge) GetPayload() isChallenge_Payload { @@ -2124,6 +2319,15 @@ func (x *Challenge) GetTpmEncryptedCredential() *TPMEncryptedCredential { return nil } +func (x *Challenge) GetAzureChallenge() *AzureChallenge { + if x != nil { + if x, ok := x.Payload.(*Challenge_AzureChallenge); ok { + return x.AzureChallenge + } + } + return nil +} + type isChallenge_Payload interface { isChallenge_Payload() } @@ -2148,6 +2352,10 @@ type Challenge_TpmEncryptedCredential struct { TpmEncryptedCredential *TPMEncryptedCredential `protobuf:"bytes,5,opt,name=tpm_encrypted_credential,json=tpmEncryptedCredential,proto3,oneof"` } +type Challenge_AzureChallenge struct { + AzureChallenge *AzureChallenge `protobuf:"bytes,6,opt,name=azure_challenge,json=azureChallenge,proto3,oneof"` +} + func (*Challenge_BoundKeypairChallenge) isChallenge_Payload() {} func (*Challenge_BoundKeypairRotationRequest) isChallenge_Payload() {} @@ -2158,6 +2366,8 @@ func (*Challenge_OracleChallenge) isChallenge_Payload() {} func (*Challenge_TpmEncryptedCredential) isChallenge_Payload() {} +func (*Challenge_AzureChallenge) isChallenge_Payload() {} + // Result is the final message sent from the cluster back to the client, it // contains the result of the joining process including the assigned host ID // and issued certificates. @@ -2174,7 +2384,7 @@ type Result struct { func (x *Result) Reset() { *x = Result{} - mi := &file_teleport_join_v1_joinservice_proto_msgTypes[28] + mi := &file_teleport_join_v1_joinservice_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2186,7 +2396,7 @@ func (x *Result) String() string { func (*Result) ProtoMessage() {} func (x *Result) ProtoReflect() protoreflect.Message { - mi := &file_teleport_join_v1_joinservice_proto_msgTypes[28] + mi := &file_teleport_join_v1_joinservice_proto_msgTypes[31] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2199,7 +2409,7 @@ func (x *Result) ProtoReflect() protoreflect.Message { // Deprecated: Use Result.ProtoReflect.Descriptor instead. func (*Result) Descriptor() ([]byte, []int) { - return file_teleport_join_v1_joinservice_proto_rawDescGZIP(), []int{28} + return file_teleport_join_v1_joinservice_proto_rawDescGZIP(), []int{31} } func (x *Result) GetPayload() isResult_Payload { @@ -2262,7 +2472,7 @@ type Certificates struct { func (x *Certificates) Reset() { *x = Certificates{} - mi := &file_teleport_join_v1_joinservice_proto_msgTypes[29] + mi := &file_teleport_join_v1_joinservice_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2274,7 +2484,7 @@ func (x *Certificates) String() string { func (*Certificates) ProtoMessage() {} func (x *Certificates) ProtoReflect() protoreflect.Message { - mi := &file_teleport_join_v1_joinservice_proto_msgTypes[29] + mi := &file_teleport_join_v1_joinservice_proto_msgTypes[32] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2287,7 +2497,7 @@ func (x *Certificates) ProtoReflect() protoreflect.Message { // Deprecated: Use Certificates.ProtoReflect.Descriptor instead. func (*Certificates) Descriptor() ([]byte, []int) { - return file_teleport_join_v1_joinservice_proto_rawDescGZIP(), []int{29} + return file_teleport_join_v1_joinservice_proto_rawDescGZIP(), []int{32} } func (x *Certificates) GetTlsCert() []byte { @@ -2331,7 +2541,7 @@ type HostResult struct { func (x *HostResult) Reset() { *x = HostResult{} - mi := &file_teleport_join_v1_joinservice_proto_msgTypes[30] + mi := &file_teleport_join_v1_joinservice_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2343,7 +2553,7 @@ func (x *HostResult) String() string { func (*HostResult) ProtoMessage() {} func (x *HostResult) ProtoReflect() protoreflect.Message { - mi := &file_teleport_join_v1_joinservice_proto_msgTypes[30] + mi := &file_teleport_join_v1_joinservice_proto_msgTypes[33] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2356,7 +2566,7 @@ func (x *HostResult) ProtoReflect() protoreflect.Message { // Deprecated: Use HostResult.ProtoReflect.Descriptor instead. func (*HostResult) Descriptor() ([]byte, []int) { - return file_teleport_join_v1_joinservice_proto_rawDescGZIP(), []int{30} + return file_teleport_join_v1_joinservice_proto_rawDescGZIP(), []int{33} } func (x *HostResult) GetCertificates() *Certificates { @@ -2386,7 +2596,7 @@ type BotResult struct { func (x *BotResult) Reset() { *x = BotResult{} - mi := &file_teleport_join_v1_joinservice_proto_msgTypes[31] + mi := &file_teleport_join_v1_joinservice_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2398,7 +2608,7 @@ func (x *BotResult) String() string { func (*BotResult) ProtoMessage() {} func (x *BotResult) ProtoReflect() protoreflect.Message { - mi := &file_teleport_join_v1_joinservice_proto_msgTypes[31] + mi := &file_teleport_join_v1_joinservice_proto_msgTypes[34] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2411,7 +2621,7 @@ func (x *BotResult) ProtoReflect() protoreflect.Message { // Deprecated: Use BotResult.ProtoReflect.Descriptor instead. func (*BotResult) Descriptor() ([]byte, []int) { - return file_teleport_join_v1_joinservice_proto_rawDescGZIP(), []int{31} + return file_teleport_join_v1_joinservice_proto_rawDescGZIP(), []int{34} } func (x *BotResult) GetCertificates() *Certificates { @@ -2443,7 +2653,7 @@ type JoinResponse struct { func (x *JoinResponse) Reset() { *x = JoinResponse{} - mi := &file_teleport_join_v1_joinservice_proto_msgTypes[32] + mi := &file_teleport_join_v1_joinservice_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2455,7 +2665,7 @@ func (x *JoinResponse) String() string { func (*JoinResponse) ProtoMessage() {} func (x *JoinResponse) ProtoReflect() protoreflect.Message { - mi := &file_teleport_join_v1_joinservice_proto_msgTypes[32] + mi := &file_teleport_join_v1_joinservice_proto_msgTypes[35] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2468,7 +2678,7 @@ func (x *JoinResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use JoinResponse.ProtoReflect.Descriptor instead. func (*JoinResponse) Descriptor() ([]byte, []int) { - return file_teleport_join_v1_joinservice_proto_rawDescGZIP(), []int{32} + return file_teleport_join_v1_joinservice_proto_rawDescGZIP(), []int{35} } func (x *JoinResponse) GetPayload() isJoinResponse_Payload { @@ -2551,7 +2761,7 @@ type ClientInit_ProxySuppliedParams struct { func (x *ClientInit_ProxySuppliedParams) Reset() { *x = ClientInit_ProxySuppliedParams{} - mi := &file_teleport_join_v1_joinservice_proto_msgTypes[33] + mi := &file_teleport_join_v1_joinservice_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2563,7 +2773,7 @@ func (x *ClientInit_ProxySuppliedParams) String() string { func (*ClientInit_ProxySuppliedParams) ProtoMessage() {} func (x *ClientInit_ProxySuppliedParams) ProtoReflect() protoreflect.Message { - mi := &file_teleport_join_v1_joinservice_proto_msgTypes[33] + mi := &file_teleport_join_v1_joinservice_proto_msgTypes[36] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2695,13 +2905,21 @@ const file_teleport_join_v1_joinservice_proto_rawDesc = "" + "\x0fcredential_blob\x18\x01 \x01(\fR\x0ecredentialBlob\x12\x16\n" + "\x06secret\x18\x02 \x01(\fR\x06secret\")\n" + "\vTPMSolution\x12\x1a\n" + - "\bsolution\x18\x01 \x01(\fR\bsolution\"\xa0\x04\n" + + "\bsolution\x18\x01 \x01(\fR\bsolution\"P\n" + + "\tAzureInit\x12C\n" + + "\rclient_params\x18\x01 \x01(\v2\x1e.teleport.join.v1.ClientParamsR\fclientParams\".\n" + + "\x0eAzureChallenge\x12\x1c\n" + + "\tchallenge\x18\x01 \x01(\tR\tchallenge\"`\n" + + "\x16AzureChallengeSolution\x12#\n" + + "\rattested_data\x18\x01 \x01(\fR\fattestedData\x12!\n" + + "\faccess_token\x18\x02 \x01(\tR\vaccessToken\"\x86\x05\n" + "\x11ChallengeSolution\x12z\n" + " bound_keypair_challenge_solution\x18\x01 \x01(\v2/.teleport.join.v1.BoundKeypairChallengeSolutionH\x00R\x1dboundKeypairChallengeSolution\x12w\n" + "\x1fbound_keypair_rotation_response\x18\x02 \x01(\v2..teleport.join.v1.BoundKeypairRotationResponseH\x00R\x1cboundKeypairRotationResponse\x12^\n" + "\x16iam_challenge_solution\x18\x03 \x01(\v2&.teleport.join.v1.IAMChallengeSolutionH\x00R\x14iamChallengeSolution\x12g\n" + "\x19oracle_challenge_solution\x18\x04 \x01(\v2).teleport.join.v1.OracleChallengeSolutionH\x00R\x17oracleChallengeSolution\x12B\n" + - "\ftpm_solution\x18\x05 \x01(\v2\x1d.teleport.join.v1.TPMSolutionH\x00R\vtpmSolutionB\t\n" + + "\ftpm_solution\x18\x05 \x01(\v2\x1d.teleport.join.v1.TPMSolutionH\x00R\vtpmSolution\x12d\n" + + "\x18azure_challenge_solution\x18\x06 \x01(\v2(.teleport.join.v1.AzureChallengeSolutionH\x00R\x16azureChallengeSolutionB\t\n" + "\apayload\"\xe9\x01\n" + "\bGivingUp\x129\n" + "\x06reason\x18\x01 \x01(\x0e2!.teleport.join.v1.GivingUp.ReasonR\x06reason\x12\x10\n" + @@ -2710,7 +2928,7 @@ const file_teleport_join_v1_joinservice_proto_rawDesc = "" + "\x12REASON_UNSPECIFIED\x10\x00\x12\"\n" + "\x1eREASON_UNSUPPORTED_JOIN_METHOD\x10\x01\x12#\n" + "\x1fREASON_UNSUPPORTED_MESSAGE_TYPE\x10\x02\x12$\n" + - " REASON_CHALLENGE_SOLUTION_FAILED\x10\x03\"\x8d\x05\n" + + " REASON_CHALLENGE_SOLUTION_FAILED\x10\x03\"\xcb\x05\n" + "\vJoinRequest\x12?\n" + "\vclient_init\x18\x01 \x01(\v2\x1c.teleport.join.v1.ClientInitH\x00R\n" + "clientInit\x12<\n" + @@ -2725,19 +2943,22 @@ const file_teleport_join_v1_joinservice_proto_rawDesc = "" + "\voracle_init\x18\t \x01(\v2\x1c.teleport.join.v1.OracleInitH\x00R\n" + "oracleInit\x126\n" + "\btpm_init\x18\n" + - " \x01(\v2\x19.teleport.join.v1.TPMInitH\x00R\atpmInitB\t\n" + + " \x01(\v2\x19.teleport.join.v1.TPMInitH\x00R\atpmInit\x12<\n" + + "\n" + + "azure_init\x18\v \x01(\v2\x1b.teleport.join.v1.AzureInitH\x00R\tazureInitB\t\n" + "\apayload\"i\n" + "\n" + "ServerInit\x12\x1f\n" + "\vjoin_method\x18\x01 \x01(\tR\n" + "joinMethod\x12:\n" + - "\x19signature_algorithm_suite\x18\x02 \x01(\tR\x17signatureAlgorithmSuite\"\xec\x03\n" + + "\x19signature_algorithm_suite\x18\x02 \x01(\tR\x17signatureAlgorithmSuite\"\xb9\x04\n" + "\tChallenge\x12a\n" + "\x17bound_keypair_challenge\x18\x01 \x01(\v2'.teleport.join.v1.BoundKeypairChallengeH\x00R\x15boundKeypairChallenge\x12t\n" + "\x1ebound_keypair_rotation_request\x18\x02 \x01(\v2-.teleport.join.v1.BoundKeypairRotationRequestH\x00R\x1bboundKeypairRotationRequest\x12E\n" + "\riam_challenge\x18\x03 \x01(\v2\x1e.teleport.join.v1.IAMChallengeH\x00R\fiamChallenge\x12N\n" + "\x10oracle_challenge\x18\x04 \x01(\v2!.teleport.join.v1.OracleChallengeH\x00R\x0foracleChallenge\x12d\n" + - "\x18tpm_encrypted_credential\x18\x05 \x01(\v2(.teleport.join.v1.TPMEncryptedCredentialH\x00R\x16tpmEncryptedCredentialB\t\n" + + "\x18tpm_encrypted_credential\x18\x05 \x01(\v2(.teleport.join.v1.TPMEncryptedCredentialH\x00R\x16tpmEncryptedCredential\x12K\n" + + "\x0fazure_challenge\x18\x06 \x01(\v2 .teleport.join.v1.AzureChallengeH\x00R\x0eazureChallengeB\t\n" + "\apayload\"\x92\x01\n" + "\x06Result\x12?\n" + "\vhost_result\x18\x01 \x01(\v2\x1c.teleport.join.v1.HostResultH\x00R\n" + @@ -2780,7 +3001,7 @@ func file_teleport_join_v1_joinservice_proto_rawDescGZIP() []byte { } var file_teleport_join_v1_joinservice_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_teleport_join_v1_joinservice_proto_msgTypes = make([]protoimpl.MessageInfo, 34) +var file_teleport_join_v1_joinservice_proto_msgTypes = make([]protoimpl.MessageInfo, 37) var file_teleport_join_v1_joinservice_proto_goTypes = []any{ (GivingUp_Reason)(0), // 0: teleport.join.v1.GivingUp.Reason (*ClientInit)(nil), // 1: teleport.join.v1.ClientInit @@ -2806,24 +3027,27 @@ var file_teleport_join_v1_joinservice_proto_goTypes = []any{ (*TPMInit)(nil), // 21: teleport.join.v1.TPMInit (*TPMEncryptedCredential)(nil), // 22: teleport.join.v1.TPMEncryptedCredential (*TPMSolution)(nil), // 23: teleport.join.v1.TPMSolution - (*ChallengeSolution)(nil), // 24: teleport.join.v1.ChallengeSolution - (*GivingUp)(nil), // 25: teleport.join.v1.GivingUp - (*JoinRequest)(nil), // 26: teleport.join.v1.JoinRequest - (*ServerInit)(nil), // 27: teleport.join.v1.ServerInit - (*Challenge)(nil), // 28: teleport.join.v1.Challenge - (*Result)(nil), // 29: teleport.join.v1.Result - (*Certificates)(nil), // 30: teleport.join.v1.Certificates - (*HostResult)(nil), // 31: teleport.join.v1.HostResult - (*BotResult)(nil), // 32: teleport.join.v1.BotResult - (*JoinResponse)(nil), // 33: teleport.join.v1.JoinResponse - (*ClientInit_ProxySuppliedParams)(nil), // 34: teleport.join.v1.ClientInit.ProxySuppliedParams - (*timestamppb.Timestamp)(nil), // 35: google.protobuf.Timestamp + (*AzureInit)(nil), // 24: teleport.join.v1.AzureInit + (*AzureChallenge)(nil), // 25: teleport.join.v1.AzureChallenge + (*AzureChallengeSolution)(nil), // 26: teleport.join.v1.AzureChallengeSolution + (*ChallengeSolution)(nil), // 27: teleport.join.v1.ChallengeSolution + (*GivingUp)(nil), // 28: teleport.join.v1.GivingUp + (*JoinRequest)(nil), // 29: teleport.join.v1.JoinRequest + (*ServerInit)(nil), // 30: teleport.join.v1.ServerInit + (*Challenge)(nil), // 31: teleport.join.v1.Challenge + (*Result)(nil), // 32: teleport.join.v1.Result + (*Certificates)(nil), // 33: teleport.join.v1.Certificates + (*HostResult)(nil), // 34: teleport.join.v1.HostResult + (*BotResult)(nil), // 35: teleport.join.v1.BotResult + (*JoinResponse)(nil), // 36: teleport.join.v1.JoinResponse + (*ClientInit_ProxySuppliedParams)(nil), // 37: teleport.join.v1.ClientInit.ProxySuppliedParams + (*timestamppb.Timestamp)(nil), // 38: google.protobuf.Timestamp } var file_teleport_join_v1_joinservice_proto_depIdxs = []int32{ - 34, // 0: teleport.join.v1.ClientInit.proxy_supplied_parameters:type_name -> teleport.join.v1.ClientInit.ProxySuppliedParams + 37, // 0: teleport.join.v1.ClientInit.proxy_supplied_parameters:type_name -> teleport.join.v1.ClientInit.ProxySuppliedParams 2, // 1: teleport.join.v1.HostParams.public_keys:type_name -> teleport.join.v1.PublicKeys 2, // 2: teleport.join.v1.BotParams.public_keys:type_name -> teleport.join.v1.PublicKeys - 35, // 3: teleport.join.v1.BotParams.expires:type_name -> google.protobuf.Timestamp + 38, // 3: teleport.join.v1.BotParams.expires:type_name -> google.protobuf.Timestamp 3, // 4: teleport.join.v1.ClientParams.host_params:type_name -> teleport.join.v1.HostParams 4, // 5: teleport.join.v1.ClientParams.bot_params:type_name -> teleport.join.v1.BotParams 5, // 6: teleport.join.v1.TokenInit.client_params:type_name -> teleport.join.v1.ClientParams @@ -2833,42 +3057,46 @@ var file_teleport_join_v1_joinservice_proto_depIdxs = []int32{ 5, // 10: teleport.join.v1.EC2Init.client_params:type_name -> teleport.join.v1.ClientParams 5, // 11: teleport.join.v1.OracleInit.client_params:type_name -> teleport.join.v1.ClientParams 5, // 12: teleport.join.v1.TPMInit.client_params:type_name -> teleport.join.v1.ClientParams - 10, // 13: teleport.join.v1.ChallengeSolution.bound_keypair_challenge_solution:type_name -> teleport.join.v1.BoundKeypairChallengeSolution - 12, // 14: teleport.join.v1.ChallengeSolution.bound_keypair_rotation_response:type_name -> teleport.join.v1.BoundKeypairRotationResponse - 16, // 15: teleport.join.v1.ChallengeSolution.iam_challenge_solution:type_name -> teleport.join.v1.IAMChallengeSolution - 20, // 16: teleport.join.v1.ChallengeSolution.oracle_challenge_solution:type_name -> teleport.join.v1.OracleChallengeSolution - 23, // 17: teleport.join.v1.ChallengeSolution.tpm_solution:type_name -> teleport.join.v1.TPMSolution - 0, // 18: teleport.join.v1.GivingUp.reason:type_name -> teleport.join.v1.GivingUp.Reason - 1, // 19: teleport.join.v1.JoinRequest.client_init:type_name -> teleport.join.v1.ClientInit - 6, // 20: teleport.join.v1.JoinRequest.token_init:type_name -> teleport.join.v1.TokenInit - 8, // 21: teleport.join.v1.JoinRequest.bound_keypair_init:type_name -> teleport.join.v1.BoundKeypairInit - 24, // 22: teleport.join.v1.JoinRequest.solution:type_name -> teleport.join.v1.ChallengeSolution - 14, // 23: teleport.join.v1.JoinRequest.iam_init:type_name -> teleport.join.v1.IAMInit - 25, // 24: teleport.join.v1.JoinRequest.giving_up:type_name -> teleport.join.v1.GivingUp - 17, // 25: teleport.join.v1.JoinRequest.ec2_init:type_name -> teleport.join.v1.EC2Init - 7, // 26: teleport.join.v1.JoinRequest.oidc_init:type_name -> teleport.join.v1.OIDCInit - 18, // 27: teleport.join.v1.JoinRequest.oracle_init:type_name -> teleport.join.v1.OracleInit - 21, // 28: teleport.join.v1.JoinRequest.tpm_init:type_name -> teleport.join.v1.TPMInit - 9, // 29: teleport.join.v1.Challenge.bound_keypair_challenge:type_name -> teleport.join.v1.BoundKeypairChallenge - 11, // 30: teleport.join.v1.Challenge.bound_keypair_rotation_request:type_name -> teleport.join.v1.BoundKeypairRotationRequest - 15, // 31: teleport.join.v1.Challenge.iam_challenge:type_name -> teleport.join.v1.IAMChallenge - 19, // 32: teleport.join.v1.Challenge.oracle_challenge:type_name -> teleport.join.v1.OracleChallenge - 22, // 33: teleport.join.v1.Challenge.tpm_encrypted_credential:type_name -> teleport.join.v1.TPMEncryptedCredential - 31, // 34: teleport.join.v1.Result.host_result:type_name -> teleport.join.v1.HostResult - 32, // 35: teleport.join.v1.Result.bot_result:type_name -> teleport.join.v1.BotResult - 30, // 36: teleport.join.v1.HostResult.certificates:type_name -> teleport.join.v1.Certificates - 30, // 37: teleport.join.v1.BotResult.certificates:type_name -> teleport.join.v1.Certificates - 13, // 38: teleport.join.v1.BotResult.bound_keypair_result:type_name -> teleport.join.v1.BoundKeypairResult - 27, // 39: teleport.join.v1.JoinResponse.init:type_name -> teleport.join.v1.ServerInit - 28, // 40: teleport.join.v1.JoinResponse.challenge:type_name -> teleport.join.v1.Challenge - 29, // 41: teleport.join.v1.JoinResponse.result:type_name -> teleport.join.v1.Result - 26, // 42: teleport.join.v1.JoinService.Join:input_type -> teleport.join.v1.JoinRequest - 33, // 43: teleport.join.v1.JoinService.Join:output_type -> teleport.join.v1.JoinResponse - 43, // [43:44] is the sub-list for method output_type - 42, // [42:43] is the sub-list for method input_type - 42, // [42:42] is the sub-list for extension type_name - 42, // [42:42] is the sub-list for extension extendee - 0, // [0:42] is the sub-list for field type_name + 5, // 13: teleport.join.v1.AzureInit.client_params:type_name -> teleport.join.v1.ClientParams + 10, // 14: teleport.join.v1.ChallengeSolution.bound_keypair_challenge_solution:type_name -> teleport.join.v1.BoundKeypairChallengeSolution + 12, // 15: teleport.join.v1.ChallengeSolution.bound_keypair_rotation_response:type_name -> teleport.join.v1.BoundKeypairRotationResponse + 16, // 16: teleport.join.v1.ChallengeSolution.iam_challenge_solution:type_name -> teleport.join.v1.IAMChallengeSolution + 20, // 17: teleport.join.v1.ChallengeSolution.oracle_challenge_solution:type_name -> teleport.join.v1.OracleChallengeSolution + 23, // 18: teleport.join.v1.ChallengeSolution.tpm_solution:type_name -> teleport.join.v1.TPMSolution + 26, // 19: teleport.join.v1.ChallengeSolution.azure_challenge_solution:type_name -> teleport.join.v1.AzureChallengeSolution + 0, // 20: teleport.join.v1.GivingUp.reason:type_name -> teleport.join.v1.GivingUp.Reason + 1, // 21: teleport.join.v1.JoinRequest.client_init:type_name -> teleport.join.v1.ClientInit + 6, // 22: teleport.join.v1.JoinRequest.token_init:type_name -> teleport.join.v1.TokenInit + 8, // 23: teleport.join.v1.JoinRequest.bound_keypair_init:type_name -> teleport.join.v1.BoundKeypairInit + 27, // 24: teleport.join.v1.JoinRequest.solution:type_name -> teleport.join.v1.ChallengeSolution + 14, // 25: teleport.join.v1.JoinRequest.iam_init:type_name -> teleport.join.v1.IAMInit + 28, // 26: teleport.join.v1.JoinRequest.giving_up:type_name -> teleport.join.v1.GivingUp + 17, // 27: teleport.join.v1.JoinRequest.ec2_init:type_name -> teleport.join.v1.EC2Init + 7, // 28: teleport.join.v1.JoinRequest.oidc_init:type_name -> teleport.join.v1.OIDCInit + 18, // 29: teleport.join.v1.JoinRequest.oracle_init:type_name -> teleport.join.v1.OracleInit + 21, // 30: teleport.join.v1.JoinRequest.tpm_init:type_name -> teleport.join.v1.TPMInit + 24, // 31: teleport.join.v1.JoinRequest.azure_init:type_name -> teleport.join.v1.AzureInit + 9, // 32: teleport.join.v1.Challenge.bound_keypair_challenge:type_name -> teleport.join.v1.BoundKeypairChallenge + 11, // 33: teleport.join.v1.Challenge.bound_keypair_rotation_request:type_name -> teleport.join.v1.BoundKeypairRotationRequest + 15, // 34: teleport.join.v1.Challenge.iam_challenge:type_name -> teleport.join.v1.IAMChallenge + 19, // 35: teleport.join.v1.Challenge.oracle_challenge:type_name -> teleport.join.v1.OracleChallenge + 22, // 36: teleport.join.v1.Challenge.tpm_encrypted_credential:type_name -> teleport.join.v1.TPMEncryptedCredential + 25, // 37: teleport.join.v1.Challenge.azure_challenge:type_name -> teleport.join.v1.AzureChallenge + 34, // 38: teleport.join.v1.Result.host_result:type_name -> teleport.join.v1.HostResult + 35, // 39: teleport.join.v1.Result.bot_result:type_name -> teleport.join.v1.BotResult + 33, // 40: teleport.join.v1.HostResult.certificates:type_name -> teleport.join.v1.Certificates + 33, // 41: teleport.join.v1.BotResult.certificates:type_name -> teleport.join.v1.Certificates + 13, // 42: teleport.join.v1.BotResult.bound_keypair_result:type_name -> teleport.join.v1.BoundKeypairResult + 30, // 43: teleport.join.v1.JoinResponse.init:type_name -> teleport.join.v1.ServerInit + 31, // 44: teleport.join.v1.JoinResponse.challenge:type_name -> teleport.join.v1.Challenge + 32, // 45: teleport.join.v1.JoinResponse.result:type_name -> teleport.join.v1.Result + 29, // 46: teleport.join.v1.JoinService.Join:input_type -> teleport.join.v1.JoinRequest + 36, // 47: teleport.join.v1.JoinService.Join:output_type -> teleport.join.v1.JoinResponse + 47, // [47:48] is the sub-list for method output_type + 46, // [46:47] is the sub-list for method input_type + 46, // [46:46] is the sub-list for extension type_name + 46, // [46:46] is the sub-list for extension extendee + 0, // [0:46] is the sub-list for field type_name } func init() { file_teleport_join_v1_joinservice_proto_init() } @@ -2886,14 +3114,15 @@ func file_teleport_join_v1_joinservice_proto_init() { (*TPMInit_EkCert)(nil), (*TPMInit_EkKey)(nil), } - file_teleport_join_v1_joinservice_proto_msgTypes[23].OneofWrappers = []any{ + file_teleport_join_v1_joinservice_proto_msgTypes[26].OneofWrappers = []any{ (*ChallengeSolution_BoundKeypairChallengeSolution)(nil), (*ChallengeSolution_BoundKeypairRotationResponse)(nil), (*ChallengeSolution_IamChallengeSolution)(nil), (*ChallengeSolution_OracleChallengeSolution)(nil), (*ChallengeSolution_TpmSolution)(nil), + (*ChallengeSolution_AzureChallengeSolution)(nil), } - file_teleport_join_v1_joinservice_proto_msgTypes[25].OneofWrappers = []any{ + file_teleport_join_v1_joinservice_proto_msgTypes[28].OneofWrappers = []any{ (*JoinRequest_ClientInit)(nil), (*JoinRequest_TokenInit)(nil), (*JoinRequest_BoundKeypairInit)(nil), @@ -2904,20 +3133,22 @@ func file_teleport_join_v1_joinservice_proto_init() { (*JoinRequest_OidcInit)(nil), (*JoinRequest_OracleInit)(nil), (*JoinRequest_TpmInit)(nil), + (*JoinRequest_AzureInit)(nil), } - file_teleport_join_v1_joinservice_proto_msgTypes[27].OneofWrappers = []any{ + file_teleport_join_v1_joinservice_proto_msgTypes[30].OneofWrappers = []any{ (*Challenge_BoundKeypairChallenge)(nil), (*Challenge_BoundKeypairRotationRequest)(nil), (*Challenge_IamChallenge)(nil), (*Challenge_OracleChallenge)(nil), (*Challenge_TpmEncryptedCredential)(nil), + (*Challenge_AzureChallenge)(nil), } - file_teleport_join_v1_joinservice_proto_msgTypes[28].OneofWrappers = []any{ + file_teleport_join_v1_joinservice_proto_msgTypes[31].OneofWrappers = []any{ (*Result_HostResult)(nil), (*Result_BotResult)(nil), } - file_teleport_join_v1_joinservice_proto_msgTypes[31].OneofWrappers = []any{} - file_teleport_join_v1_joinservice_proto_msgTypes[32].OneofWrappers = []any{ + file_teleport_join_v1_joinservice_proto_msgTypes[34].OneofWrappers = []any{} + file_teleport_join_v1_joinservice_proto_msgTypes[35].OneofWrappers = []any{ (*JoinResponse_Init)(nil), (*JoinResponse_Challenge)(nil), (*JoinResponse_Result)(nil), @@ -2928,7 +3159,7 @@ func file_teleport_join_v1_joinservice_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_teleport_join_v1_joinservice_proto_rawDesc), len(file_teleport_join_v1_joinservice_proto_rawDesc)), NumEnums: 1, - NumMessages: 34, + NumMessages: 37, NumExtensions: 0, NumServices: 1, }, diff --git a/api/proto/teleport/join/v1/joinservice.proto b/api/proto/teleport/join/v1/joinservice.proto index bab3ed7df8429..2408193bb5346 100644 --- a/api/proto/teleport/join/v1/joinservice.proto +++ b/api/proto/teleport/join/v1/joinservice.proto @@ -349,6 +349,41 @@ message TPMSolution { bytes solution = 1; } +// AzureInit is sent from the client in response to the ServerInit message for +// the Azure join method. +// +// The Azure method join flow is: +// 1. client->server: ClientInit +// 2. client<-server: ServerInit +// 3. client->server: AzureInit +// 4. client<-server: AzureChallenge +// 5. client->server: AzureChallengeSolution +// 6. client<-server: Result +message AzureInit { + // ClientParams holds parameters for the specific type of client trying to join. + ClientParams client_params = 1; +} + +// AzureChallenge is sent from the server in response to the AzureInit message from the client. +// The client is expected to respond with a AzureChallengeSolution. +message AzureChallenge { + // Challenge is a a crypto-random string that should be included by the + // client in the challenge response message. + string challenge = 1; +} + +// AzureChallengeSolution must be sent from the client in response to the +// AzureChallenge message. +message AzureChallengeSolution { + // AttestedData is a signed JSON document from an Azure VM's attested data + // metadata endpoint used to prove the identity of a joining node. It must + // include the challenge string as the nonce. + bytes attested_data = 1; + // AccessToken is a JWT signed by Azure, used to prove the identity of a + // joining node. + string access_token = 2; +} + // ChallengeSolution holds a solution to a challenge issued by the server. message ChallengeSolution { oneof payload { @@ -357,6 +392,7 @@ message ChallengeSolution { IAMChallengeSolution iam_challenge_solution = 3; OracleChallengeSolution oracle_challenge_solution = 4; TPMSolution tpm_solution = 5; + AzureChallengeSolution azure_challenge_solution = 6; } } @@ -396,6 +432,7 @@ message JoinRequest { OIDCInit oidc_init = 8; OracleInit oracle_init = 9; TPMInit tpm_init = 10; + AzureInit azure_init = 11; } } @@ -417,6 +454,7 @@ message Challenge { IAMChallenge iam_challenge = 3; OracleChallenge oracle_challenge = 4; TPMEncryptedCredential tpm_encrypted_credential = 5; + AzureChallenge azure_challenge = 6; } } diff --git a/lib/join/internal/messages/messages.go b/lib/join/internal/messages/messages.go index 26f9392aa2b20..436cfe2014a6e 100644 --- a/lib/join/internal/messages/messages.go +++ b/lib/join/internal/messages/messages.go @@ -468,6 +468,48 @@ type TPMSolution struct { Solution []byte } +// AzureInit is sent from the client in response to the ServerInit message for +// the Azure join method. +// +// The Azure method join flow is: +// 1. client->server: ClientInit +// 2. client<-server: ServerInit +// 3. client->server: AzureInit +// 4. client<-server: AzureChallenge +// 5. client->server: AzureChallengeSolution +// 6. client<-server: Result +type AzureInit struct { + embedRequest + + // ClientParams holds parameters for the specific type of client trying to join. + ClientParams ClientParams +} + +// AzureChallenge is sent from the server in response to the AzureInit message +// from the client. The client is expected to respond with a +// AzureChallengeSolution. +type AzureChallenge struct { + embedResponse + + // Challenge is a a crypto-random string that should be included by the + // client in the AzureChallengeSolution message. + Challenge string +} + +// AzureChallenge message. +// AzureChallengeSolution must be sent from the client in response to the +type AzureChallengeSolution struct { + embedRequest + + // AttestedData is a signed JSON document from an Azure VM's attested data + // metadata endpoint used to prove the identity of a joining node. It must + // include the challenge string as the nonce. + AttestedData []byte + // AccessToken is a JWT signed by Azure, used to prove the identity of a + // joining node. + AccessToken string +} + // Response is implemented by all join response messages. type Response interface { isResponse() diff --git a/lib/join/joinv1/messages.go b/lib/join/joinv1/messages.go index b884dbab4a12b..a4649a366f975 100644 --- a/lib/join/joinv1/messages.go +++ b/lib/join/joinv1/messages.go @@ -44,6 +44,8 @@ func requestToMessage(req *joinv1.JoinRequest) (messages.Request, error) { return oracleInitToMessage(msg.OracleInit) case *joinv1.JoinRequest_TpmInit: return tpmInitToMessage(msg.TpmInit) + case *joinv1.JoinRequest_AzureInit: + return azureInitToMessage(msg.AzureInit) case *joinv1.JoinRequest_Solution: return challengeSolutionToMessage(msg.Solution) case *joinv1.JoinRequest_GivingUp: @@ -133,11 +135,22 @@ func requestFromMessage(msg messages.Request) (*joinv1.JoinRequest, error) { TpmInit: tpmInit, }, }, nil + case *messages.AzureInit: + azureInit, err := azureInitFromMessage(typedMsg) + if err != nil { + return nil, trace.Wrap(err) + } + return &joinv1.JoinRequest{ + Payload: &joinv1.JoinRequest_AzureInit{ + AzureInit: azureInit, + }, + }, nil case *messages.BoundKeypairChallengeSolution, *messages.BoundKeypairRotationResponse, *messages.IAMChallengeSolution, *messages.OracleChallengeSolution, - *messages.TPMSolution: + *messages.TPMSolution, + *messages.AzureChallengeSolution: solution, err := challengeSolutionFromMessage(typedMsg) if err != nil { return nil, trace.Wrap(err) @@ -307,6 +320,8 @@ func challengeSolutionToMessage(req *joinv1.ChallengeSolution) (messages.Request return oracleChallengeSolutionToMessage(payload.OracleChallengeSolution), nil case *joinv1.ChallengeSolution_TpmSolution: return tpmSolutionToMessage(payload.TpmSolution), nil + case *joinv1.ChallengeSolution_AzureChallengeSolution: + return azureChallengeSolutionToMessage(payload.AzureChallengeSolution), nil default: return nil, trace.BadParameter("unrecognized challenge solution message type %T", payload) } @@ -344,6 +359,12 @@ func challengeSolutionFromMessage(msg messages.Request) (*joinv1.ChallengeSoluti TpmSolution: tpmSolutionFromMessage(typedMsg), }, }, nil + case *messages.AzureChallengeSolution: + return &joinv1.ChallengeSolution{ + Payload: &joinv1.ChallengeSolution_AzureChallengeSolution{ + AzureChallengeSolution: azureChallengeSolutionFromMessage(typedMsg), + }, + }, nil default: return nil, trace.BadParameter("unrecognized challenge solution message type %T", msg) } @@ -377,7 +398,8 @@ func responseFromMessage(msg messages.Response) (*joinv1.JoinResponse, error) { *messages.BoundKeypairRotationRequest, *messages.IAMChallenge, *messages.OracleChallenge, - *messages.TPMEncryptedCredential: + *messages.TPMEncryptedCredential, + *messages.AzureChallenge: challenge, err := challengeFromMessage(msg) if err != nil { return nil, trace.Wrap(err) @@ -442,6 +464,8 @@ func challengeToMessage(resp *joinv1.Challenge) (messages.Response, error) { return oracleChallengeToMessage(payload.OracleChallenge), nil case *joinv1.Challenge_TpmEncryptedCredential: return tpmEncryptedCredentialToMessage(payload.TpmEncryptedCredential), nil + case *joinv1.Challenge_AzureChallenge: + return azureChallengeToMessage(payload.AzureChallenge), nil default: return nil, trace.BadParameter("unrecognized challenge payload type %T", payload) } @@ -479,6 +503,12 @@ func challengeFromMessage(resp messages.Response) (*joinv1.Challenge, error) { TpmEncryptedCredential: tpmEncryptedCredentialFromMessage(msg), }, }, nil + case *messages.AzureChallenge: + return &joinv1.Challenge{ + Payload: &joinv1.Challenge_AzureChallenge{ + AzureChallenge: azureChallengeFromMessage(msg), + }, + }, nil default: return nil, trace.BadParameter("unrecognized challenge message type %T", msg) } diff --git a/lib/join/joinv1/messages_azure.go b/lib/join/joinv1/messages_azure.go new file mode 100644 index 0000000000000..b28778b210b89 --- /dev/null +++ b/lib/join/joinv1/messages_azure.go @@ -0,0 +1,70 @@ +// 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 joinv1 + +import ( + "github.com/gravitational/trace" + + joinv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/join/v1" + "github.com/gravitational/teleport/lib/join/internal/messages" +) + +func azureInitToMessage(req *joinv1.AzureInit) (*messages.AzureInit, error) { + clientParams, err := clientParamsToMessage(req.ClientParams) + if err != nil { + return nil, trace.Wrap(err) + } + return &messages.AzureInit{ + ClientParams: clientParams, + }, nil +} + +func azureInitFromMessage(msg *messages.AzureInit) (*joinv1.AzureInit, error) { + clientParams, err := clientParamsFromMessage(msg.ClientParams) + if err != nil { + return nil, trace.Wrap(err) + } + return &joinv1.AzureInit{ + ClientParams: clientParams, + }, nil +} + +func azureChallengeToMessage(req *joinv1.AzureChallenge) *messages.AzureChallenge { + return &messages.AzureChallenge{ + Challenge: req.Challenge, + } +} + +func azureChallengeFromMessage(msg *messages.AzureChallenge) *joinv1.AzureChallenge { + return &joinv1.AzureChallenge{ + Challenge: msg.Challenge, + } +} + +func azureChallengeSolutionToMessage(req *joinv1.AzureChallengeSolution) *messages.AzureChallengeSolution { + return &messages.AzureChallengeSolution{ + AttestedData: req.AttestedData, + AccessToken: req.AccessToken, + } +} + +func azureChallengeSolutionFromMessage(msg *messages.AzureChallengeSolution) *joinv1.AzureChallengeSolution { + return &joinv1.AzureChallengeSolution{ + AttestedData: msg.AttestedData, + AccessToken: msg.AccessToken, + } +} diff --git a/lib/join/joinv1/messages_test.go b/lib/join/joinv1/messages_test.go index 334e025509511..3b0999ab091f4 100644 --- a/lib/join/joinv1/messages_test.go +++ b/lib/join/joinv1/messages_test.go @@ -88,6 +88,12 @@ func TestRequestToMessage(t *testing.T) { Payload: &joinv1.JoinRequest_TpmInit{}, }, }, + { + desc: "empty AzureInit", + req: &joinv1.JoinRequest{ + Payload: &joinv1.JoinRequest_AzureInit{}, + }, + }, { desc: "empty HostParams", req: &joinv1.JoinRequest{ @@ -168,6 +174,16 @@ func TestRequestToMessage(t *testing.T) { }, }, }, + { + desc: "empty AzureSolution", + req: &joinv1.JoinRequest{ + Payload: &joinv1.JoinRequest_Solution{ + Solution: &joinv1.ChallengeSolution{ + Payload: &joinv1.ChallengeSolution_AzureChallengeSolution{}, + }, + }, + }, + }, { desc: "empty GivingUp", req: &joinv1.JoinRequest{ From 88e394365edb8e5b906c4662ad0117e59bff9c25 Mon Sep 17 00:00:00 2001 From: Nic Klaassen Date: Wed, 19 Nov 2025 13:51:56 -0800 Subject: [PATCH 2/2] add intermediate CA --- .../go/teleport/join/v1/joinservice.pb.go | 19 +++++++++++++++---- api/proto/teleport/join/v1/joinservice.proto | 5 ++++- lib/join/internal/messages/messages.go | 3 +++ lib/join/joinv1/messages_azure.go | 10 ++++++---- 4 files changed, 28 insertions(+), 9 deletions(-) diff --git a/api/gen/proto/go/teleport/join/v1/joinservice.pb.go b/api/gen/proto/go/teleport/join/v1/joinservice.pb.go index fac060e57af67..316e07272a5ca 100644 --- a/api/gen/proto/go/teleport/join/v1/joinservice.pb.go +++ b/api/gen/proto/go/teleport/join/v1/joinservice.pb.go @@ -1683,9 +1683,12 @@ type AzureChallengeSolution struct { // metadata endpoint used to prove the identity of a joining node. It must // include the challenge string as the nonce. AttestedData []byte `protobuf:"bytes,1,opt,name=attested_data,json=attestedData,proto3" json:"attested_data,omitempty"` + // Intermediate encodes the intermediate CAs that issued the leaf certificate + // used to sign the attested data document, in x509 DER format. + Intermediate []byte `protobuf:"bytes,2,opt,name=intermediate,proto3" json:"intermediate,omitempty"` // AccessToken is a JWT signed by Azure, used to prove the identity of a // joining node. - AccessToken string `protobuf:"bytes,2,opt,name=access_token,json=accessToken,proto3" json:"access_token,omitempty"` + AccessToken string `protobuf:"bytes,3,opt,name=access_token,json=accessToken,proto3" json:"access_token,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -1727,6 +1730,13 @@ func (x *AzureChallengeSolution) GetAttestedData() []byte { return nil } +func (x *AzureChallengeSolution) GetIntermediate() []byte { + if x != nil { + return x.Intermediate + } + return nil +} + func (x *AzureChallengeSolution) GetAccessToken() string { if x != nil { return x.AccessToken @@ -2909,10 +2919,11 @@ const file_teleport_join_v1_joinservice_proto_rawDesc = "" + "\tAzureInit\x12C\n" + "\rclient_params\x18\x01 \x01(\v2\x1e.teleport.join.v1.ClientParamsR\fclientParams\".\n" + "\x0eAzureChallenge\x12\x1c\n" + - "\tchallenge\x18\x01 \x01(\tR\tchallenge\"`\n" + + "\tchallenge\x18\x01 \x01(\tR\tchallenge\"\x84\x01\n" + "\x16AzureChallengeSolution\x12#\n" + - "\rattested_data\x18\x01 \x01(\fR\fattestedData\x12!\n" + - "\faccess_token\x18\x02 \x01(\tR\vaccessToken\"\x86\x05\n" + + "\rattested_data\x18\x01 \x01(\fR\fattestedData\x12\"\n" + + "\fintermediate\x18\x02 \x01(\fR\fintermediate\x12!\n" + + "\faccess_token\x18\x03 \x01(\tR\vaccessToken\"\x86\x05\n" + "\x11ChallengeSolution\x12z\n" + " bound_keypair_challenge_solution\x18\x01 \x01(\v2/.teleport.join.v1.BoundKeypairChallengeSolutionH\x00R\x1dboundKeypairChallengeSolution\x12w\n" + "\x1fbound_keypair_rotation_response\x18\x02 \x01(\v2..teleport.join.v1.BoundKeypairRotationResponseH\x00R\x1cboundKeypairRotationResponse\x12^\n" + diff --git a/api/proto/teleport/join/v1/joinservice.proto b/api/proto/teleport/join/v1/joinservice.proto index 2408193bb5346..2bc620a2ac6ac 100644 --- a/api/proto/teleport/join/v1/joinservice.proto +++ b/api/proto/teleport/join/v1/joinservice.proto @@ -379,9 +379,12 @@ message AzureChallengeSolution { // metadata endpoint used to prove the identity of a joining node. It must // include the challenge string as the nonce. bytes attested_data = 1; + // Intermediate encodes the intermediate CAs that issued the leaf certificate + // used to sign the attested data document, in x509 DER format. + bytes intermediate = 2; // AccessToken is a JWT signed by Azure, used to prove the identity of a // joining node. - string access_token = 2; + string access_token = 3; } // ChallengeSolution holds a solution to a challenge issued by the server. diff --git a/lib/join/internal/messages/messages.go b/lib/join/internal/messages/messages.go index 436cfe2014a6e..00444ab14be4c 100644 --- a/lib/join/internal/messages/messages.go +++ b/lib/join/internal/messages/messages.go @@ -505,6 +505,9 @@ type AzureChallengeSolution struct { // metadata endpoint used to prove the identity of a joining node. It must // include the challenge string as the nonce. AttestedData []byte + // Intermediate encodes the intermediate CAs that issued the leaf certificate + // used to sign the attested data document, in x509 DER format. + Intermediate []byte // AccessToken is a JWT signed by Azure, used to prove the identity of a // joining node. AccessToken string diff --git a/lib/join/joinv1/messages_azure.go b/lib/join/joinv1/messages_azure.go index b28778b210b89..8fa1872e6b8c4 100644 --- a/lib/join/joinv1/messages_azure.go +++ b/lib/join/joinv1/messages_azure.go @@ -24,7 +24,7 @@ import ( ) func azureInitToMessage(req *joinv1.AzureInit) (*messages.AzureInit, error) { - clientParams, err := clientParamsToMessage(req.ClientParams) + clientParams, err := clientParamsToMessage(req.GetClientParams()) if err != nil { return nil, trace.Wrap(err) } @@ -45,7 +45,7 @@ func azureInitFromMessage(msg *messages.AzureInit) (*joinv1.AzureInit, error) { func azureChallengeToMessage(req *joinv1.AzureChallenge) *messages.AzureChallenge { return &messages.AzureChallenge{ - Challenge: req.Challenge, + Challenge: req.GetChallenge(), } } @@ -57,14 +57,16 @@ func azureChallengeFromMessage(msg *messages.AzureChallenge) *joinv1.AzureChalle func azureChallengeSolutionToMessage(req *joinv1.AzureChallengeSolution) *messages.AzureChallengeSolution { return &messages.AzureChallengeSolution{ - AttestedData: req.AttestedData, - AccessToken: req.AccessToken, + AttestedData: req.GetAttestedData(), + Intermediate: req.GetIntermediate(), + AccessToken: req.GetAccessToken(), } } func azureChallengeSolutionFromMessage(msg *messages.AzureChallengeSolution) *joinv1.AzureChallengeSolution { return &joinv1.AzureChallengeSolution{ AttestedData: msg.AttestedData, + Intermediate: msg.Intermediate, AccessToken: msg.AccessToken, } }