mirror of
https://github.com/gravitational/teleport.git
synced 2026-10-25 10:40:02 +08:00
114 lines
3.5 KiB
Go
114 lines
3.5 KiB
Go
/*
|
|
* Teleport
|
|
* Copyright (C) 2026 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 server
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
|
|
ststypes "github.com/aws/aws-sdk-go-v2/service/sts/types"
|
|
"github.com/gravitational/trace"
|
|
|
|
utilsaws "github.com/gravitational/teleport/lib/utils/aws"
|
|
)
|
|
|
|
// EC2IAMPermissionError is a structured IAM permission error from EC2 discovery.
|
|
type EC2IAMPermissionError struct {
|
|
// Integration is the AWS integration used by discovery.
|
|
Integration string
|
|
// AccountID is the AWS account ID associated with the permission error.
|
|
AccountID string
|
|
// Region is the AWS region associated with the permission error, if known.
|
|
Region string
|
|
// IssueType is the UserTask issue type for the permission error.
|
|
IssueType string
|
|
// DiscoveryConfigName is the DiscoveryConfig name that produced the permission error.
|
|
DiscoveryConfigName string
|
|
// CallerARN is the AWS caller identity ARN used for the failed discovery call.
|
|
CallerARN string
|
|
// Err is the underlying AWS or Teleport error.
|
|
Err error
|
|
}
|
|
|
|
// Error formats the permission error as a human-readable string, including the
|
|
// integration and region (if set), issue type, account ID, and underlying error.
|
|
func (e *EC2IAMPermissionError) Error() string {
|
|
integrationPrefix := ""
|
|
if e.Integration != "" {
|
|
integrationPrefix = fmt.Sprintf("integration %s: ", e.Integration)
|
|
}
|
|
|
|
if e.Region != "" {
|
|
return fmt.Sprintf("%sIAM permission error (%s) for account %s in region %s: %v",
|
|
integrationPrefix, e.IssueType, e.AccountID, e.Region, e.Err)
|
|
}
|
|
|
|
return fmt.Sprintf("%sIAM permission error (%s) for account %s: %v",
|
|
integrationPrefix, e.IssueType, e.AccountID, e.Err)
|
|
}
|
|
|
|
// Unwrap returns the underlying error that triggered the permission failure.
|
|
// This is typically an AWS SDK request error.
|
|
func (e *EC2IAMPermissionError) Unwrap() error {
|
|
return e.Err
|
|
}
|
|
|
|
// EC2IAMPermissionErrors returns EC2 IAM permission errors found in err.
|
|
func EC2IAMPermissionErrors(err error) []*EC2IAMPermissionError {
|
|
if err == nil {
|
|
return nil
|
|
}
|
|
|
|
var aggregate trace.Aggregate
|
|
if errors.As(err, &aggregate) {
|
|
var permissionErrors []*EC2IAMPermissionError
|
|
for _, err := range aggregate.Errors() {
|
|
permissionErrors = append(permissionErrors, EC2IAMPermissionErrors(err)...)
|
|
}
|
|
return permissionErrors
|
|
}
|
|
|
|
var permissionError *EC2IAMPermissionError
|
|
if errors.As(err, &permissionError) {
|
|
return []*EC2IAMPermissionError{permissionError}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func isEC2DiscoveryPermissionError(err error) bool {
|
|
if trace.IsAccessDenied(err) {
|
|
return true
|
|
}
|
|
|
|
var invalidIdentityTokenErr *ststypes.InvalidIdentityTokenException
|
|
return errors.As(err, &invalidIdentityTokenErr)
|
|
}
|
|
|
|
// accountIDFromRoleARN extracts the AWS account ID from a role ARN.
|
|
// It returns "unknown" when the account ID cannot be determined.
|
|
func accountIDFromRoleARN(roleARN string) string {
|
|
parsed, err := utilsaws.ParseRoleARN(roleARN)
|
|
if err != nil {
|
|
return "unknown"
|
|
}
|
|
|
|
return parsed.AccountID
|
|
}
|