diff --git a/Makefile b/Makefile index 493f20dda..5ea33563f 100644 --- a/Makefile +++ b/Makefile @@ -142,7 +142,8 @@ protobuild: @protoc-go-inject-tag -input=./internal/gen/controller/api/services/auth_method_service.pb.go @protoc-go-inject-tag -input=./sdk/pbs/controller/api/resources/authmethods/auth_method.pb.go @protoc-go-inject-tag -input=./sdk/pbs/controller/api/resources/scopes/scope.pb.go - + @protoc-go-inject-tag -input=./internal/gen/controller/servers/services/session_service.pb.go + @protoc-go-inject-tag -input=./sdk/pbs/controller/api/resources/targets/target.pb.go # these protos, services and openapi artifacts are purely for testing purposes @protoc-go-inject-tag -input=./internal/gen/testing/event/event.pb.go diff --git a/internal/gen/controller/servers/services/session_service.pb.go b/internal/gen/controller/servers/services/session_service.pb.go index 3927dd38e..0159d05e0 100644 --- a/internal/gen/controller/servers/services/session_service.pb.go +++ b/internal/gen/controller/servers/services/session_service.pb.go @@ -28,10 +28,10 @@ type LookupSessionRequest struct { unknownFields protoimpl.UnknownFields // The session ID from the client - SessionId string `protobuf:"bytes,10,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` + SessionId string `protobuf:"bytes,10,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty" class:"public"` // @gotags: `class:"public"` // The name of the requesting worker, used for filtering to ensure this // worker is allowed to handle this session. - ServerId string `protobuf:"bytes,20,opt,name=server_id,json=serverId,proto3" json:"server_id,omitempty"` + ServerId string `protobuf:"bytes,20,opt,name=server_id,json=serverId,proto3" json:"server_id,omitempty" class:"public"` // @gotags: `class:"public"` } func (x *LookupSessionRequest) Reset() { @@ -88,17 +88,17 @@ type LookupSessionResponse struct { unknownFields protoimpl.UnknownFields Authorization *targets.SessionAuthorizationData `protobuf:"bytes,10,opt,name=authorization,proto3" json:"authorization,omitempty"` - TofuToken string `protobuf:"bytes,20,opt,name=tofu_token,json=tofuToken,proto3" json:"tofu_token,omitempty"` - Version uint32 `protobuf:"varint,30,opt,name=version,proto3" json:"version,omitempty"` - Endpoint string `protobuf:"bytes,40,opt,name=endpoint,proto3" json:"endpoint,omitempty"` - Expiration *timestamppb.Timestamp `protobuf:"bytes,50,opt,name=expiration,proto3" json:"expiration,omitempty"` - Status SESSIONSTATUS `protobuf:"varint,60,opt,name=status,proto3,enum=controller.servers.services.v1.SESSIONSTATUS" json:"status,omitempty"` - ConnectionLimit int32 `protobuf:"varint,70,opt,name=connection_limit,json=connectionLimit,proto3" json:"connection_limit,omitempty"` - ConnectionsLeft int32 `protobuf:"varint,80,opt,name=connections_left,json=connectionsLeft,proto3" json:"connections_left,omitempty"` - HostId string `protobuf:"bytes,90,opt,name=host_id,json=hostId,proto3" json:"host_id,omitempty"` - HostSetId string `protobuf:"bytes,100,opt,name=host_set_id,json=hostSetId,proto3" json:"host_set_id,omitempty"` - TargetId string `protobuf:"bytes,110,opt,name=target_id,json=targetId,proto3" json:"target_id,omitempty"` - UserId string `protobuf:"bytes,120,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + TofuToken string `protobuf:"bytes,20,opt,name=tofu_token,json=tofuToken,proto3" json:"tofu_token,omitempty" class:"secret"` // @gotags: `class:"secret"` + Version uint32 `protobuf:"varint,30,opt,name=version,proto3" json:"version,omitempty" class:"public"` // @gotags: `class:"public"` + Endpoint string `protobuf:"bytes,40,opt,name=endpoint,proto3" json:"endpoint,omitempty" class:"public"` // @gotags: `class:"public"` + Expiration *timestamppb.Timestamp `protobuf:"bytes,50,opt,name=expiration,proto3" json:"expiration,omitempty" class:"public"` // @gotags: `class:"public"` + Status SESSIONSTATUS `protobuf:"varint,60,opt,name=status,proto3,enum=controller.servers.services.v1.SESSIONSTATUS" json:"status,omitempty" class:"public"` // @gotags: `class:"public"` + ConnectionLimit int32 `protobuf:"varint,70,opt,name=connection_limit,json=connectionLimit,proto3" json:"connection_limit,omitempty" class:"public"` // @gotags: `class:"public"` + ConnectionsLeft int32 `protobuf:"varint,80,opt,name=connections_left,json=connectionsLeft,proto3" json:"connections_left,omitempty" class:"public"` // @gotags: `class:"public"` + HostId string `protobuf:"bytes,90,opt,name=host_id,json=hostId,proto3" json:"host_id,omitempty" class:"public"` // @gotags: `class:"public"` + HostSetId string `protobuf:"bytes,100,opt,name=host_set_id,json=hostSetId,proto3" json:"host_set_id,omitempty" class:"public"` // @gotags: `class:"public"` + TargetId string `protobuf:"bytes,110,opt,name=target_id,json=targetId,proto3" json:"target_id,omitempty" class:"public"` // @gotags: `class:"public"` + UserId string `protobuf:"bytes,120,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty" class:"public"` // @gotags: `class:"public"` } func (x *LookupSessionResponse) Reset() { @@ -222,11 +222,11 @@ type ActivateSessionRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - SessionId string `protobuf:"bytes,10,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` - TofuToken string `protobuf:"bytes,20,opt,name=tofu_token,json=tofuToken,proto3" json:"tofu_token,omitempty"` - Version uint32 `protobuf:"varint,30,opt,name=version,proto3" json:"version,omitempty"` - WorkerId string `protobuf:"bytes,40,opt,name=worker_id,json=workerId,proto3" json:"worker_id,omitempty"` - Status SESSIONSTATUS `protobuf:"varint,50,opt,name=status,proto3,enum=controller.servers.services.v1.SESSIONSTATUS" json:"status,omitempty"` + SessionId string `protobuf:"bytes,10,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty" class:"public"` // @gotags: `class:"public"` + TofuToken string `protobuf:"bytes,20,opt,name=tofu_token,json=tofuToken,proto3" json:"tofu_token,omitempty" class:"secret"` // @gotags: `class:"secret"` + Version uint32 `protobuf:"varint,30,opt,name=version,proto3" json:"version,omitempty" class:"public"` // @gotags: `class:"public"` + WorkerId string `protobuf:"bytes,40,opt,name=worker_id,json=workerId,proto3" json:"worker_id,omitempty" class:"public"` // @gotags: `class:"public"` + Status SESSIONSTATUS `protobuf:"varint,50,opt,name=status,proto3,enum=controller.servers.services.v1.SESSIONSTATUS" json:"status,omitempty" class:"public"` // @gotags: `class:"public"` } func (x *ActivateSessionRequest) Reset() { @@ -301,7 +301,7 @@ type ActivateSessionResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Status SESSIONSTATUS `protobuf:"varint,10,opt,name=status,proto3,enum=controller.servers.services.v1.SESSIONSTATUS" json:"status,omitempty"` + Status SESSIONSTATUS `protobuf:"varint,10,opt,name=status,proto3,enum=controller.servers.services.v1.SESSIONSTATUS" json:"status,omitempty" class:"public"` // @gotags: `class:"public"` } func (x *ActivateSessionResponse) Reset() { @@ -348,7 +348,7 @@ type CancelSessionRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - SessionId string `protobuf:"bytes,10,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` + SessionId string `protobuf:"bytes,10,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty" class:"public"` // @gotags: `class:"public"` } func (x *CancelSessionRequest) Reset() { @@ -395,7 +395,7 @@ type CancelSessionResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Status SESSIONSTATUS `protobuf:"varint,10,opt,name=status,proto3,enum=controller.servers.services.v1.SESSIONSTATUS" json:"status,omitempty"` + Status SESSIONSTATUS `protobuf:"varint,10,opt,name=status,proto3,enum=controller.servers.services.v1.SESSIONSTATUS" json:"status,omitempty" class:"public"` // @gotags: `class:"public"` } func (x *CancelSessionResponse) Reset() { @@ -442,8 +442,8 @@ type AuthorizeConnectionRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - SessionId string `protobuf:"bytes,10,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` - WorkerId string `protobuf:"bytes,20,opt,name=worker_id,json=workerId,proto3" json:"worker_id,omitempty"` + SessionId string `protobuf:"bytes,10,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty" class:"public"` // @gotags: `class:"public"` + WorkerId string `protobuf:"bytes,20,opt,name=worker_id,json=workerId,proto3" json:"worker_id,omitempty" class:"public"` // @gotags: `class:"public"` } func (x *AuthorizeConnectionRequest) Reset() { @@ -497,9 +497,9 @@ type AuthorizeConnectionResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - ConnectionId string `protobuf:"bytes,10,opt,name=connection_id,json=connectionId,proto3" json:"connection_id,omitempty"` - Status CONNECTIONSTATUS `protobuf:"varint,20,opt,name=status,proto3,enum=controller.servers.services.v1.CONNECTIONSTATUS" json:"status,omitempty"` - ConnectionsLeft int32 `protobuf:"varint,30,opt,name=connections_left,json=connectionsLeft,proto3" json:"connections_left,omitempty"` + ConnectionId string `protobuf:"bytes,10,opt,name=connection_id,json=connectionId,proto3" json:"connection_id,omitempty" class:"public"` // @gotags: `class:"public"` + Status CONNECTIONSTATUS `protobuf:"varint,20,opt,name=status,proto3,enum=controller.servers.services.v1.CONNECTIONSTATUS" json:"status,omitempty" class:"public"` // @gotags: `class:"public"` + ConnectionsLeft int32 `protobuf:"varint,30,opt,name=connections_left,json=connectionsLeft,proto3" json:"connections_left,omitempty" class:"public"` // @gotags: `class:"public"` } func (x *AuthorizeConnectionResponse) Reset() { @@ -560,12 +560,12 @@ type ConnectConnectionRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - ConnectionId string `protobuf:"bytes,10,opt,name=connection_id,json=connectionId,proto3" json:"connection_id,omitempty"` - ClientTcpAddress string `protobuf:"bytes,20,opt,name=client_tcp_address,json=clientTcpAddress,proto3" json:"client_tcp_address,omitempty"` - ClientTcpPort uint32 `protobuf:"varint,30,opt,name=client_tcp_port,json=clientTcpPort,proto3" json:"client_tcp_port,omitempty"` - EndpointTcpAddress string `protobuf:"bytes,40,opt,name=endpoint_tcp_address,json=endpointTcpAddress,proto3" json:"endpoint_tcp_address,omitempty"` - EndpointTcpPort uint32 `protobuf:"varint,50,opt,name=endpoint_tcp_port,json=endpointTcpPort,proto3" json:"endpoint_tcp_port,omitempty"` - Type string `protobuf:"bytes,60,opt,name=type,proto3" json:"type,omitempty"` + ConnectionId string `protobuf:"bytes,10,opt,name=connection_id,json=connectionId,proto3" json:"connection_id,omitempty" class:"public"` // @gotags: `class:"public"` + ClientTcpAddress string `protobuf:"bytes,20,opt,name=client_tcp_address,json=clientTcpAddress,proto3" json:"client_tcp_address,omitempty" class:"public"` // @gotags: `class:"public"` + ClientTcpPort uint32 `protobuf:"varint,30,opt,name=client_tcp_port,json=clientTcpPort,proto3" json:"client_tcp_port,omitempty" class:"public"` // @gotags: `class:"public"` + EndpointTcpAddress string `protobuf:"bytes,40,opt,name=endpoint_tcp_address,json=endpointTcpAddress,proto3" json:"endpoint_tcp_address,omitempty" class:"public"` // @gotags: `class:"public"` + EndpointTcpPort uint32 `protobuf:"varint,50,opt,name=endpoint_tcp_port,json=endpointTcpPort,proto3" json:"endpoint_tcp_port,omitempty" class:"public"` // @gotags: `class:"public"` + Type string `protobuf:"bytes,60,opt,name=type,proto3" json:"type,omitempty" class:"public"` // @gotags: `class:"public"` } func (x *ConnectConnectionRequest) Reset() { @@ -647,7 +647,7 @@ type ConnectConnectionResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Status CONNECTIONSTATUS `protobuf:"varint,10,opt,name=status,proto3,enum=controller.servers.services.v1.CONNECTIONSTATUS" json:"status,omitempty"` + Status CONNECTIONSTATUS `protobuf:"varint,10,opt,name=status,proto3,enum=controller.servers.services.v1.CONNECTIONSTATUS" json:"status,omitempty" class:"public"` // @gotags: `class:"public"` } func (x *ConnectConnectionResponse) Reset() { @@ -694,10 +694,10 @@ type CloseConnectionRequestData struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - ConnectionId string `protobuf:"bytes,10,opt,name=connection_id,json=connectionId,proto3" json:"connection_id,omitempty"` - BytesUp uint64 `protobuf:"varint,20,opt,name=bytes_up,json=bytesUp,proto3" json:"bytes_up,omitempty"` - BytesDown uint64 `protobuf:"varint,30,opt,name=bytes_down,json=bytesDown,proto3" json:"bytes_down,omitempty"` - Reason string `protobuf:"bytes,40,opt,name=reason,proto3" json:"reason,omitempty"` + ConnectionId string `protobuf:"bytes,10,opt,name=connection_id,json=connectionId,proto3" json:"connection_id,omitempty" class:"public"` // @gotags: `class:"public"` + BytesUp uint64 `protobuf:"varint,20,opt,name=bytes_up,json=bytesUp,proto3" json:"bytes_up,omitempty" class:"public"` // @gotags: `class:"public"` + BytesDown uint64 `protobuf:"varint,30,opt,name=bytes_down,json=bytesDown,proto3" json:"bytes_down,omitempty" class:"public"` // @gotags: `class:"public"` + Reason string `protobuf:"bytes,40,opt,name=reason,proto3" json:"reason,omitempty" class:"public"` // @gotags: `class:"public"` } func (x *CloseConnectionRequestData) Reset() { @@ -765,7 +765,7 @@ type CloseConnectionRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - CloseRequestData []*CloseConnectionRequestData `protobuf:"bytes,10,rep,name=close_request_data,json=closeRequestData,proto3" json:"close_request_data,omitempty"` + CloseRequestData []*CloseConnectionRequestData `protobuf:"bytes,10,rep,name=close_request_data,json=closeRequestData,proto3" json:"close_request_data,omitempty" class:"public"` // @gotags: `class:"public"` } func (x *CloseConnectionRequest) Reset() { @@ -813,7 +813,7 @@ type CloseConnectionResponseData struct { unknownFields protoimpl.UnknownFields ConnectionId string `protobuf:"bytes,10,opt,name=connection_id,json=connectionId,proto3" json:"connection_id,omitempty"` - Status CONNECTIONSTATUS `protobuf:"varint,20,opt,name=status,proto3,enum=controller.servers.services.v1.CONNECTIONSTATUS" json:"status,omitempty"` + Status CONNECTIONSTATUS `protobuf:"varint,20,opt,name=status,proto3,enum=controller.servers.services.v1.CONNECTIONSTATUS" json:"status,omitempty" class:"public"` // @gotags: `class:"public"` } func (x *CloseConnectionResponseData) Reset() { @@ -867,7 +867,7 @@ type CloseConnectionResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - CloseResponseData []*CloseConnectionResponseData `protobuf:"bytes,10,rep,name=close_response_data,json=closeResponseData,proto3" json:"close_response_data,omitempty"` + CloseResponseData []*CloseConnectionResponseData `protobuf:"bytes,10,rep,name=close_response_data,json=closeResponseData,proto3" json:"close_response_data,omitempty" class:"public"` // @gotags: `class:"public"` } func (x *CloseConnectionResponse) Reset() { diff --git a/internal/observability/event/cloudevents_formatter_node.go b/internal/observability/event/cloudevents_formatter_node.go index 78434830d..a96a1cbf8 100644 --- a/internal/observability/event/cloudevents_formatter_node.go +++ b/internal/observability/event/cloudevents_formatter_node.go @@ -67,10 +67,28 @@ func newCloudEventsFormatterFilter(source *url.URL, format cloudevents.Format, o n.deny = append(n.deny, f) } } + defaultDenyFilters, err := defaultCloudEventsDenyFilters() + if err != nil { + return nil, err + } + n.deny = append(n.deny, defaultDenyFilters...) n.Predicate = newPredicate(n.allow, n.deny) return &n, nil } +func defaultCloudEventsDenyFilters() ([]*filter, error) { + const ( + op = "event.defaultCloudEventsDenyFilters" + // denyWorkStatusEvents is a default filter for worker to controller API status requests + denyWorkStatusEvents = `"/Data/RequestInfo/Method" contains "ServerCoordinationService/Status"` + ) + f, err := newFilter(denyWorkStatusEvents) + if err != nil { + return nil, fmt.Errorf("%s: unable to create deny filter for worker status events '%s': %w", op, denyWorkStatusEvents, err) + } + return []*filter{f}, nil +} + // Rotate supports rotating the filter's wrapper. No options are currently // supported. func (f *cloudEventsFormatterFilter) Rotate(w wrapping.Wrapper, _ ...Option) error { diff --git a/internal/observability/event/cloudevents_formatter_node_test.go b/internal/observability/event/cloudevents_formatter_node_test.go index fd8a1903d..ba2fd42a2 100644 --- a/internal/observability/event/cloudevents_formatter_node_test.go +++ b/internal/observability/event/cloudevents_formatter_node_test.go @@ -130,7 +130,12 @@ func Test_newCloudEventsFormatterFilter(t *testing.T) { for _, f := range got.allow { assert.Contains(tt.wantAllow, f.raw) } - assert.Len(got.deny, len(tt.wantDeny)) + assert.Len(got.deny, len(tt.wantDeny)+1) // +1 since there's always a default deny + defs, err := defaultCloudEventsDenyFilters() + require.NoError(err) + for _, f := range defs { + tt.wantDeny = append(tt.wantDeny, f.raw) + } for _, f := range got.deny { assert.Contains(tt.wantDeny, f.raw) } diff --git a/internal/observability/event/hclog_formatter_node.go b/internal/observability/event/hclog_formatter_node.go index 8704f6128..1b51d844d 100644 --- a/internal/observability/event/hclog_formatter_node.go +++ b/internal/observability/event/hclog_formatter_node.go @@ -66,11 +66,29 @@ func newHclogFormatterFilter(jsonFormat bool, opt ...Option) (*hclogFormatterFil n.deny = append(n.deny, f) } } + defaultDenyFilters, err := defaultHclogEventsDenyFilters() + if err != nil { + return nil, err + } + n.deny = append(n.deny, defaultDenyFilters...) n.predicate = newPredicate(n.allow, n.deny) return &n, nil } +func defaultHclogEventsDenyFilters() ([]*filter, error) { + const ( + op = "event.defaultHclogEventsDenyFilters" + // denyWorkStatusEvents is a default filter for worker to controller API status requests + denyWorkStatusEvents = `"/RequestInfo/Method" contains "ServerCoordinationService/Status"` + ) + f, err := newFilter(denyWorkStatusEvents) + if err != nil { + return nil, fmt.Errorf("%s: unable to create deny filter for worker status events '%s': %w", op, denyWorkStatusEvents, err) + } + return []*filter{f}, nil +} + // Rotate supports rotating the filter's wrapper. No options are currently // supported. func (f *hclogFormatterFilter) Rotate(w wrapping.Wrapper, _ ...Option) error { diff --git a/internal/observability/event/hclog_formatter_node_test.go b/internal/observability/event/hclog_formatter_node_test.go index cf7ca1a4d..aea34f13e 100644 --- a/internal/observability/event/hclog_formatter_node_test.go +++ b/internal/observability/event/hclog_formatter_node_test.go @@ -387,7 +387,12 @@ func Test_newHclogFormatterFilter(t *testing.T) { for _, f := range got.allow { assert.Contains(tt.wantAllow, f.raw) } - assert.Len(got.deny, len(tt.wantDeny)) + assert.Len(got.deny, len(tt.wantDeny)+1) // +1 since there's always a default deny + defs, err := defaultHclogEventsDenyFilters() + require.NoError(err) + for _, f := range defs { + tt.wantDeny = append(tt.wantDeny, f.raw) + } for _, f := range got.deny { assert.Contains(tt.wantDeny, f.raw) } diff --git a/internal/proto/local/controller/api/resources/targets/v1/target.proto b/internal/proto/local/controller/api/resources/targets/v1/target.proto index d52173522..58d5a1ced 100644 --- a/internal/proto/local/controller/api/resources/targets/v1/target.proto +++ b/internal/proto/local/controller/api/resources/targets/v1/target.proto @@ -11,230 +11,234 @@ import "controller/api/resources/scopes/v1/scope.proto"; import "controller/custom_options/v1/options.proto"; message HostSource { - // Output only. The ID of the Host Set. - string id = 10; + // Output only. The ID of the Host Set. + string id = 10; - // Output only. The Host Catalog to which this Host Source belongs. - string host_catalog_id = 20 [json_name="host_catalog_id"]; + // Output only. The Host Catalog to which this Host Source belongs. + string host_catalog_id = 20 [json_name = "host_catalog_id"]; } message HostSet { - // Output only. The ID of the Host Set. - string id = 10; + // Output only. The ID of the Host Set. + string id = 10; - // Output only. The Host Catalog to which this Host Set belongs. - string host_catalog_id = 20 [json_name="host_catalog_id"]; + // Output only. The Host Catalog to which this Host Set belongs. + string host_catalog_id = 20 [json_name = "host_catalog_id"]; } message CredentialSource { - // The ID of the Credential. May be empty if the credential is dynamically generated from a library. - string id = 10; + // The ID of the Credential. May be empty if the credential is dynamically generated from a library. + string id = 10; - // Output only. The name of the Credential source. - string name = 20; + // Output only. The name of the Credential source. + string name = 20; - // Output only. The description of the Credential source. - string description = 30; + // Output only. The description of the Credential source. + string description = 30; - // Output only. The Credential Store to which this Credential source belongs. - string credential_store_id = 40 [json_name="credential_store_id"]; + // Output only. The Credential Store to which this Credential source belongs. + string credential_store_id = 40 [json_name = "credential_store_id"]; - // Output only. The type of the credential source (e.g. "vault"; not the type of the credential itself). - string type = 60; + // Output only. The type of the credential source (e.g. "vault"; not the type of the credential itself). + string type = 60; } message CredentialLibrary { - // The ID of the Credential Library. - string id = 10; + // The ID of the Credential Library. + string id = 10; - // Output only. The name of the Credential Library. - string name = 20; + // Output only. The name of the Credential Library. + string name = 20; - // Output only. The description of the Credential Library. - string description = 30; + // Output only. The description of the Credential Library. + string description = 30; - // Output only. The Credential Store to which this Credential Library belongs. - string credential_store_id = 40 [json_name="credential_store_id"]; + // Output only. The Credential Store to which this Credential Library belongs. + string credential_store_id = 40 [json_name = "credential_store_id"]; - // Output only. The type of the credential library. - string type = 60; + // Output only. The type of the credential library. + string type = 60; } // The actual secret for a session credential. message SessionSecret { - // Output only. The base64-encoded value representing the raw bytes from the - // credential provider. - string raw = 10; + // Output only. The base64-encoded value representing the raw bytes from the + // credential provider. + string raw = 10; - // Output only. The decoded raw string, if a JSON object. - google.protobuf.Struct decoded = 20; + // Output only. The decoded raw string, if a JSON object. + google.protobuf.Struct decoded = 20; } // Credential information for a session. message SessionCredential { - // Output only. The credential source information. - CredentialSource credential_source = 1; + // Output only. The credential source information. + CredentialSource credential_source = 1; - // Output only. The library which generated this credential. Deprecated: use credential_source instead. - CredentialLibrary credential_library = 10 [deprecated = true]; + // Output only. The library which generated this credential. Deprecated: use credential_source instead. + CredentialLibrary credential_library = 10 [deprecated = true]; - // Output only. The secret of this credential base64 encoded. - SessionSecret secret = 20; + // Output only. The secret of this credential base64 encoded. + SessionSecret secret = 20; } // Target contains all fields related to a Target resource message Target { - // Output only. The ID of the resource. - string id = 10; + // Output only. The ID of the resource. + string id = 10; - // The Scope of of this resource. This must be defined for creation of this resource, but is otherwise output only. - string scope_id = 20 [json_name="scope_id"]; + // The Scope of of this resource. This must be defined for creation of this resource, but is otherwise output only. + string scope_id = 20 [json_name = "scope_id"]; - // Output only. Scope information for this resource. - resources.scopes.v1.ScopeInfo scope = 30; - - // Required name for identification purposes. - google.protobuf.StringValue name = 40 [(custom_options.v1.generate_sdk_option) = true, (custom_options.v1.mask_mapping) = {this:"name" that: "name"}]; + // Output only. Scope information for this resource. + resources.scopes.v1.ScopeInfo scope = 30; - // Optional user-set description for identification purposes. - google.protobuf.StringValue description = 50 [(custom_options.v1.generate_sdk_option) = true, (custom_options.v1.mask_mapping) = {this:"description" that: "description"}]; + // Required name for identification purposes. + google.protobuf.StringValue name = 40 [(custom_options.v1.generate_sdk_option) = true, (custom_options.v1.mask_mapping) = { this: "name" that: "name" }]; - // Output only. The time this resource was created. - google.protobuf.Timestamp created_time = 60 [json_name="created_time"]; + // Optional user-set description for identification purposes. + google.protobuf.StringValue description = 50 [(custom_options.v1.generate_sdk_option) = true, (custom_options.v1.mask_mapping) = { this: "description" that: "description" }]; - // Output only. The time this resource was last updated. - google.protobuf.Timestamp updated_time = 70 [json_name="updated_time"]; + // Output only. The time this resource was created. + google.protobuf.Timestamp created_time = 60 [json_name = "created_time"]; - // Version is used in mutation requests, after the initial creation, to ensure this resource has not changed. - // The mutation will fail if the version does not match the latest known good version. - uint32 version = 80; + // Output only. The time this resource was last updated. + google.protobuf.Timestamp updated_time = 70 [json_name = "updated_time"]; - // The type of the Target. - string type = 90; + // Version is used in mutation requests, after the initial creation, to ensure this resource has not changed. + // The mutation will fail if the version does not match the latest known good version. + uint32 version = 80; - // Output only. The IDs of the Host Sets associated with this Target. - repeated string host_set_ids = 100 [json_name="host_set_ids"]; + // The type of the Target. + string type = 90; - // Output only. The Host Sets associated with this Target. - repeated HostSet host_sets = 110 [json_name="host_sets"]; + // Output only. The IDs of the Host Sets associated with this Target. + repeated string host_set_ids = 100 [json_name = "host_set_ids"]; - // Output only. The IDs of the Host Sources associated with this Target. - repeated string host_source_ids = 420 [json_name="host_source_ids"]; + // Output only. The Host Sets associated with this Target. + repeated HostSet host_sets = 110 [json_name = "host_sets"]; - // Output only. The Host Sources associated with this Target. - repeated HostSource host_sources = 430 [json_name="host_sources"]; + // Output only. The IDs of the Host Sources associated with this Target. + repeated string host_source_ids = 420 [json_name = "host_source_ids"]; - // Maximum total lifetime of a created Session, in seconds. - google.protobuf.UInt32Value session_max_seconds = 120 [json_name="session_max_seconds", (custom_options.v1.generate_sdk_option) = true, (custom_options.v1.mask_mapping) = {this: "session_max_seconds" that: "SessionMaxSeconds"}]; + // Output only. The Host Sources associated with this Target. + repeated HostSource host_sources = 430 [json_name = "host_sources"]; - // Maximum number of connections allowed in a Session. Unlimited is indicated by the value -1. - google.protobuf.Int32Value session_connection_limit = 130 [json_name="session_connection_limit", (custom_options.v1.generate_sdk_option) = true, (custom_options.v1.mask_mapping) = {this: "session_connection_limit" that: "SessionConnectionLimit"}]; + // Maximum total lifetime of a created Session, in seconds. + google.protobuf.UInt32Value session_max_seconds = 120 + [json_name = "session_max_seconds", (custom_options.v1.generate_sdk_option) = true, (custom_options.v1.mask_mapping) = { this: "session_max_seconds" that: "SessionMaxSeconds" }]; - // Optional boolean expression to filter the workers that are allowed to satisfy this request. - google.protobuf.StringValue worker_filter = 140 [json_name="worker_filter", (custom_options.v1.generate_sdk_option) = true, (custom_options.v1.mask_mapping) = {this: "worker_filter" that: "WorkerFilter"}]; + // Maximum number of connections allowed in a Session. Unlimited is indicated by the value -1. + google.protobuf.Int32Value session_connection_limit = 130 + [json_name = "session_connection_limit", (custom_options.v1.generate_sdk_option) = true, (custom_options.v1.mask_mapping) = { this: "session_connection_limit" that: "SessionConnectionLimit" }]; - // Output only. The IDs of the application credential library ids associated with this Target. Deprecated: use application_credential_source_ids instead. - repeated string application_credential_library_ids = 150 [json_name="application_credential_library_ids", deprecated = true]; - // Output only. The application credential libraries associated with this Target. Deprecated: use application_credential_sources instead. - repeated CredentialLibrary application_credential_libraries = 180 [json_name="application_credential_libraries", deprecated = true]; + // Optional boolean expression to filter the workers that are allowed to satisfy this request. + google.protobuf.StringValue worker_filter = 140 + [json_name = "worker_filter", (custom_options.v1.generate_sdk_option) = true, (custom_options.v1.mask_mapping) = { this: "worker_filter" that: "WorkerFilter" }]; - // Output only. The IDs of the application credential source ids associated with this Target. - repeated string application_credential_source_ids = 400 [json_name="application_credential_source_ids"]; - // Output only. The application credential sources associated with this Target. - repeated CredentialSource application_credential_sources = 410 [json_name="application_credential_sources"]; + // Output only. The IDs of the application credential library ids associated with this Target. Deprecated: use application_credential_source_ids instead. + repeated string application_credential_library_ids = 150 [json_name = "application_credential_library_ids", deprecated = true]; + // Output only. The application credential libraries associated with this Target. Deprecated: use application_credential_sources instead. + repeated CredentialLibrary application_credential_libraries = 180 [json_name = "application_credential_libraries", deprecated = true]; - // Output only. The IDs of the egress credential source ids associated with this Target. - repeated string egress_credential_source_ids = 500 [json_name="egress_credential_source_ids"]; - // Output only. The egress credential sources associated with this Target. - repeated CredentialSource egress_credential_sources = 510 [json_name="egress_credential_sources"]; + // Output only. The IDs of the application credential source ids associated with this Target. + repeated string application_credential_source_ids = 400 [json_name = "application_credential_source_ids"]; + // Output only. The application credential sources associated with this Target. + repeated CredentialSource application_credential_sources = 410 [json_name = "application_credential_sources"]; - // The attributes that are applicable for the specific Target. - google.protobuf.Struct attributes = 200 [(custom_options.v1.generate_sdk_option) = true]; + // Output only. The IDs of the egress credential source ids associated with this Target. + repeated string egress_credential_source_ids = 500 [json_name = "egress_credential_source_ids"]; + // Output only. The egress credential sources associated with this Target. + repeated CredentialSource egress_credential_sources = 510 [json_name = "egress_credential_sources"]; - // Output only. The available actions on this resource for this user. - repeated string authorized_actions = 300 [json_name="authorized_actions"]; + // The attributes that are applicable for the specific Target. + google.protobuf.Struct attributes = 200 [(custom_options.v1.generate_sdk_option) = true]; + + // Output only. The available actions on this resource for this user. + repeated string authorized_actions = 300 [json_name = "authorized_actions"]; } // TcpTargetAttributes contains attributes relevant to Targets of type "tcp" message TcpTargetAttributes { - // The default TCP port that will be used when connecting to the endpoint unless overridden by a Host Set or Host. - google.protobuf.UInt32Value default_port = 10 [json_name="default_port", (custom_options.v1.generate_sdk_option) = true, (custom_options.v1.mask_mapping) = {this: "attributes.default_port" that: "DefaultPort"}]; + // The default TCP port that will be used when connecting to the endpoint unless overridden by a Host Set or Host. + google.protobuf.UInt32Value default_port = 10 + [json_name = "default_port", (custom_options.v1.generate_sdk_option) = true, (custom_options.v1.mask_mapping) = { this: "attributes.default_port" that: "DefaultPort" }]; } // WorkerInfo contains information about workers, returned in to the client in SessionAuthorization message WorkerInfo { - // Output only. The address of the worker. - string address = 10; + // Output only. The address of the worker. + string address = 10; // @gotags: `class:"public"` } // SessionAuthorizationData contains the fields needed by the proxy command to connect to a worker. It is marshaled inside the SessionAuthorization message. message SessionAuthorizationData { - // Output only. The ID of the session. - string session_id = 10 [json_name="session_id"]; + // Output only. The ID of the session. + string session_id = 10 [json_name = "session_id"]; // @gotags: `class:"public"` - // Output only. The ID of the Target authorizing this session. - string target_id = 20 [json_name="target_id"]; + // Output only. The ID of the Target authorizing this session. + string target_id = 20 [json_name = "target_id"]; // @gotags: `class:"public"` - // Output only. Scope information for this the Target that authorized this session. - resources.scopes.v1.ScopeInfo scope = 30; + // Output only. Scope information for this the Target that authorized this session. + resources.scopes.v1.ScopeInfo scope = 30; - // Output only. The time this resource was created. - google.protobuf.Timestamp created_time = 40 [json_name="created_time"]; + // Output only. The time this resource was created. + google.protobuf.Timestamp created_time = 40 [json_name = "created_time"]; // @gotags: `class:"public"` - // Output only. Type of the session (e.g. tcp, ssh, etc.). - string type = 80; + // Output only. Type of the session (e.g. tcp, ssh, etc.). + string type = 80; // @gotags: `class:"public"` - // Output only. The connection limit being applied to this session. -1 means unlimited. This is not actually enforced on the client side but it provides for better listener handling by including it. - int32 connection_limit = 90 [json_name="connection_limit"]; + // Output only. The connection limit being applied to this session. -1 means unlimited. This is not actually enforced on the client side but it provides for better listener handling by including it. + int32 connection_limit = 90 [json_name = "connection_limit"]; - // Output only. The certificate to use when connecting. Raw DER bytes. - bytes certificate = 120; + // Output only. The certificate to use when connecting. Raw DER bytes. + bytes certificate = 120; // @gotags: `class:"secret"` - // Output only. The private key to use when connecting. We are using Ed25519, so this is purely raw bytes, no marshaling. - bytes private_key = 130 [json_name="private_key"]; + // Output only. The private key to use when connecting. We are using Ed25519, so this is purely raw bytes, no marshaling. + bytes private_key = 130 [json_name = "private_key"]; // @gotags: `class:"secret"` - // Output only. The host ID...not used for security purposes, but for some special command handling (e.g. ssh host key aliasing). - string host_id = 140; + // Output only. The host ID...not used for security purposes, but for some special command handling (e.g. ssh host key aliasing). + string host_id = 140; // @gotags: `class:"public"` - // Output only. The endpoint, for some special command handling. - string endpoint = 141; + // Output only. The endpoint, for some special command handling. + string endpoint = 141; // @gotags: `class:"public"` - // Output only. Worker information. The first worker in the array should be prioritized. - repeated WorkerInfo worker_info = 150 [json_name="worker_info"]; + // Output only. Worker information. The first worker in the array should be prioritized. + repeated WorkerInfo worker_info = 150 [json_name = "worker_info"]; } // SessionAuthorization contains all fields related to authorization for a Session. It's in the Targets package because it's returned by a Target's authorize action. message SessionAuthorization { - // Output only. The ID of the Session. - string session_id = 10 [json_name="session_id"]; + // Output only. The ID of the Session. + string session_id = 10 [json_name = "session_id"]; // @gotags: `class:"public"` - // Output only. The ID of the Target authorizing this Session. - string target_id = 20 [json_name="target_id"]; + // Output only. The ID of the Target authorizing this Session. + string target_id = 20 [json_name = "target_id"]; // @gotags: `class:"public"` - // Output only. Scope information for this resource. - resources.scopes.v1.ScopeInfo scope = 30; + // Output only. Scope information for this resource. + resources.scopes.v1.ScopeInfo scope = 30; - // Output only. The time this resource was created. - google.protobuf.Timestamp created_time = 40 [json_name="created_time"]; + // Output only. The time this resource was created. + google.protobuf.Timestamp created_time = 40 [json_name = "created_time"]; // @gotags: `class:"public"` - // Output only. The User for which this Session was authorized. - string user_id = 50 [json_name="user_id"]; + // Output only. The User for which this Session was authorized. + string user_id = 50 [json_name = "user_id"]; // @gotags: `class:"public"` - // Output only. The Host Set containing the Host being used for this Session. - string host_set_id = 60 [json_name="host_set_id"]; + // Output only. The Host Set containing the Host being used for this Session. + string host_set_id = 60 [json_name = "host_set_id"]; // @gotags: `class:"public"` - // Output only. The Host whose address is being used as the endpoint for this Session. - string host_id = 70 [json_name="host_id"]; + // Output only. The Host whose address is being used as the endpoint for this Session. + string host_id = 70 [json_name = "host_id"]; // @gotags: `class:"public"` - // Output only. Type of the Session (e.g. tcp, ssh, etc.). - string type = 80; + // Output only. Type of the Session (e.g. tcp, ssh, etc.). + string type = 80; // @gotags: `class:"public"` - // Output only. The marshaled SessionAuthorizationData message containing all information that the proxy needs. - string authorization_token = 90 [json_name="authorization_token"]; + // Output only. The marshaled SessionAuthorizationData message containing all information that the proxy needs. + string authorization_token = 90 [json_name = "authorization_token"]; // @gotags: `class:"private"` - // Output only. The endpoint address that the worker will connect to, useful for setting TLS parameters. - string endpoint = 100; + // Output only. The endpoint address that the worker will connect to, useful for setting TLS parameters. + string endpoint = 100; // @gotags: `class:"public"` - // Output only. The credentials for this session. - repeated SessionCredential credentials = 110 [json_name="credentials"]; + // Output only. The credentials for this session. + repeated SessionCredential credentials = 110 [json_name = "credentials"]; } diff --git a/internal/proto/local/controller/servers/services/v1/session_service.proto b/internal/proto/local/controller/servers/services/v1/session_service.proto index 01a594344..8a297697f 100644 --- a/internal/proto/local/controller/servers/services/v1/session_service.proto +++ b/internal/proto/local/controller/servers/services/v1/session_service.proto @@ -9,111 +9,111 @@ import "controller/api/resources/targets/v1/target.proto"; import "controller/servers/services/v1/server_coordination_service.proto"; service SessionService { - // GetSession allows a worker to retrieve session information from the - // controller. - rpc LookupSession(LookupSessionRequest) returns (LookupSessionResponse) {} - - // ActivateSession allows a worker to activate a session on a controller. - rpc ActivateSession(ActivateSessionRequest) returns (ActivateSessionResponse) {} + // GetSession allows a worker to retrieve session information from the + // controller. + rpc LookupSession(LookupSessionRequest) returns (LookupSessionResponse) {} - // CancelSession allows a worker to request that the controller cancel a session. - rpc CancelSession(CancelSessionRequest) returns (CancelSessionResponse) {} + // ActivateSession allows a worker to activate a session on a controller. + rpc ActivateSession(ActivateSessionRequest) returns (ActivateSessionResponse) {} - // AuthorizeConnection allows a worker to authorize a connection on a controller. - rpc AuthorizeConnection(AuthorizeConnectionRequest) returns (AuthorizeConnectionResponse) {} + // CancelSession allows a worker to request that the controller cancel a session. + rpc CancelSession(CancelSessionRequest) returns (CancelSessionResponse) {} - // ConnectConnection updates a connection to set it to connected - rpc ConnectConnection(ConnectConnectionRequest) returns (ConnectConnectionResponse) {} + // AuthorizeConnection allows a worker to authorize a connection on a controller. + rpc AuthorizeConnection(AuthorizeConnectionRequest) returns (AuthorizeConnectionResponse) {} - // CloseConnections updates a connection to set it to closed - rpc CloseConnection(CloseConnectionRequest) returns (CloseConnectionResponse) {} + // ConnectConnection updates a connection to set it to connected + rpc ConnectConnection(ConnectConnectionRequest) returns (ConnectConnectionResponse) {} + + // CloseConnections updates a connection to set it to closed + rpc CloseConnection(CloseConnectionRequest) returns (CloseConnectionResponse) {} } message LookupSessionRequest { - // The session ID from the client - string session_id = 10; - // The name of the requesting worker, used for filtering to ensure this - // worker is allowed to handle this session. - string server_id = 20; + // The session ID from the client + string session_id = 10; // @gotags: `class:"public"` + // The name of the requesting worker, used for filtering to ensure this + // worker is allowed to handle this session. + string server_id = 20; // @gotags: `class:"public"` } // LookupSessionResponse contains information necessary for a client to // establish a session. message LookupSessionResponse { - api.resources.targets.v1.SessionAuthorizationData authorization = 10; - string tofu_token = 20; - uint32 version = 30; - string endpoint = 40; - google.protobuf.Timestamp expiration = 50; - controller.servers.services.v1.SESSIONSTATUS status = 60; - int32 connection_limit = 70; - int32 connections_left = 80; - string host_id = 90; - string host_set_id = 100; - string target_id = 110; - string user_id = 120; + api.resources.targets.v1.SessionAuthorizationData authorization = 10; + string tofu_token = 20; // @gotags: `class:"secret"` + uint32 version = 30; // @gotags: `class:"public"` + string endpoint = 40; // @gotags: `class:"public"` + google.protobuf.Timestamp expiration = 50; // @gotags: `class:"public"` + controller.servers.services.v1.SESSIONSTATUS status = 60; // @gotags: `class:"public"` + int32 connection_limit = 70; // @gotags: `class:"public"` + int32 connections_left = 80; // @gotags: `class:"public"` + string host_id = 90; // @gotags: `class:"public"` + string host_set_id = 100; // @gotags: `class:"public"` + string target_id = 110; // @gotags: `class:"public"` + string user_id = 120; // @gotags: `class:"public"` } message ActivateSessionRequest { - string session_id = 10; - string tofu_token = 20; - uint32 version = 30; - string worker_id = 40; - controller.servers.services.v1.SESSIONSTATUS status = 50; + string session_id = 10; // @gotags: `class:"public"` + string tofu_token = 20; // @gotags: `class:"secret"` + uint32 version = 30; // @gotags: `class:"public"` + string worker_id = 40; // @gotags: `class:"public"` + controller.servers.services.v1.SESSIONSTATUS status = 50; // @gotags: `class:"public"` } message ActivateSessionResponse { - controller.servers.services.v1.SESSIONSTATUS status = 10; + controller.servers.services.v1.SESSIONSTATUS status = 10; // @gotags: `class:"public"` } message CancelSessionRequest { - string session_id = 10; + string session_id = 10; // @gotags: `class:"public"` } message CancelSessionResponse { - controller.servers.services.v1.SESSIONSTATUS status = 10; + controller.servers.services.v1.SESSIONSTATUS status = 10; // @gotags: `class:"public"` } message AuthorizeConnectionRequest { - string session_id = 10; - string worker_id = 20; + string session_id = 10; // @gotags: `class:"public"` + string worker_id = 20; // @gotags: `class:"public"` } message AuthorizeConnectionResponse { - string connection_id = 10; - controller.servers.services.v1.CONNECTIONSTATUS status = 20; - int32 connections_left = 30; + string connection_id = 10; // @gotags: `class:"public"` + controller.servers.services.v1.CONNECTIONSTATUS status = 20; // @gotags: `class:"public"` + int32 connections_left = 30; // @gotags: `class:"public"` } message ConnectConnectionRequest { - string connection_id = 10; - string client_tcp_address = 20; - uint32 client_tcp_port = 30; - string endpoint_tcp_address = 40; - uint32 endpoint_tcp_port = 50; - string type = 60; + string connection_id = 10; // @gotags: `class:"public"` + string client_tcp_address = 20; // @gotags: `class:"public"` + uint32 client_tcp_port = 30; // @gotags: `class:"public"` + string endpoint_tcp_address = 40; // @gotags: `class:"public"` + uint32 endpoint_tcp_port = 50; // @gotags: `class:"public"` + string type = 60; // @gotags: `class:"public"` } message ConnectConnectionResponse { - controller.servers.services.v1.CONNECTIONSTATUS status = 10; + controller.servers.services.v1.CONNECTIONSTATUS status = 10; // @gotags: `class:"public"` } message CloseConnectionRequestData { - string connection_id = 10; - uint64 bytes_up = 20; - uint64 bytes_down = 30; - string reason = 40; + string connection_id = 10; // @gotags: `class:"public"` + uint64 bytes_up = 20; // @gotags: `class:"public"` + uint64 bytes_down = 30; // @gotags: `class:"public"` + string reason = 40; // @gotags: `class:"public"` } message CloseConnectionRequest { - repeated CloseConnectionRequestData close_request_data = 10; + repeated CloseConnectionRequestData close_request_data = 10; // @gotags: `class:"public"` } message CloseConnectionResponseData { - string connection_id = 10; - controller.servers.services.v1.CONNECTIONSTATUS status = 20; + string connection_id = 10; + controller.servers.services.v1.CONNECTIONSTATUS status = 20; // @gotags: `class:"public"` } message CloseConnectionResponse { - repeated CloseConnectionResponseData close_response_data = 10; + repeated CloseConnectionResponseData close_response_data = 10; // @gotags: `class:"public"` } diff --git a/internal/servers/controller/interceptor.go b/internal/servers/controller/interceptor.go index c7887ce76..2f741f8b1 100644 --- a/internal/servers/controller/interceptor.go +++ b/internal/servers/controller/interceptor.go @@ -13,6 +13,7 @@ import ( "github.com/hashicorp/boundary/internal/kms" "github.com/hashicorp/boundary/internal/observability/event" "github.com/hashicorp/boundary/internal/requests" + commonSrv "github.com/hashicorp/boundary/internal/servers/common" "github.com/hashicorp/boundary/internal/servers/controller/auth" "github.com/hashicorp/boundary/internal/servers/controller/common" "github.com/hashicorp/boundary/internal/servers/controller/handlers" @@ -268,3 +269,39 @@ func auditResponseInterceptor( return resp, err } } + +func workerRequestInfoInterceptor(ctx context.Context, eventer *event.Eventer) (grpc.UnaryServerInterceptor, error) { + const op = "worker.requestInfoInterceptor" + if eventer == nil { + return nil, errors.New(ctx, errors.InvalidParameter, op, "missing eventer") + + } + return func(interceptorCtx context.Context, + req interface{}, + srvInfo *grpc.UnaryServerInfo, + handler grpc.UnaryHandler) (interface{}, error) { + var err error + id, err := event.NewId(event.IdPrefix) + if err != nil { + event.WriteError(interceptorCtx, op, err, event.WithInfoMsg("unable to create id for event", "method", srvInfo.FullMethod)) + return nil, status.Errorf(codes.Internal, "Error creating id for event: %v", err) + } + info := &event.RequestInfo{ + EventId: id, + Id: commonSrv.GeneratedTraceId(interceptorCtx), + Method: srvInfo.FullMethod, + } + interceptorCtx, err = event.NewRequestInfoContext(interceptorCtx, info) + if err != nil { + event.WriteError(interceptorCtx, op, err, event.WithInfoMsg("unable to create context with request info", "method", srvInfo.FullMethod)) + return nil, status.Errorf(codes.Internal, "Error creating context with request info: %v", err) + } + interceptorCtx, err = event.NewEventerContext(interceptorCtx, eventer) + if err != nil { + event.WriteError(interceptorCtx, op, err, event.WithInfoMsg("unable to create context with eventer", "method", srvInfo.FullMethod)) + return nil, status.Errorf(codes.Internal, "Error creating context with eventer: %v", err) + } + // call the handler... + return handler(interceptorCtx, req) + }, nil +} diff --git a/internal/servers/controller/interceptor_test.go b/internal/servers/controller/interceptor_test.go index d1b0d5740..922e762d3 100644 --- a/internal/servers/controller/interceptor_test.go +++ b/internal/servers/controller/interceptor_test.go @@ -464,6 +464,97 @@ func Test_statusCodeInterceptor(t *testing.T) { } } +func Test_workerRequestInfoInterceptor(t *testing.T) { + factoryCtx := context.Background() + requestCtx := context.Background() + + returnCtxHandler := func(ctx context.Context, req interface{}) (interface{}, error) { + return ctx, nil + } + + c := event.TestEventerConfig(t, "Test_requestCtxInterceptor", event.TestWithAuditSink(t), event.TestWithObservationSink(t)) + testLock := &sync.Mutex{} + testLogger := hclog.New(&hclog.LoggerOptions{ + Mutex: testLock, + Name: "test", + }) + testEventer, err := event.NewEventer(testLogger, testLock, "Test_requestCtxInterceptor", c.EventerConfig) + require.NoError(t, err) + + tests := []struct { + name string + requestCtx context.Context + eventer *event.Eventer + wantFactoryErr bool + wantFactoryErrMatch *errors.Template + wantFactoryErrContains string + wantRequestErr bool + wantRequestErrMatch *errors.Template + wantRequestErrContains string + }{ + + { + name: "missing-eventer", + requestCtx: requestCtx, + wantFactoryErr: true, + wantFactoryErrMatch: errors.T(errors.InvalidParameter), + wantFactoryErrContains: "missing eventer", + }, + + { + name: "valid", + requestCtx: requestCtx, + eventer: testEventer, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert, require := assert.New(t), require.New(t) + interceptor, err := workerRequestInfoInterceptor(factoryCtx, tt.eventer) + if tt.wantFactoryErr { + require.Error(err) + assert.Nil(interceptor) + if tt.wantFactoryErrMatch != nil { + assert.Truef(errors.Match(tt.wantFactoryErrMatch, err), "want err code: %q got: %q", tt.wantFactoryErrMatch.Code, err) + } + if tt.wantFactoryErrContains != "" { + assert.Contains(err.Error(), tt.wantFactoryErrContains) + } + return + } + require.NoError(err) + assert.NotNil(interceptor) + + info := &grpc.UnaryServerInfo{ + FullMethod: "FakeMethod", + } + retCtx, err := interceptor(tt.requestCtx, nil, info, returnCtxHandler) + if tt.wantRequestErr { + require.Error(err) + assert.Nil(retCtx) + if tt.wantRequestErrMatch != nil { + assert.Truef(errors.Match(tt.wantRequestErrMatch, err), "want err code: %q got: %q", tt.wantRequestErrMatch.Code, err) + } + if tt.wantRequestErrContains != "" { + assert.Contains(err.Error(), tt.wantRequestErrContains) + } + return + } + require.NoError(err) + requestInfo, found := event.RequestInfoFromContext(retCtx.(context.Context)) + require.True(found) + assert.NotNil(requestInfo) + assert.NotEmpty(requestInfo.Id) + assert.NotEmpty(requestInfo.EventId) + assert.Equal("FakeMethod", requestInfo.Method) + + eventer, found := event.EventerFromContext(retCtx.(context.Context)) + require.True(found) + assert.NotNil(eventer) + }) + } +} + type testGreeter struct { interceptor.UnimplementedGreeterServiceServer } diff --git a/internal/servers/controller/listeners.go b/internal/servers/controller/listeners.go index d5c175ff4..7c3452890 100644 --- a/internal/servers/controller/listeners.go +++ b/internal/servers/controller/listeners.go @@ -12,6 +12,7 @@ import ( "sync" "time" + grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware" "github.com/hashicorp/boundary/globals" "github.com/hashicorp/boundary/internal/cmd/base" pbs "github.com/hashicorp/boundary/internal/gen/controller/servers/services" @@ -123,9 +124,20 @@ func (c *Controller) startListeners(ctx context.Context) error { return fmt.Errorf("error getting sub-listener for worker proto: %w", err) } + workerReqInterceptor, err := workerRequestInfoInterceptor(ctx, c.conf.Eventer) + if err != nil { + return fmt.Errorf("error getting sub-listener for worker proto: %w", err) + } workerServer := grpc.NewServer( grpc.MaxRecvMsgSize(math.MaxInt32), grpc.MaxSendMsgSize(math.MaxInt32), + grpc.UnaryInterceptor( + grpc_middleware.ChainUnaryServer( + workerReqInterceptor, + auditRequestInterceptor(ctx), // before we get started, audit the request + auditResponseInterceptor(ctx), // as we finish, audit the response + ), + ), ) workerService := workers.NewWorkerServiceServer(c.ServersRepoFn, c.SessionRepoFn, c.workerStatusUpdateTimes, c.kms) pbs.RegisterServerCoordinationServiceServer(workerServer, workerService) diff --git a/sdk/pbs/controller/api/resources/targets/target.pb.go b/sdk/pbs/controller/api/resources/targets/target.pb.go index 388432916..77df25ee1 100644 --- a/sdk/pbs/controller/api/resources/targets/target.pb.go +++ b/sdk/pbs/controller/api/resources/targets/target.pb.go @@ -755,7 +755,7 @@ type WorkerInfo struct { unknownFields protoimpl.UnknownFields // Output only. The address of the worker. - Address string `protobuf:"bytes,10,opt,name=address,proto3" json:"address,omitempty"` + Address string `protobuf:"bytes,10,opt,name=address,proto3" json:"address,omitempty" class:"public"` // @gotags: `class:"public"` } func (x *WorkerInfo) Reset() { @@ -804,25 +804,25 @@ type SessionAuthorizationData struct { unknownFields protoimpl.UnknownFields // Output only. The ID of the session. - SessionId string `protobuf:"bytes,10,opt,name=session_id,proto3" json:"session_id,omitempty"` + SessionId string `protobuf:"bytes,10,opt,name=session_id,proto3" json:"session_id,omitempty" class:"public"` // @gotags: `class:"public"` // Output only. The ID of the Target authorizing this session. - TargetId string `protobuf:"bytes,20,opt,name=target_id,proto3" json:"target_id,omitempty"` + TargetId string `protobuf:"bytes,20,opt,name=target_id,proto3" json:"target_id,omitempty" class:"public"` // @gotags: `class:"public"` // Output only. Scope information for this the Target that authorized this session. Scope *scopes.ScopeInfo `protobuf:"bytes,30,opt,name=scope,proto3" json:"scope,omitempty"` // Output only. The time this resource was created. - CreatedTime *timestamppb.Timestamp `protobuf:"bytes,40,opt,name=created_time,proto3" json:"created_time,omitempty"` + CreatedTime *timestamppb.Timestamp `protobuf:"bytes,40,opt,name=created_time,proto3" json:"created_time,omitempty" class:"public"` // @gotags: `class:"public"` // Output only. Type of the session (e.g. tcp, ssh, etc.). - Type string `protobuf:"bytes,80,opt,name=type,proto3" json:"type,omitempty"` + Type string `protobuf:"bytes,80,opt,name=type,proto3" json:"type,omitempty" class:"public"` // @gotags: `class:"public"` // Output only. The connection limit being applied to this session. -1 means unlimited. This is not actually enforced on the client side but it provides for better listener handling by including it. ConnectionLimit int32 `protobuf:"varint,90,opt,name=connection_limit,proto3" json:"connection_limit,omitempty"` // Output only. The certificate to use when connecting. Raw DER bytes. - Certificate []byte `protobuf:"bytes,120,opt,name=certificate,proto3" json:"certificate,omitempty"` + Certificate []byte `protobuf:"bytes,120,opt,name=certificate,proto3" json:"certificate,omitempty" class:"secret"` // @gotags: `class:"secret"` // Output only. The private key to use when connecting. We are using Ed25519, so this is purely raw bytes, no marshaling. - PrivateKey []byte `protobuf:"bytes,130,opt,name=private_key,proto3" json:"private_key,omitempty"` + PrivateKey []byte `protobuf:"bytes,130,opt,name=private_key,proto3" json:"private_key,omitempty" class:"secret"` // @gotags: `class:"secret"` // Output only. The host ID...not used for security purposes, but for some special command handling (e.g. ssh host key aliasing). - HostId string `protobuf:"bytes,140,opt,name=host_id,json=hostId,proto3" json:"host_id,omitempty"` + HostId string `protobuf:"bytes,140,opt,name=host_id,json=hostId,proto3" json:"host_id,omitempty" class:"public"` // @gotags: `class:"public"` // Output only. The endpoint, for some special command handling. - Endpoint string `protobuf:"bytes,141,opt,name=endpoint,proto3" json:"endpoint,omitempty"` + Endpoint string `protobuf:"bytes,141,opt,name=endpoint,proto3" json:"endpoint,omitempty" class:"public"` // @gotags: `class:"public"` // Output only. Worker information. The first worker in the array should be prioritized. WorkerInfo []*WorkerInfo `protobuf:"bytes,150,rep,name=worker_info,proto3" json:"worker_info,omitempty"` } @@ -943,25 +943,25 @@ type SessionAuthorization struct { unknownFields protoimpl.UnknownFields // Output only. The ID of the Session. - SessionId string `protobuf:"bytes,10,opt,name=session_id,proto3" json:"session_id,omitempty"` + SessionId string `protobuf:"bytes,10,opt,name=session_id,proto3" json:"session_id,omitempty" class:"public"` // @gotags: `class:"public"` // Output only. The ID of the Target authorizing this Session. - TargetId string `protobuf:"bytes,20,opt,name=target_id,proto3" json:"target_id,omitempty"` + TargetId string `protobuf:"bytes,20,opt,name=target_id,proto3" json:"target_id,omitempty" class:"public"` // @gotags: `class:"public"` // Output only. Scope information for this resource. Scope *scopes.ScopeInfo `protobuf:"bytes,30,opt,name=scope,proto3" json:"scope,omitempty"` // Output only. The time this resource was created. - CreatedTime *timestamppb.Timestamp `protobuf:"bytes,40,opt,name=created_time,proto3" json:"created_time,omitempty"` + CreatedTime *timestamppb.Timestamp `protobuf:"bytes,40,opt,name=created_time,proto3" json:"created_time,omitempty" class:"public"` // @gotags: `class:"public"` // Output only. The User for which this Session was authorized. - UserId string `protobuf:"bytes,50,opt,name=user_id,proto3" json:"user_id,omitempty"` + UserId string `protobuf:"bytes,50,opt,name=user_id,proto3" json:"user_id,omitempty" class:"public"` // @gotags: `class:"public"` // Output only. The Host Set containing the Host being used for this Session. - HostSetId string `protobuf:"bytes,60,opt,name=host_set_id,proto3" json:"host_set_id,omitempty"` + HostSetId string `protobuf:"bytes,60,opt,name=host_set_id,proto3" json:"host_set_id,omitempty" class:"public"` // @gotags: `class:"public"` // Output only. The Host whose address is being used as the endpoint for this Session. - HostId string `protobuf:"bytes,70,opt,name=host_id,proto3" json:"host_id,omitempty"` + HostId string `protobuf:"bytes,70,opt,name=host_id,proto3" json:"host_id,omitempty" class:"public"` // @gotags: `class:"public"` // Output only. Type of the Session (e.g. tcp, ssh, etc.). - Type string `protobuf:"bytes,80,opt,name=type,proto3" json:"type,omitempty"` + Type string `protobuf:"bytes,80,opt,name=type,proto3" json:"type,omitempty" class:"public"` // @gotags: `class:"public"` // Output only. The marshaled SessionAuthorizationData message containing all information that the proxy needs. - AuthorizationToken string `protobuf:"bytes,90,opt,name=authorization_token,proto3" json:"authorization_token,omitempty"` + AuthorizationToken string `protobuf:"bytes,90,opt,name=authorization_token,proto3" json:"authorization_token,omitempty" class:"private"` // @gotags: `class:"private"` // Output only. The endpoint address that the worker will connect to, useful for setting TLS parameters. - Endpoint string `protobuf:"bytes,100,opt,name=endpoint,proto3" json:"endpoint,omitempty"` + Endpoint string `protobuf:"bytes,100,opt,name=endpoint,proto3" json:"endpoint,omitempty" class:"public"` // @gotags: `class:"public"` // Output only. The credentials for this session. Credentials []*SessionCredential `protobuf:"bytes,110,rep,name=credentials,proto3" json:"credentials,omitempty"` }