mirror of
https://github.com/gravitational/teleport.git
synced 2026-10-31 20:39:37 +08:00
* Expose device verification methods in lib/devicetrust/authz * Set device fields in auth.Context.GetAccessState * Enable role-based device verification for SSH * Enable role-based device verification for DBs * Add TODO for better SSH error messages * Do not override device error on lib/kube/proxy * Run gci
93 lines
3.0 KiB
Go
93 lines
3.0 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 authz
|
|
|
|
import (
|
|
"sync"
|
|
|
|
"github.com/gravitational/trace"
|
|
log "github.com/sirupsen/logrus"
|
|
"golang.org/x/crypto/ssh"
|
|
|
|
"github.com/gravitational/teleport"
|
|
"github.com/gravitational/teleport/api/constants"
|
|
"github.com/gravitational/teleport/api/types"
|
|
"github.com/gravitational/teleport/lib/devicetrust/config"
|
|
"github.com/gravitational/teleport/lib/tlsca"
|
|
)
|
|
|
|
// IsTLSDeviceVerified returns true if ext contains all required device
|
|
// extensions.
|
|
func IsTLSDeviceVerified(ext *tlsca.DeviceExtensions) bool {
|
|
// Expect all device extensions to be present.
|
|
return ext != nil && ext.DeviceID != "" && ext.AssetTag != "" && ext.CredentialID != ""
|
|
}
|
|
|
|
// VerifyTLSUser verifies if the TLS identity has the required extensions to
|
|
// fulfill the device trust configuration.
|
|
func VerifyTLSUser(dt *types.DeviceTrust, identity tlsca.Identity) error {
|
|
return verifyDeviceExtensions(dt, identity.Username, IsTLSDeviceVerified(&identity.DeviceExtensions))
|
|
}
|
|
|
|
// IsSSHDeviceVerified returns true if cert contains all required device
|
|
// extensions.
|
|
func IsSSHDeviceVerified(cert *ssh.Certificate) bool {
|
|
// Expect all device extensions to be present.
|
|
return cert != nil &&
|
|
cert.Extensions[teleport.CertExtensionDeviceID] != "" &&
|
|
cert.Extensions[teleport.CertExtensionDeviceAssetTag] != "" &&
|
|
cert.Extensions[teleport.CertExtensionDeviceCredentialID] != ""
|
|
}
|
|
|
|
// VerifySSHUser verifies if the SSH certificate has the required extensions to
|
|
// fulfill the device trust configuration.
|
|
func VerifySSHUser(dt *types.DeviceTrust, cert *ssh.Certificate) error {
|
|
if cert == nil {
|
|
return trace.BadParameter("cert required")
|
|
}
|
|
|
|
username := cert.KeyId
|
|
return verifyDeviceExtensions(dt, username, IsSSHDeviceVerified(cert))
|
|
}
|
|
|
|
func verifyDeviceExtensions(dt *types.DeviceTrust, username string, verified bool) error {
|
|
mode := config.GetEffectiveMode(dt)
|
|
maybeLogModeMismatch(mode, dt)
|
|
|
|
switch {
|
|
case mode != constants.DeviceTrustModeRequired:
|
|
return nil // OK, extensions not enforced.
|
|
case !verified:
|
|
log.
|
|
WithField("User", username).
|
|
Debug("Device Trust: denied access for unidentified device")
|
|
return trace.AccessDenied("unauthorized device")
|
|
default:
|
|
return nil
|
|
}
|
|
}
|
|
|
|
var logModeOnce sync.Once
|
|
|
|
func maybeLogModeMismatch(effective string, dt *types.DeviceTrust) {
|
|
if dt == nil || dt.Mode == "" || effective == dt.Mode {
|
|
return
|
|
}
|
|
|
|
logModeOnce.Do(func() {
|
|
log.Warnf("Device Trust: mode %q requires Teleport Enterprise. Using effective mode %q.", dt.Mode, effective)
|
|
})
|
|
}
|