Files
Maja Cieślak ed40e1c66d Add mobile_device.create_enroll_token permission; make boombuler/barcode a direct dep (#67863)
* Add `mobile_device` kind for `mobile_device.create_enroll_token` permission

* Update preset-roles.json

* Add `mobile_device.create_enroll_token` to user ACL

* Make boombuler/barcode a direct dep

It's used in teleport.e to generate the QR code that's going to be
consumed by the mobile app.

* Enable defaultAllowRules to return roles which need `buildType`

* Backfill device-admin role

* Add `mobile_device.create_enroll_token` to admin role
2026-06-26 15:53:20 +00:00

351 lines
16 KiB
Go

/*
* Teleport
* Copyright (C) 2023 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 <http://www.gnu.org/licenses/>.
*/
package services
import (
"github.com/gravitational/teleport/api/client/proto"
apidefaults "github.com/gravitational/teleport/api/defaults"
"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/entitlements"
"github.com/gravitational/teleport/lib/modules"
)
type ResourceAccess struct {
List bool `json:"list"`
Read bool `json:"read"`
Edit bool `json:"edit"`
Create bool `json:"create"`
Delete bool `json:"remove"`
Use bool `json:"use"`
}
// MobileDeviceAccess defines permissions for the mobile_device resource.
// It uses a dedicated shape rather than ResourceAccess because mobile_device
// exposes a custom verb, not the standard list/read/edit/create/delete/use set.
type MobileDeviceAccess struct {
// CreateEnrollToken reflects the mobile_device.create_enroll_token verb,
// which gates a user's ability to start mobile device enrollment.
CreateEnrollToken bool `json:"createEnrollToken"`
}
// UserACL is derived from a user's role set and includes
// information as to what features the user is allowed to use.
type UserACL struct {
// RecordedSessions defines access to recorded sessions.
RecordedSessions ResourceAccess `json:"recordedSessions"`
// ActiveSessions defines access to active sessions.
ActiveSessions ResourceAccess `json:"activeSessions"`
// AuthConnectors defines access to auth.connectors.
AuthConnectors ResourceAccess `json:"authConnectors"`
// Roles defines access to roles.
Roles ResourceAccess `json:"roles"`
// Users defines access to users.
Users ResourceAccess `json:"users"`
// TrustedClusters defines access to trusted clusters.
TrustedClusters ResourceAccess `json:"trustedClusters"`
// Events defines access to audit logs.
Events ResourceAccess `json:"events"`
// Tokens defines access to tokens.
Tokens ResourceAccess `json:"tokens"`
// Nodes defines access to nodes.
Nodes ResourceAccess `json:"nodes"`
// AppServers defines access to application servers
AppServers ResourceAccess `json:"appServers"`
// DBServers defines access to database servers.
DBServers ResourceAccess `json:"dbServers"`
// DB defines access to database resource.
DB ResourceAccess `json:"db"`
// KubeServers defines access to kubernetes servers.
KubeServers ResourceAccess `json:"kubeServers"`
// Desktops defines access to desktops.
Desktops ResourceAccess `json:"desktops"`
// AccessRequests defines access to access requests.
AccessRequests ResourceAccess `json:"accessRequests"`
// Billing defines access to billing information.
Billing ResourceAccess `json:"billing"`
// ConnectionDiagnostic defines access to connection diagnostics.
ConnectionDiagnostic ResourceAccess `json:"connectionDiagnostic"`
// Clipboard defines whether the user can use a shared clipboard during windows desktop sessions.
Clipboard bool `json:"clipboard"`
// DesktopSessionRecording defines whether the user's desktop sessions are being recorded.
DesktopSessionRecording bool `json:"desktopSessionRecording"`
// DirectorySharing defines whether a user is permitted to share a directory during windows desktop sessions.
DirectorySharing bool `json:"directorySharing"`
// Download defines whether the user has access to download Teleport Enterprise Binaries
Download ResourceAccess `json:"download"`
// Download defines whether the user has access to download the license
License ResourceAccess `json:"license"`
// Plugins defines whether the user has access to manage hosted plugin instances
Plugins ResourceAccess `json:"plugins"`
// Integrations defines whether the user has access to manage integrations.
Integrations ResourceAccess `json:"integrations"`
// UserTasks defines whether the user has access to manage UserTasks.
UserTasks ResourceAccess `json:"userTasks"`
// DeviceTrust defines access to device trust.
DeviceTrust ResourceAccess `json:"deviceTrust"`
// Locks defines access to locking resources.
Locks ResourceAccess `json:"lock"`
// SAMLIdpServiceProvider defines access to `saml_idp_service_provider` objects.
SAMLIdpServiceProvider ResourceAccess `json:"samlIdpServiceProvider"`
// AccessList defines access to access list management.
AccessList ResourceAccess `json:"accessList"`
// DiscoveryConfig defines whether the user has access to manage DiscoveryConfigs.
DiscoveryConfig ResourceAccess `json:"discoverConfigs"`
// AuditQuery defines access to audit query management.
AuditQuery ResourceAccess `json:"auditQuery"`
// SecurityReport defines access to security reports.
SecurityReport ResourceAccess `json:"securityReport"`
// ExternalAuditStorage defines access to manage ExternalAuditStorage
ExternalAuditStorage ResourceAccess `json:"externalAuditStorage"`
// AccessGraph defines access to access graph.
AccessGraph ResourceAccess `json:"accessGraph"`
// Bots defines access to manage Bots.
Bots ResourceAccess `json:"bots"`
// BotInstances defines access to manage bot instances
BotInstances ResourceAccess `json:"botInstances"`
// Instances defines access to manage instances
Instances ResourceAccess `json:"instances"`
// AccessMonitoringRule defines access to manage access monitoring rule resources.
AccessMonitoringRule ResourceAccess `json:"accessMonitoringRule"`
// CrownJewel defines access to manage CrownJewel resources.
CrownJewel ResourceAccess `json:"crownJewel"`
// AccessGraphSettings defines access to manage access graph settings.
AccessGraphSettings ResourceAccess `json:"accessGraphSettings"`
// ReviewRequests defines the ability to review requests
ReviewRequests bool `json:"reviewRequests"`
// Contact defines the ability to manage contacts
Contact ResourceAccess `json:"contact"`
// FileTransferAccess defines the ability to perform remote file operations via SCP or SFTP
FileTransferAccess bool `json:"fileTransferAccess"`
// WebTerminalClipboardMode determines clipboard behavior in the Web UI terminal.
WebTerminalClipboardMode types.WebTerminalClipboardMode `json:"webTerminalClipboardMode,omitempty"`
// GitServers defines access to Git servers.
GitServers ResourceAccess `json:"gitServers"`
// WorkloadIdentity defines access to Workload Identity
WorkloadIdentity ResourceAccess `json:"workloadIdentity"`
// ClientIPRestriction defines access to Cloud IP Restrictions
ClientIPRestriction ResourceAccess `json:"clientIpRestriction"`
// InferenceModel defines access to session summaries inference model.
InferenceModel ResourceAccess `json:"inferenceModel"`
// InferencePolicy defines access to session summaries inference policy.
InferencePolicy ResourceAccess `json:"inferencePolicy"`
// InferenceSecret defines access to session summaries inference secret.
InferenceSecret ResourceAccess `json:"inferenceSecret"`
// Classifier defines access to session summarization classifiers.
Classifier ResourceAccess `json:"classifier"`
// AutoUpdateConfig defines access to autoupdate config.
AutoUpdateConfig ResourceAccess `json:"autoUpdateConfig"`
// AutoUpdateVersion defines access to autoupdate version.
AutoUpdateVersion ResourceAccess `json:"autoUpdateVersion"`
// AutoUpdateAgentRollout defines access to autoupdate agent rollout.
AutoUpdateAgentRollout ResourceAccess `json:"autoUpdateAgentRollout"`
// AutoUpdateAgentReport defines access to autoupdate agent reports.
AutoUpdateAgentReport ResourceAccess `json:"autoUpdateAgentReport"`
// Beam defines access to Beams
Beam ResourceAccess `json:"beam"`
// MobileDevice defines permissions for the mobile_device resource.
MobileDevice MobileDeviceAccess `json:"mobileDevice"`
}
func hasAccess(roleSet RoleSet, ctx *Context, kind string, verbs ...string) bool {
for _, verb := range verbs {
// Since this check occurs often and does not imply the caller is trying to
// ResourceAccess any resource, silence any logging done on the proxy.
if err := roleSet.GuessIfAccessIsPossible(ctx, apidefaults.Namespace, kind, verb); err != nil {
return false
}
}
return true
}
func newAccess(roleSet RoleSet, ctx *Context, kind string) ResourceAccess {
return ResourceAccess{
List: hasAccess(roleSet, ctx, kind, types.VerbList),
Read: hasAccess(roleSet, ctx, kind, types.VerbRead),
Edit: hasAccess(roleSet, ctx, kind, types.VerbUpdate),
Create: hasAccess(roleSet, ctx, kind, types.VerbCreate),
Delete: hasAccess(roleSet, ctx, kind, types.VerbDelete),
Use: hasAccess(roleSet, ctx, kind, types.VerbUse),
}
}
// NewUserACL builds an ACL for a user based on their roles.
func NewUserACL(user types.User, userRoles RoleSet, features proto.Features, desktopRecordingEnabled, accessMonitoringEnabled bool) UserACL {
ctx := &Context{User: user}
recordedSessionAccess := newAccess(userRoles, ctx, types.KindSession)
roleAccess := newAccess(userRoles, ctx, types.KindRole)
authConnectors := newAccess(userRoles, ctx, types.KindAuthConnector)
trustedClusterAccess := newAccess(userRoles, ctx, types.KindTrustedCluster)
eventAccess := newAccess(userRoles, ctx, types.KindEvent)
userAccess := newAccess(userRoles, ctx, types.KindUser)
tokenAccess := newAccess(userRoles, ctx, types.KindToken)
nodeAccess := newAccess(userRoles, ctx, types.KindNode)
appServerAccess := newAccess(userRoles, ctx, types.KindAppServer)
dbServerAccess := newAccess(userRoles, ctx, types.KindDatabaseServer)
dbAccess := newAccess(userRoles, ctx, types.KindDatabase)
kubeServerAccess := newAccess(userRoles, ctx, types.KindKubeServer)
requestAccess := newAccess(userRoles, ctx, types.KindAccessRequest)
accessMonitoringRules := newAccess(userRoles, ctx, types.KindAccessMonitoringRule)
desktopAccess := newAccess(userRoles, ctx, types.KindWindowsDesktop)
cnDiagnosticAccess := newAccess(userRoles, ctx, types.KindConnectionDiagnostic)
samlIdpServiceProviderAccess := newAccess(userRoles, ctx, types.KindSAMLIdPServiceProvider)
gitServersAccess := newAccess(userRoles, ctx, types.KindGitServer)
// active sessions are a special case - if a user's role set has any join_sessions
// policies then the ACL must permit showing active sessions
activeSessionAccess := newAccess(userRoles, ctx, types.KindSSHSession)
if userRoles.CanJoinSessions() {
activeSessionAccess.List = true
activeSessionAccess.Read = true
}
// The billing dashboards are available in: cloud clusters &
// usage-based self-hosted non-stripe dashboards.
var billingAccess ResourceAccess
isDashboard := IsDashboard(features)
isUsageBased := features.IsUsageBased
isStripeManaged := features.IsStripeManaged
if features.Cloud || (isDashboard && isUsageBased && !isStripeManaged) {
billingAccess = newAccess(userRoles, ctx, types.KindBilling)
}
var pluginsAccess ResourceAccess
if features.Plugins {
pluginsAccess = newAccess(userRoles, ctx, types.KindPlugin)
}
var accessGraphAccess ResourceAccess
var accessGraphSettings ResourceAccess
if features.AccessGraph {
accessGraphAccess = newAccess(userRoles, ctx, types.KindAccessGraph)
}
// accessGraphSettings should always be enabled for users to interact with demo mode
accessGraphSettings = newAccess(userRoles, ctx, types.KindAccessGraphSettings)
clipboard := userRoles.DesktopClipboard()
desktopSessionRecording := desktopRecordingEnabled && userRoles.RecordDesktopSession()
directorySharing := userRoles.DesktopDirectorySharing()
download := newAccess(userRoles, ctx, types.KindDownload)
license := newAccess(userRoles, ctx, types.KindLicense)
deviceTrust := newAccess(userRoles, ctx, types.KindDevice)
integrationsAccess := newAccess(userRoles, ctx, types.KindIntegration)
discoveryConfigsAccess := newAccess(userRoles, ctx, types.KindDiscoveryConfig)
lockAccess := newAccess(userRoles, ctx, types.KindLock)
accessListAccess := newAccess(userRoles, ctx, types.KindAccessList)
externalAuditStorage := newAccess(userRoles, ctx, types.KindExternalAuditStorage)
bots := newAccess(userRoles, ctx, types.KindBot)
botInstances := newAccess(userRoles, ctx, types.KindBotInstance)
instances := newAccess(userRoles, ctx, types.KindInstance)
crownJewelAccess := newAccess(userRoles, ctx, types.KindCrownJewel)
userTasksAccess := newAccess(userRoles, ctx, types.KindUserTask)
reviewRequests := userRoles.MaybeCanReviewRequests()
fileTransferAccess := userRoles.CanCopyFiles()
workloadIdentity := newAccess(userRoles, ctx, types.KindWorkloadIdentity)
var auditQuery ResourceAccess
var securityReports ResourceAccess
if accessMonitoringEnabled {
auditQuery = newAccess(userRoles, ctx, types.KindAuditQuery)
securityReports = newAccess(userRoles, ctx, types.KindSecurityReport)
}
contact := newAccess(userRoles, ctx, types.KindContact)
var clientIPRestrictions ResourceAccess
if features.Cloud {
clientIPRestrictions = newAccess(userRoles, ctx, types.KindClientIPRestriction)
}
autoUpdateConfig := newAccess(userRoles, ctx, types.KindAutoUpdateConfig)
autoUpdateVersion := newAccess(userRoles, ctx, types.KindAutoUpdateVersion)
autoUpdateAgentRollout := newAccess(userRoles, ctx, types.KindAutoUpdateAgentRollout)
autoUpdateAgentReport := newAccess(userRoles, ctx, types.KindAutoUpdateAgentReport)
beamsEntitlement := modules.GetProtoEntitlement(&features, entitlements.Beams)
var beam ResourceAccess
if beamsEntitlement.Enabled {
beam = newAccess(userRoles, ctx, types.KindBeam)
}
mobileDevice := MobileDeviceAccess{
CreateEnrollToken: hasAccess(userRoles, ctx, types.KindMobileDevice, types.VerbCreateEnrollToken),
}
return UserACL{
AccessRequests: requestAccess,
AppServers: appServerAccess,
DBServers: dbServerAccess,
DB: dbAccess,
ReviewRequests: reviewRequests,
KubeServers: kubeServerAccess,
Desktops: desktopAccess,
AuthConnectors: authConnectors,
TrustedClusters: trustedClusterAccess,
RecordedSessions: recordedSessionAccess,
ActiveSessions: activeSessionAccess,
Roles: roleAccess,
Events: eventAccess,
Users: userAccess,
Tokens: tokenAccess,
Nodes: nodeAccess,
Billing: billingAccess,
ConnectionDiagnostic: cnDiagnosticAccess,
Clipboard: clipboard,
DesktopSessionRecording: desktopSessionRecording,
DirectorySharing: directorySharing,
Download: download,
License: license,
Plugins: pluginsAccess,
Integrations: integrationsAccess,
UserTasks: userTasksAccess,
DiscoveryConfig: discoveryConfigsAccess,
DeviceTrust: deviceTrust,
Locks: lockAccess,
SAMLIdpServiceProvider: samlIdpServiceProviderAccess,
AccessList: accessListAccess,
AuditQuery: auditQuery,
SecurityReport: securityReports,
ExternalAuditStorage: externalAuditStorage,
AccessGraph: accessGraphAccess,
Bots: bots,
BotInstances: botInstances,
Instances: instances,
AccessMonitoringRule: accessMonitoringRules,
CrownJewel: crownJewelAccess,
AccessGraphSettings: accessGraphSettings,
Contact: contact,
FileTransferAccess: fileTransferAccess,
WebTerminalClipboardMode: userRoles.GetWebTerminalClipboardMode(),
GitServers: gitServersAccess,
WorkloadIdentity: workloadIdentity,
ClientIPRestriction: clientIPRestrictions,
InferenceModel: newAccess(userRoles, ctx, types.KindInferenceModel),
InferencePolicy: newAccess(userRoles, ctx, types.KindInferencePolicy),
InferenceSecret: newAccess(userRoles, ctx, types.KindInferenceSecret),
Classifier: newAccess(userRoles, ctx, types.KindClassifier),
AutoUpdateConfig: autoUpdateConfig,
AutoUpdateVersion: autoUpdateVersion,
AutoUpdateAgentRollout: autoUpdateAgentRollout,
AutoUpdateAgentReport: autoUpdateAgentReport,
Beam: beam,
MobileDevice: mobileDevice,
}
}