mirror of
https://github.com/gravitational/teleport
synced 2024-10-20 17:23:22 +00:00
Display license out of compliance warnings (#14114)
This commit is contained in:
parent
c0fcb143e6
commit
26e3df82b5
File diff suppressed because it is too large
Load diff
|
@ -467,6 +467,8 @@ message PingResponse {
|
|||
string ProxyPublicAddr = 4 [ (gogoproto.jsontag) = "proxy_public_addr" ];
|
||||
// IsBoring signals whether or not the server was compiled with BoringCrypto.
|
||||
bool IsBoring = 5 [ (gogoproto.jsontag) = "is_boring" ];
|
||||
// LicenseWarnings is a list of license compliance warnings.
|
||||
repeated string LicenseWarnings = 6 [ (gogoproto.jsontag) = "license_warnings" ];
|
||||
}
|
||||
|
||||
// Features are auth server features.
|
||||
|
|
|
@ -285,6 +285,8 @@ type PingResponse struct {
|
|||
MinClientVersion string `json:"min_client_version"`
|
||||
// ClusterName contains the name of the Teleport cluster.
|
||||
ClusterName string `json:"cluster_name"`
|
||||
// LicenseWarnings contains a list of license compliance warning messages
|
||||
LicenseWarnings []string `json:"license_warnings,omitempty"`
|
||||
}
|
||||
|
||||
// PingErrorResponse contains the error message if the requested connector
|
||||
|
|
2
e
2
e
|
@ -1 +1 @@
|
|||
Subproject commit 7868ba469330df45a76cae1840b7b961aee315f3
|
||||
Subproject commit 1362c0bde5bd53566badc9083f24a2d3885e33b0
|
|
@ -975,3 +975,6 @@ type NewRemoteProxyCachingAccessPoint func(clt ClientI, cacheName []string) (Rem
|
|||
// notImplementedMessage is the message to return for endpoints that are not
|
||||
// implemented. This is due to how service interfaces are used with Teleport.
|
||||
const notImplementedMessage = "not implemented: can only be called by auth locally"
|
||||
|
||||
// LicenseExpiredNotification defines a license expired notification
|
||||
const LicenseExpiredNotification = "licenseExpired"
|
||||
|
|
|
@ -154,6 +154,9 @@ func NewServer(cfg *InitConfig, opts ...ServerOption) (*Server, error) {
|
|||
return nil, trace.Wrap(err)
|
||||
}
|
||||
}
|
||||
if cfg.Enforcer == nil {
|
||||
cfg.Enforcer = local.NewNoopEnforcer()
|
||||
}
|
||||
if cfg.KeyStoreConfig.RSAKeyPairSource == nil {
|
||||
native.PrecomputeKeys()
|
||||
cfg.KeyStoreConfig.RSAKeyPairSource = native.GenerateKeyPair
|
||||
|
@ -204,6 +207,7 @@ func NewServer(cfg *InitConfig, opts ...ServerOption) (*Server, error) {
|
|||
Events: cfg.Events,
|
||||
WindowsDesktops: cfg.WindowsDesktops,
|
||||
SessionTrackerService: cfg.SessionTrackerService,
|
||||
Enforcer: cfg.Enforcer,
|
||||
},
|
||||
keyStore: keyStore,
|
||||
getClaimsFun: getClaims,
|
||||
|
@ -232,6 +236,7 @@ type Services struct {
|
|||
services.Databases
|
||||
services.WindowsDesktops
|
||||
services.SessionTrackerService
|
||||
services.Enforcer
|
||||
types.Events
|
||||
events.IAuditLog
|
||||
}
|
||||
|
@ -610,6 +615,11 @@ func (a *Server) SetAuditLog(auditLog events.IAuditLog) {
|
|||
a.IAuditLog = auditLog
|
||||
}
|
||||
|
||||
// SetEnforcer sets the server's enforce service
|
||||
func (a *Server) SetEnforcer(enforcer services.Enforcer) {
|
||||
a.Enforcer = enforcer
|
||||
}
|
||||
|
||||
// GetAuthPreference gets AuthPreference from the cache.
|
||||
func (a *Server) GetAuthPreference(ctx context.Context) (types.AuthPreference, error) {
|
||||
return a.GetCache().GetAuthPreference(ctx)
|
||||
|
|
|
@ -57,6 +57,7 @@ import (
|
|||
"github.com/gravitational/teleport/lib/tlsca"
|
||||
"github.com/gravitational/teleport/lib/utils"
|
||||
|
||||
reporting "github.com/gravitational/reporting/types"
|
||||
"github.com/gravitational/trace"
|
||||
|
||||
"github.com/coreos/go-oidc/jose"
|
||||
|
@ -2038,3 +2039,39 @@ func TestCAGeneration(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
type mockEnforcer struct {
|
||||
services.Enforcer
|
||||
notifications []reporting.Notification
|
||||
}
|
||||
|
||||
func (m mockEnforcer) GetLicenseCheckResult(ctx context.Context) (*reporting.Heartbeat, error) {
|
||||
return &reporting.Heartbeat{
|
||||
Spec: reporting.HeartbeatSpec{
|
||||
Notifications: m.notifications,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func TestEnforcerGetLicenseCheckResult(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx := context.Background()
|
||||
s := newAuthSuite(t)
|
||||
|
||||
expected := []reporting.Notification{
|
||||
{
|
||||
Type: "test",
|
||||
Severity: "warning",
|
||||
Text: "test warning",
|
||||
HTML: "test warning",
|
||||
},
|
||||
}
|
||||
|
||||
s.a.SetEnforcer(&mockEnforcer{
|
||||
notifications: expected,
|
||||
})
|
||||
|
||||
heartbeat, err := s.a.GetLicenseCheckResult(ctx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expected, heartbeat.Spec.Notifications)
|
||||
}
|
||||
|
|
|
@ -1919,13 +1919,23 @@ func (a *ServerWithRoles) Ping(ctx context.Context) (proto.PingResponse, error)
|
|||
if err != nil {
|
||||
return proto.PingResponse{}, trace.Wrap(err)
|
||||
}
|
||||
|
||||
heartbeat, err := a.authServer.GetLicenseCheckResult(ctx)
|
||||
if err != nil {
|
||||
return proto.PingResponse{}, trace.Wrap(err)
|
||||
}
|
||||
var warnings []string
|
||||
for _, notification := range heartbeat.Spec.Notifications {
|
||||
if notification.Type == LicenseExpiredNotification {
|
||||
warnings = append(warnings, notification.Text)
|
||||
}
|
||||
}
|
||||
return proto.PingResponse{
|
||||
ClusterName: cn.GetClusterName(),
|
||||
ServerVersion: teleport.Version,
|
||||
ServerFeatures: modules.GetModules().Features().ToProto(),
|
||||
ProxyPublicAddr: a.getProxyPublicAddr(),
|
||||
IsBoring: modules.GetModules().IsBoringBinary(),
|
||||
LicenseWarnings: warnings,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -4163,6 +4163,7 @@ func NewGRPCServer(cfg GRPCServerConfig) (*GRPCServer, error) {
|
|||
grpc.Creds(&httplib.TLSCreds{
|
||||
Config: cfg.TLS,
|
||||
}),
|
||||
|
||||
grpc.ChainUnaryInterceptor(otelgrpc.UnaryServerInterceptor(), cfg.UnaryInterceptor),
|
||||
grpc.ChainStreamInterceptor(otelgrpc.StreamServerInterceptor(), cfg.StreamInterceptor),
|
||||
grpc.KeepaliveParams(
|
||||
|
|
|
@ -170,6 +170,9 @@ type InitConfig struct {
|
|||
WindowsDesktops services.WindowsDesktops
|
||||
|
||||
SessionTrackerService services.SessionTrackerService
|
||||
|
||||
// Enforcer is used to enforce Teleport Enterprise license compliance.
|
||||
Enforcer services.Enforcer
|
||||
}
|
||||
|
||||
// Init instantiates and configures an instance of AuthServer
|
||||
|
|
29
lib/services/enforcer.go
Normal file
29
lib/services/enforcer.go
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
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/reporting/types"
|
||||
)
|
||||
|
||||
// Enforcer defines interface for fetching license status.
|
||||
type Enforcer interface {
|
||||
// GetLicenseCheckResult returns the license status in a heartbeat.
|
||||
GetLicenseCheckResult(ctx context.Context) (*types.Heartbeat, error)
|
||||
}
|
36
lib/services/local/enforcer.go
Normal file
36
lib/services/local/enforcer.go
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
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 local
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gravitational/reporting/types"
|
||||
)
|
||||
|
||||
// NoopEnforcer is a no-op enforcer.
|
||||
type NoopEnforcer struct{}
|
||||
|
||||
// NewNoopEnforcer returns a new no-op enforcer.
|
||||
func NewNoopEnforcer() *NoopEnforcer {
|
||||
return &NoopEnforcer{}
|
||||
}
|
||||
|
||||
// GetLicenseCheckResult returns the default heartbeat.
|
||||
func (r *NoopEnforcer) GetLicenseCheckResult(ctx context.Context) (*types.Heartbeat, error) {
|
||||
return types.NewHeartbeat(), nil
|
||||
}
|
|
@ -841,12 +841,18 @@ func (h *Handler) ping(w http.ResponseWriter, r *http.Request, p httprouter.Para
|
|||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
||||
pr, err := h.cfg.ProxyClient.Ping(r.Context())
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
||||
return webclient.PingResponse{
|
||||
Auth: authSettings,
|
||||
Proxy: *proxyConfig,
|
||||
ServerVersion: teleport.Version,
|
||||
MinClientVersion: teleport.MinClientVersion,
|
||||
ClusterName: h.auth.clusterName,
|
||||
LicenseWarnings: pr.LicenseWarnings,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -1458,7 +1458,20 @@ func onLogin(cf *CLIConf) error {
|
|||
cf.Proxy = webProxyHost
|
||||
|
||||
// Print status to show information of the logged in user.
|
||||
return trace.Wrap(onStatus(cf))
|
||||
if err := onStatus(cf); err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
|
||||
// Display any license compliance warnings
|
||||
resp, err := tc.Ping(cf.Context)
|
||||
if err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
for _, warning := range resp.LicenseWarnings {
|
||||
fmt.Fprintf(os.Stderr, "%s\n\n", warning)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// setupNoninteractiveClient sets up existing client to use
|
||||
|
|
Loading…
Reference in a new issue