teleport/lib/services/connection_diagnostic.go
Marco André Dinis 89f4d5476a
Create and List Connection Diagnostics (#14781)
In Teleport Discover, we want to improve the UX of adding a resource.
We'll suggest users to test accessing a resource, and give them immediate feedback using the UI.

Note: we'll add this feature to Server Access, later one we'll add other resources.

After adding a server resource, the user will be presented with a command to test the connection:
`tsh ssh --test-id=123 user@host`

Running that command will provide the user feedback right in the UI of whether or not it worked.
If not, a short message will be displayed describing why it didn't work and how the user can solve the problem.

---

To achieve this we'll need a couple of changes:
1. new resource that stores the result of trying to connect to a given resource, so that the UI can ask for it
2. change `tsh ssh` to receive the `--test-id` flag and write the result to a record of this new resource

This PR addresses 1 - new resource.

A new resource is created:
```
Connection Diagnostics
- success (bool)
- message (string)
```

Two new rpc methods:
- create connection diagnostics
- read connection diagnostics

One new HTTP Endpoint:
- read connection diagnostics

Related to
https://github.com/gravitational/teleport/issues/13957
2022-08-01 08:49:35 +01:00

105 lines
2.9 KiB
Go

/*
Copyright 2022 Gravitational, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package services
import (
"context"
"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/lib/utils"
"github.com/gravitational/trace"
)
// ConnectionsDiagnostic defines an interface for managing Connection Diagnostics.
type ConnectionsDiagnostic interface {
// CreateConnectionDiagnostic creates a new Connection Diagnostic
CreateConnectionDiagnostic(context.Context, types.ConnectionDiagnostic) error
// GetConnectionDiagnostic receives a name and returns the Connection Diagnostic matching that name
//
// If not found, a `trace.NotFound` error is returned
GetConnectionDiagnostic(ctx context.Context, name string) (types.ConnectionDiagnostic, error)
}
// MarshalConnectionDiagnostic marshals the ConnectionDiagnostic resource to JSON.
func MarshalConnectionDiagnostic(s types.ConnectionDiagnostic, opts ...MarshalOption) ([]byte, error) {
if err := s.CheckAndSetDefaults(); err != nil {
return nil, trace.Wrap(err)
}
cfg, err := CollectOptions(opts)
if err != nil {
return nil, trace.Wrap(err)
}
switch s := s.(type) {
case *types.ConnectionDiagnosticV1:
if !cfg.PreserveResourceID {
// avoid modifying the original object
// to prevent unexpected data races
copy := *s
copy.SetResourceID(0)
s = &copy
}
return utils.FastMarshal(s)
}
return nil, trace.BadParameter("unrecognized connection diagnostic version %T", s)
}
// UnmarshalConnectionDiagnostic unmarshals the ConnectionDiagnostic resource from JSON.
func UnmarshalConnectionDiagnostic(data []byte, opts ...MarshalOption) (types.ConnectionDiagnostic, error) {
if len(data) == 0 {
return nil, trace.BadParameter("missing connection diagnostic data")
}
cfg, err := CollectOptions(opts)
if err != nil {
return nil, trace.Wrap(err)
}
var h types.ResourceHeader
if err := utils.FastUnmarshal(data, &h); err != nil {
return nil, trace.Wrap(err)
}
switch h.Version {
case types.V1:
var s types.ConnectionDiagnosticV1
if err := utils.FastUnmarshal(data, &s); err != nil {
return nil, trace.BadParameter(err.Error())
}
if err := s.CheckAndSetDefaults(); err != nil {
return nil, trace.Wrap(err)
}
if cfg.ID != 0 {
s.SetResourceID(cfg.ID)
}
if !cfg.Expires.IsZero() {
s.SetExpiry(cfg.Expires)
}
return &s, nil
}
return nil, trace.BadParameter("connection diagnostic resource version %q is not supported", h.Version)
}