Skip to content

Commit 9c06ddc

Browse files
authored
Check cloud feature before setting billing access for web (#6537)
* Init web handler with auth server feature flags on proxy init * Retrieve auth server features by calling Ping when connecting to auth svc which contains the server feature flags in the response
1 parent 9910598 commit 9c06ddc

File tree

5 files changed

+81
-34
lines changed

5 files changed

+81
-34
lines changed

Diff for: lib/service/connect.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,10 @@ func (process *TeleportProcess) reconnectToAuthService(role teleport.Role) (*Con
5555
// if connected and client is present, make sure the connector's
5656
// client works, by using call that should succeed at all times
5757
if connector.Client != nil {
58-
_, err = connector.Client.GetNamespace(defaults.Namespace)
58+
pingResponse, err := connector.Client.Ping(process.ExitContext())
5959
if err == nil {
60+
process.setClusterFeatures(pingResponse.GetServerFeatures())
61+
process.log.Infof("%v: features loaded from auth server: %+v", role, pingResponse.GetServerFeatures())
6062
return connector, nil
6163
}
6264
process.log.Debugf("Connected client %v failed to execute test call: %v. Node or proxy credentials are out of sync.", role, err)

Diff for: lib/service/service.go

+37-15
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ import (
4747
"github.com/gravitational/trace"
4848

4949
"github.com/gravitational/teleport"
50+
"github.com/gravitational/teleport/api/client/proto"
5051
"github.com/gravitational/teleport/api/client/webclient"
5152
"github.com/gravitational/teleport/lib/auth"
5253
"github.com/gravitational/teleport/lib/auth/native"
@@ -293,6 +294,9 @@ type TeleportProcess struct {
293294
// appDependCh is used by application service in single process mode to block
294295
// until auth and reverse tunnel servers are ready.
295296
appDependCh chan Event
297+
298+
// clusterFeatures contain flags for supported and unsupported features.
299+
clusterFeatures proto.Features
296300
}
297301

298302
type keyPairKey struct {
@@ -355,6 +359,22 @@ func (process *TeleportProcess) addConnector(connector *Connector) {
355359
process.connectors[connector.ClientIdentity.ID.Role] = connector
356360
}
357361

362+
func (process *TeleportProcess) setClusterFeatures(features *proto.Features) {
363+
process.Lock()
364+
defer process.Unlock()
365+
366+
if features != nil {
367+
process.clusterFeatures = *features
368+
}
369+
}
370+
371+
func (process *TeleportProcess) getClusterFeatures() proto.Features {
372+
process.Lock()
373+
defer process.Unlock()
374+
375+
return process.clusterFeatures
376+
}
377+
358378
// GetIdentity returns the process identity (credentials to the auth server) for a given
359379
// teleport Role. A teleport process can have any combination of 3 roles: auth, node, proxy
360380
// and they have their own identities
@@ -2528,23 +2548,25 @@ func (process *TeleportProcess) initProxyEndpoint(conn *Connector) error {
25282548
return trace.Wrap(err)
25292549
}
25302550
}
2551+
25312552
webHandler, err = web.NewHandler(
25322553
web.Config{
2533-
Proxy: tsrv,
2534-
AuthServers: cfg.AuthServers[0],
2535-
DomainName: cfg.Hostname,
2536-
ProxyClient: conn.Client,
2537-
ProxySSHAddr: proxySSHAddr,
2538-
ProxyWebAddr: cfg.Proxy.WebAddr,
2539-
ProxySettings: proxySettings,
2540-
CipherSuites: cfg.CipherSuites,
2541-
FIPS: cfg.FIPS,
2542-
AccessPoint: accessPoint,
2543-
Emitter: streamEmitter,
2544-
PluginRegistry: process.PluginRegistry,
2545-
HostUUID: process.Config.HostUUID,
2546-
Context: process.ExitContext(),
2547-
StaticFS: fs,
2554+
Proxy: tsrv,
2555+
AuthServers: cfg.AuthServers[0],
2556+
DomainName: cfg.Hostname,
2557+
ProxyClient: conn.Client,
2558+
ProxySSHAddr: proxySSHAddr,
2559+
ProxyWebAddr: cfg.Proxy.WebAddr,
2560+
ProxySettings: proxySettings,
2561+
CipherSuites: cfg.CipherSuites,
2562+
FIPS: cfg.FIPS,
2563+
AccessPoint: accessPoint,
2564+
Emitter: streamEmitter,
2565+
PluginRegistry: process.PluginRegistry,
2566+
HostUUID: process.Config.HostUUID,
2567+
Context: process.ExitContext(),
2568+
StaticFS: fs,
2569+
ClusterFeatures: process.getClusterFeatures(),
25482570
})
25492571
if err != nil {
25502572
return trace.Wrap(err)

Diff for: lib/web/apiserver.go

+12-4
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import (
3636
"time"
3737

3838
"github.com/gravitational/teleport"
39+
"github.com/gravitational/teleport/api/client/proto"
3940
"github.com/gravitational/teleport/api/client/webclient"
4041
"github.com/gravitational/teleport/api/constants"
4142
"github.com/gravitational/teleport/api/types"
@@ -84,6 +85,9 @@ type Handler struct {
8485
// sshPort specifies the SSH proxy port extracted
8586
// from configuration
8687
sshPort string
88+
89+
// clusterFeatures contain flags for supported and unsupported features.
90+
clusterFeatures proto.Features
8791
}
8892

8993
// HandlerOption is a functional argument - an option that can be passed
@@ -157,6 +161,9 @@ type Config struct {
157161
// in the cache before getting purged after it has expired.
158162
// Defaults to cachedSessionLingeringThreshold if unspecified.
159163
cachedSessionLingeringThreshold *time.Duration
164+
165+
// ClusterFeatures contains flags for supported/unsupported features.
166+
ClusterFeatures proto.Features
160167
}
161168

162169
type RewritingHandler struct {
@@ -197,9 +204,10 @@ func (h *RewritingHandler) Close() error {
197204
func NewHandler(cfg Config, opts ...HandlerOption) (*RewritingHandler, error) {
198205
const apiPrefix = "/" + teleport.WebAPIVersion
199206
h := &Handler{
200-
cfg: cfg,
201-
log: newPackageLogger(),
202-
clock: clockwork.NewRealClock(),
207+
cfg: cfg,
208+
log: newPackageLogger(),
209+
clock: clockwork.NewRealClock(),
210+
clusterFeatures: cfg.ClusterFeatures,
203211
}
204212

205213
for _, o := range opts {
@@ -507,7 +515,7 @@ func (h *Handler) getUserContext(w http.ResponseWriter, r *http.Request, p httpr
507515
return nil, trace.Wrap(err)
508516
}
509517

510-
userContext, err := ui.NewUserContext(user, roleset)
518+
userContext, err := ui.NewUserContext(user, roleset, h.clusterFeatures)
511519
if err != nil {
512520
return nil, trace.Wrap(err)
513521
}

Diff for: lib/web/ui/usercontext.go

+17-12
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ limitations under the License.
1717
package ui
1818

1919
import (
20+
"github.com/gravitational/teleport/api/client/proto"
2021
"github.com/gravitational/teleport/api/types"
2122
"github.com/gravitational/teleport/lib/defaults"
2223
"github.com/gravitational/teleport/lib/services"
@@ -171,21 +172,25 @@ func getAccessStrategy(roleset services.RoleSet) accessStrategy {
171172
}
172173

173174
// NewUserContext returns user context
174-
func NewUserContext(user types.User, userRoles services.RoleSet) (*UserContext, error) {
175+
func NewUserContext(user services.User, userRoles services.RoleSet, features proto.Features) (*UserContext, error) {
175176
ctx := &services.Context{User: user}
176-
sessionAccess := newAccess(userRoles, ctx, types.KindSession)
177-
roleAccess := newAccess(userRoles, ctx, types.KindRole)
178-
authConnectors := newAccess(userRoles, ctx, types.KindAuthConnector)
179-
trustedClusterAccess := newAccess(userRoles, ctx, types.KindTrustedCluster)
180-
eventAccess := newAccess(userRoles, ctx, types.KindEvent)
181-
userAccess := newAccess(userRoles, ctx, types.KindUser)
182-
tokenAccess := newAccess(userRoles, ctx, types.KindToken)
183-
nodeAccess := newAccess(userRoles, ctx, types.KindNode)
184-
appServerAccess := newAccess(userRoles, ctx, types.KindAppServer)
177+
sessionAccess := newAccess(userRoles, ctx, services.KindSession)
178+
roleAccess := newAccess(userRoles, ctx, services.KindRole)
179+
authConnectors := newAccess(userRoles, ctx, services.KindAuthConnector)
180+
trustedClusterAccess := newAccess(userRoles, ctx, services.KindTrustedCluster)
181+
eventAccess := newAccess(userRoles, ctx, services.KindEvent)
182+
userAccess := newAccess(userRoles, ctx, services.KindUser)
183+
tokenAccess := newAccess(userRoles, ctx, services.KindToken)
184+
nodeAccess := newAccess(userRoles, ctx, services.KindNode)
185+
appServerAccess := newAccess(userRoles, ctx, services.KindAppServer)
185186
dbServerAccess := newAccess(userRoles, ctx, types.KindDatabaseServer)
186187
kubeServerAccess := newAccess(userRoles, ctx, types.KindKubeService)
187-
requestAccess := newAccess(userRoles, ctx, types.KindAccessRequest)
188-
billingAccess := newAccess(userRoles, ctx, types.KindBilling)
188+
requestAccess := newAccess(userRoles, ctx, services.KindAccessRequest)
189+
190+
var billingAccess access
191+
if features.Cloud {
192+
billingAccess = newAccess(userRoles, ctx, services.KindBilling)
193+
}
189194

190195
logins := getLogins(userRoles)
191196
accessStrategy := getAccessStrategy(userRoles)

Diff for: lib/web/ui/usercontext_test.go

+12-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package ui
33
import (
44
"testing"
55

6+
"github.com/gravitational/teleport/api/client/proto"
67
"github.com/gravitational/teleport/lib/defaults"
78
"github.com/gravitational/teleport/lib/services"
89
"gopkg.in/check.v1"
@@ -46,6 +47,10 @@ func (s *UserContextSuite) TestNewUserContext(c *check.C) {
4647
Resources: []string{services.KindTrustedCluster},
4748
Verbs: services.RW(),
4849
},
50+
{
51+
Resources: []string{services.KindBilling},
52+
Verbs: services.RO(),
53+
},
4954
})
5055

5156
// set some logins
@@ -54,7 +59,7 @@ func (s *UserContextSuite) TestNewUserContext(c *check.C) {
5459
role2.SetLogins(services.Allow, []string{"d"})
5560

5661
roleSet := []services.Role{role1, role2}
57-
userContext, err := NewUserContext(user, roleSet)
62+
userContext, err := NewUserContext(user, roleSet, proto.Features{})
5863
c.Assert(err, check.IsNil)
5964

6065
allowed := access{true, true, true, true, true}
@@ -79,13 +84,18 @@ func (s *UserContextSuite) TestNewUserContext(c *check.C) {
7984
Type: services.RequestStrategyOptional,
8085
Prompt: "",
8186
})
87+
c.Assert(userContext.ACL.Billing, check.DeepEquals, denied)
8288

8389
// test local auth type
8490
c.Assert(userContext.AuthType, check.Equals, authLocal)
8591

8692
// test sso auth type
8793
user.Spec.GithubIdentities = []services.ExternalIdentity{{ConnectorID: "foo", Username: "bar"}}
88-
userContext, err = NewUserContext(user, roleSet)
94+
userContext, err = NewUserContext(user, roleSet, proto.Features{})
8995
c.Assert(err, check.IsNil)
9096
c.Assert(userContext.AuthType, check.Equals, authSSO)
97+
98+
userContext, err = NewUserContext(user, roleSet, proto.Features{Cloud: true})
99+
c.Assert(err, check.IsNil)
100+
c.Assert(userContext.ACL.Billing, check.DeepEquals, access{true, true, false, false, false})
91101
}

0 commit comments

Comments
 (0)