Files
upstream-seaweedfs/weed/iam/utils/arn_utils.go
upstream-mirror 89f5be005d
Some checks failed
go: build dev binaries / cleanup (push) Successful in 4s
Codespell / Check for spelling errors (push) Failing after 3s
docker: build dev containers / build-rust-binaries (amd64, x86_64-unknown-linux-musl) (push) Failing after 3s
docker: build dev containers / build-dev-containers (push) Has been skipped
docker: build dev containers / build-rust-binaries (arm64, true, aarch64-unknown-linux-musl) (push) Failing after 3s
End to End / FUSE Mount (push) Failing after 2s
EC Integration Tests / EC Integration Tests (push) Failing after 30s
FUSE DLM Integration Tests / FUSE DLM Integration Tests (push) Failing after 3s
FUSE Volume Server Failover Tests / FUSE Volume Server Failover (push) Failing after 3s
FUSE Integration Tests / FUSE Integration Testing (push) Failing after 2s
FUSE P2P Peer Chunk Sharing Integration Tests / FUSE P2P Peer Chunk Sharing (push) Failing after 3s
go: build binary / Go Vet (push) Failing after 2s
go: build binary / Go Vet 32-bit (push) Failing after 3s
go: build binary / Build (push) Failing after 4s
go: build binary / Build cross-platform (freebsd/amd64) (push) Failing after 3s
go: build binary / Build cross-platform (windows/amd64) (push) Failing after 3s
go: build binary / Build cross-platform (darwin/arm64) (push) Failing after 3s
go: build binary / Build cross-platform (windows/arm64) (push) Failing after 3s
go: build binary / Test (push) Failing after 2s
go: build binary / Test 32-bit (push) Failing after 3s
helm: lint and test charts / lint-test (push) Failing after 3s
Java Client Integration Tests / Java Integration Tests (11) (push) Failing after 3s
Java Client Integration Tests / Java Integration Tests (17) (push) Failing after 3s
go: build dev binaries / build_dev_linux_windows (amd64, linux) (push) Failing after 2s
go: build dev binaries / build_dev_linux_windows (amd64, windows) (push) Failing after 3s
go: build dev binaries / build_dev_darwin (amd64, darwin) (push) Has been skipped
go: build dev binaries / build_dev_darwin (arm64, darwin) (push) Has been skipped
Java Client Unit Tests / Java Unit Tests (11) (push) Failing after 3s
Java Client Unit Tests / Java Unit Tests (17) (push) Failing after 2s
Java Client Unit Tests / Java Unit Tests (21) (push) Failing after 3s
Java Client Unit Tests / Java Unit Tests (8) (push) Failing after 3s
Kafka Quick Test (Load Test with Schema Registry) / Kafka Client Load Test (Quick) (push) Failing after 3s
Kafka Gateway Tests / Kafka Unit Tests (unit-tests-1) (push) Failing after 11s
Kafka Gateway Tests / Kafka Integration Tests (Critical) (integration-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka End-to-End Tests (with SMQ) (e2e-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka Consumer Group Tests (Highly Isolated) (consumer-group-1) (push) Failing after 2s
Kafka Gateway Tests / Kafka Client Compatibility (with SMQ) (client-compat-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka SMQ Integration Tests (Full Stack) (smq-integration-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka Protocol Tests (Isolated) (protocol-1) (push) Failing after 3s
KMS Tests / KMS Provider Integration Tests (push) Failing after 2s
KMS Tests / S3 KMS End-to-End Tests (push) Failing after 3s
Master Cold Start Tests / Master Cold Start Tests (push) Failing after 4s
Metadata Subscribe Integration Tests / Metadata Subscribe Integration Tests (push) Failing after 3s
Multi-Master Tests / Multi-Master Failover Tests (push) Failing after 3s
Performance / CPU and Heap Profile (push) Failing after 2s
Performance / S3 Read/Write Benchmark (rust volume) (push) Failing after 3s
pjdfstest POSIX Compliance / pjdfstest (push) Failing after 2s
Plugin Worker Integration Tests / Plugin Worker: erasure_coding (push) Failing after 3s
Plugin Worker Integration Tests / Plugin Worker: vacuum (push) Failing after 3s
Rust Volume Server Tests / Rust Integration Tests (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 1) (push) Failing after 2s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 1) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 2) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 2) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 3) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Distributed Tests (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Performance Tests (push) Failing after 3s
Performance / Throughput Benchmark (go volume) (push) Failing after 3s
Performance / Throughput Benchmark (rust volume) (push) Failing after 2s
Performance / S3 Read/Write Benchmark (go volume) (push) Failing after 3s
Plugin Worker Integration Tests / Plugin Worker: volume_balance (push) Failing after 3s
PostgreSQL Gateway Tests / PostgreSQL Basic Tests (push) Failing after 3s
Rust Volume Server Tests / Rust Unit Tests (push) Failing after 2s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 3) (push) Failing after 3s
Rust Plugin Worker Tests / Rust Plugin Worker Build and Unit Tests (push) Failing after 3s
rust: build dev volume server binaries / cleanup (push) Successful in 3s
S3 ETag and ACL Tests / S3 ETag + ACL Integration Tests (push) Failing after 3s
S3 IAM Integration Tests / IAM Unit Tests (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (advanced) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (basic) (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Integration Tests (group) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (policy-enforcement) (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Integration Tests (sts) (push) Failing after 4s
S3 Keycloak Integration Tests / S3 Keycloak Integration Tests (push) Failing after 3s
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.11) (push) Failing after 3s
S3 PyArrow Parquet Tests / Go Unit Tests (Implicit Directory) (push) Has been cancelled
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.12) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-darwin (darwin-amd64, x86_64-apple-darwin) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-darwin (darwin-arm64, aarch64-apple-darwin) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-linux (linux-amd64, x86_64-unknown-linux-gnu) (push) Has been cancelled
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.9) (push) Has been cancelled
S3 Proxy Signature Tests / S3 Proxy Signature Verification Tests (push) Has been cancelled
S3 SDK V2 Route Disambiguation Tests / S3 SDK V2 Routing Tests (push) Has been cancelled
S3 SSE Tests / S3 SSE Integration Tests (quick) (push) Has been cancelled
S3 SSE Tests / S3 SSE Compatibility Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Metadata Persistence Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Copy Operations Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Multipart Upload Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Performance Test (push) Has been cancelled
S3 SSE Tests / S3 Volume Encryption Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Integration Tests (comprehensive) (push) Has been cancelled
Spark Integration Tests / Spark Integration Tests (push) Failing after 2s
Telemetry Integration Tests / telemetry-integration-test (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 1) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 1) (push) Failing after 3s
Ceph S3 tests / Basic S3 tests (KV store) (push) Has been cancelled
Ceph S3 tests / S3 Versioning & Object Lock tests (push) Has been cancelled
S3 Policy Integration Tests / S3 Policy Unit Tests (push) Failing after 3s
Ceph S3 tests / S3 CORS tests (push) Has been cancelled
Ceph S3 tests / SeaweedFS Custom S3 Copy tests (push) Has been cancelled
Ceph S3 tests / Basic S3 tests (SQL store) (push) Has been cancelled
test s3 over https using aws-cli / awscli-tests (push) Has been cancelled
TLS Rotation Integration Tests / TLS Rotation Integration Tests (push) Has been cancelled
Vacuum Integration Tests / Vacuum Integration Tests (push) Has been cancelled
S3 Policy Integration Tests / S3 Policy Variables Integration Tests (push) Failing after 3s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (advanced-policy) (push) Failing after 3s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (basic-policy) (push) Failing after 2s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (contextual-policy) (push) Failing after 4s
S3 Policy Integration Tests / Trusted Proxy Detection Tests (push) Failing after 2s
S3 Policy Integration Tests / S3 Policy Shell Integration Tests (push) Failing after 3s
Samba on FUSE Integration / samba-integration (push) Failing after 2s
SFTP Integration Tests / SFTP Integration Testing (push) Failing after 3s
terraform: validate and test modules / fmt, validate, plan-level tests (push) Failing after 3s
terraform: validate and test modules / local cluster smoke test (real weed) (push) Failing after 2s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 3) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 2) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 2) (push) Failing after 2s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 3) (push) Failing after 5s
mount: windows conformance / WinFsp conformance (push) Has been cancelled
mount: windows / Mount on Windows (push) Has been cancelled
snapshot of https://github.com/seaweedfs/seaweedfs.git (master, 2026-09-16; blobs > 131072B omitted)
2026-09-16 03:23:42 +05:00

297 lines
9.8 KiB
Go

// Package utils provides utility functions for AWS IAM ARN parsing and role extraction.
package utils
import "strings"
// ARN parsing constants for AWS IAM and STS services
const (
// stsPrefix is the common prefix for all AWS STS ARNs
stsPrefix = "arn:aws:sts::"
// stsAssumedRoleMarker is the marker that identifies assumed role ARNs
stsAssumedRoleMarker = "assumed-role/"
// iamPrefix is the common prefix for all AWS IAM ARNs
iamPrefix = "arn:aws:iam::"
// iamRoleMarker is the marker that identifies IAM role ARNs
iamRoleMarker = "role/"
// iamUserMarker is the marker that identifies IAM user ARNs
iamUserMarker = "user/"
)
// ARNInfo contains structured information about a parsed AWS ARN.
// This provides more context than a simple string extraction, making it
// easier to debug issues and support different ARN formats.
type ARNInfo struct {
// Original is the original ARN string that was parsed
Original string
// RoleName is the extracted role name (without "role/" prefix)
// May include path components (e.g., "Division/Team/RoleName")
// Empty string indicates an invalid ARN
RoleName string
// AccountID is the AWS account ID if present in the ARN
// Empty string for legacy format ARNs (arn:aws:iam::role/Name)
// Non-empty for standard format ARNs (arn:aws:iam::ACCOUNT:role/Name)
AccountID string
}
// ExtractRoleNameFromPrincipal extracts the role name from an AWS principal ARN.
//
// It handles both STS assumed role and IAM role ARN formats, supporting both
// legacy (without account ID) and standard AWS (with account ID) formats:
// - arn:aws:sts::assumed-role/RoleName/SessionName (legacy STS format)
// - arn:aws:sts::ACCOUNT:assumed-role/RoleName/SessionName (standard STS format)
// - arn:aws:iam::role/RoleName (legacy IAM format)
// - arn:aws:iam::ACCOUNT:role/RoleName (standard IAM format)
//
// For STS assumed-role ARNs, it extracts the role name from the "assumed-role/"
// component, which is the second part of the path (e.g., "Role" from
// "arn:aws:sts::ACCOUNT:assumed-role/Role/Session"). For IAM role ARNs, it
// delegates to ExtractRoleNameFromArn.
//
// Returns an empty string if the principal format is invalid or unrecognized.
//
// Parameters:
// - principal: The AWS principal ARN string to extract the role name from
//
// Returns:
// - The extracted role name (without "role/" prefix)
// - Empty string if the principal is invalid or no role name is found
func ExtractRoleNameFromPrincipal(principal string) string {
// Handle STS assumed role format
if strings.HasPrefix(principal, stsPrefix) {
remainder := principal[len(stsPrefix):]
// Validate ARN structure: should be either "assumed-role/..." or "ACCOUNT:assumed-role/..."
// Split on ':' to separate account ID (if present) from resource type
resourcePart := remainder
if colonIdx := strings.Index(remainder, ":"); colonIdx != -1 {
// Standard format with account ID: "ACCOUNT:assumed-role/..."
resourcePart = remainder[colonIdx+1:]
}
// Verify the resource type is exactly "assumed-role/"
if !strings.HasPrefix(resourcePart, stsAssumedRoleMarker) {
return ""
}
// Extract role name after "assumed-role/"
afterMarker := resourcePart[len(stsAssumedRoleMarker):]
if slash := strings.Index(afterMarker, "/"); slash != -1 {
return afterMarker[:slash]
}
return afterMarker
}
// Handle IAM role format
return ExtractRoleNameFromArn(principal)
}
// ExtractUserNameFromPrincipal extracts the user name from an AWS IAM principal ARN.
//
// It handles both legacy and standard AWS IAM user ARN formats:
// - arn:aws:iam::user/UserName (legacy format without account ID)
// - arn:aws:iam::ACCOUNT:user/UserName (standard AWS format with account ID)
//
// Returns an empty string if the principal does not represent an IAM user.
func ExtractUserNameFromPrincipal(principal string) string {
if !strings.HasPrefix(principal, iamPrefix) {
return ""
}
remainder := principal[len(iamPrefix):]
resourcePart := remainder
if colonIdx := strings.Index(remainder, ":"); colonIdx != -1 {
resourcePart = remainder[colonIdx+1:]
}
if !strings.HasPrefix(resourcePart, iamUserMarker) {
return ""
}
userName := resourcePart[len(iamUserMarker):]
if userName == "" {
return ""
}
return userName
}
// ExtractRoleNameFromArn extracts the role name from an AWS IAM role ARN.
//
// It handles both legacy and standard AWS IAM role ARN formats:
// - arn:aws:iam::role/RoleName (legacy format without account ID)
// - arn:aws:iam::ACCOUNT:role/RoleName (standard AWS format with account ID)
//
// The function validates the ARN structure to ensure the resource type is exactly
// "role", preventing security issues where malicious ARNs like
// "arn:aws:iam::123456789012:user/role/malicious" could be accepted.
//
// If the ARN contains a path component (e.g., "role/Division/Team/RoleName"),
// the entire path is returned after "role/".
//
// Returns an empty string if:
// - The ARN does not start with "arn:aws:iam::"
// - The resource type is not exactly "role"
// - The input is empty or invalid
//
// This function is commonly used in STS (Security Token Service) role assumption
// validation to extract the role name from principal ARNs or to validate IAM
// role ARNs during credential assumption checks.
//
// Parameters:
// - roleArn: The IAM role ARN string to extract the role name from
//
// Returns:
// - The extracted role name (without "role/" prefix, may include path)
// - Empty string if the ARN is invalid or no role name is found
func ExtractRoleNameFromArn(roleArn string) string {
if !strings.HasPrefix(roleArn, iamPrefix) {
return ""
}
remainder := roleArn[len(iamPrefix):]
// Validate ARN structure: should be either "role/..." or "ACCOUNT:role/..."
// Split on ':' to separate account ID (if present) from resource type
resourcePart := remainder
if colonIdx := strings.Index(remainder, ":"); colonIdx != -1 {
// Standard format with account ID: "ACCOUNT:role/..."
resourcePart = remainder[colonIdx+1:]
}
// Verify the resource type is exactly "role/"
if !strings.HasPrefix(resourcePart, iamRoleMarker) {
return ""
}
// Extract role name after "role/"
return resourcePart[len(iamRoleMarker):]
}
// ParseRoleARN parses an AWS IAM role ARN and returns structured information.
//
// It handles both legacy and standard AWS IAM role ARN formats:
// - arn:aws:iam::role/RoleName (legacy format without account ID)
// - arn:aws:iam::ACCOUNT:role/RoleName (standard AWS format with account ID)
//
// The function validates the ARN structure to ensure the resource type is exactly
// "role", extracting the role name and account ID (if present).
//
// Parameters:
// - roleArn: The IAM role ARN string to parse
//
// Returns:
// - ARNInfo struct containing parsed information
// - RoleName will be empty if parsing fails or ARN is malformed
func ParseRoleARN(roleArn string) ARNInfo {
info := ARNInfo{
Original: roleArn,
}
if !strings.HasPrefix(roleArn, iamPrefix) {
return info
}
remainder := roleArn[len(iamPrefix):]
// Validate ARN structure: should be either "role/..." or "ACCOUNT:role/..."
// Split on ':' to separate account ID (if present) from resource type
resourcePart := remainder
accountPart := ""
if colonIdx := strings.Index(remainder, ":"); colonIdx != -1 {
// Standard format with account ID: "ACCOUNT:role/..."
accountPart = remainder[:colonIdx]
resourcePart = remainder[colonIdx+1:]
}
// Verify the resource type is exactly "role/"
if !strings.HasPrefix(resourcePart, iamRoleMarker) {
// Invalid resource type
return info
}
// Extract role name (everything after "role/")
info.RoleName = resourcePart[len(iamRoleMarker):]
if info.RoleName == "" {
// Empty role name is invalid
return info
}
// Set account ID if present
info.AccountID = accountPart
return info
}
// ParsePrincipalARN parses an AWS principal ARN (STS or IAM) and returns structured information.
//
// It handles both STS assumed role and IAM role ARN formats:
// - arn:aws:sts::assumed-role/RoleName/SessionName (legacy STS format)
// - arn:aws:sts::ACCOUNT:assumed-role/RoleName/SessionName (standard STS format)
// - arn:aws:iam::role/RoleName (legacy IAM format)
// - arn:aws:iam::ACCOUNT:role/RoleName (standard IAM format)
//
// The function validates the ARN structure to ensure the resource type is exactly
// "assumed-role" for STS or delegates to ParseRoleARN for IAM ARNs.
//
// Parameters:
// - principal: The AWS principal ARN string to parse
//
// Returns:
// - ARNInfo struct containing parsed information
// - RoleName will be empty if parsing fails or ARN is malformed
func ParsePrincipalARN(principal string) ARNInfo {
// Handle STS assumed role format
if strings.HasPrefix(principal, stsPrefix) {
info := ARNInfo{
Original: principal,
}
remainder := principal[len(stsPrefix):]
// Validate ARN structure: should be either "assumed-role/..." or "ACCOUNT:assumed-role/..."
// Split on ':' to separate account ID (if present) from resource type
resourcePart := remainder
accountPart := ""
if colonIdx := strings.Index(remainder, ":"); colonIdx != -1 {
// Standard format with account ID: "ACCOUNT:assumed-role/..."
accountPart = remainder[:colonIdx]
resourcePart = remainder[colonIdx+1:]
}
// Verify the resource type is exactly "assumed-role/"
if !strings.HasPrefix(resourcePart, stsAssumedRoleMarker) {
// Invalid resource type
return info
}
// Extract role name (between "assumed-role/" and next "/")
afterMarker := resourcePart[len(stsAssumedRoleMarker):]
if slash := strings.Index(afterMarker, "/"); slash != -1 {
info.RoleName = afterMarker[:slash]
} else {
info.RoleName = afterMarker
}
// Validate that role name is not empty
if info.RoleName == "" {
return info
}
// Set account ID if present
info.AccountID = accountPart
return info
}
// Handle IAM role format
return ParseRoleARN(principal)
}