mirror of
https://github.com/rclone/rclone.git
synced 2025-12-06 00:03:32 +00:00
s3: The ability to specify an IAM role for cross-account interaction
This commit is contained in:
committed by
GitHub
parent
f72b32b470
commit
a99d155fd4
@@ -30,9 +30,11 @@ import (
|
||||
v4signer "github.com/aws/aws-sdk-go-v2/aws/signer/v4"
|
||||
awsconfig "github.com/aws/aws-sdk-go-v2/config"
|
||||
"github.com/aws/aws-sdk-go-v2/credentials"
|
||||
"github.com/aws/aws-sdk-go-v2/credentials/stscreds"
|
||||
"github.com/aws/aws-sdk-go-v2/feature/s3/manager"
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3/types"
|
||||
"github.com/aws/aws-sdk-go-v2/service/sts"
|
||||
"github.com/aws/smithy-go"
|
||||
"github.com/aws/smithy-go/logging"
|
||||
"github.com/aws/smithy-go/middleware"
|
||||
@@ -325,6 +327,30 @@ If empty it will default to the environment variable "AWS_PROFILE" or
|
||||
Help: "An AWS session token.",
|
||||
Advanced: true,
|
||||
Sensitive: true,
|
||||
}, {
|
||||
Name: "role_arn",
|
||||
Help: `ARN of the IAM role to assume.
|
||||
|
||||
Leave blank if not using assume role.`,
|
||||
Advanced: true,
|
||||
}, {
|
||||
Name: "role_session_name",
|
||||
Help: `Session name for assumed role.
|
||||
|
||||
If empty, a session name will be generated automatically.`,
|
||||
Advanced: true,
|
||||
}, {
|
||||
Name: "role_session_duration",
|
||||
Help: `Session duration for assumed role.
|
||||
|
||||
If empty, the default session duration will be used.`,
|
||||
Advanced: true,
|
||||
}, {
|
||||
Name: "role_external_id",
|
||||
Help: `External ID for assumed role.
|
||||
|
||||
Leave blank if not using an external ID.`,
|
||||
Advanced: true,
|
||||
}, {
|
||||
Name: "upload_concurrency",
|
||||
Help: `Concurrency for multipart uploads and copies.
|
||||
@@ -927,6 +953,10 @@ type Options struct {
|
||||
SharedCredentialsFile string `config:"shared_credentials_file"`
|
||||
Profile string `config:"profile"`
|
||||
SessionToken string `config:"session_token"`
|
||||
RoleARN string `config:"role_arn"`
|
||||
RoleSessionName string `config:"role_session_name"`
|
||||
RoleSessionDuration fs.Duration `config:"role_session_duration"`
|
||||
RoleExternalID string `config:"role_external_id"`
|
||||
UploadConcurrency int `config:"upload_concurrency"`
|
||||
ForcePathStyle bool `config:"force_path_style"`
|
||||
V2Auth bool `config:"v2_auth"`
|
||||
@@ -1290,6 +1320,34 @@ func s3Connection(ctx context.Context, opt *Options, client *http.Client) (s3Cli
|
||||
opt.Region = "us-east-1"
|
||||
}
|
||||
|
||||
// Handle assume role if RoleARN is specified
|
||||
if opt.RoleARN != "" {
|
||||
fs.Debugf(nil, "Using assume role with ARN: %s", opt.RoleARN)
|
||||
|
||||
// Set region for the config before creating STS client
|
||||
awsConfig.Region = opt.Region
|
||||
|
||||
// Create STS client using the base credentials
|
||||
stsClient := sts.NewFromConfig(awsConfig)
|
||||
|
||||
// Configure AssumeRole options
|
||||
assumeRoleOptions := func(aro *stscreds.AssumeRoleOptions) {
|
||||
// Set session name if provided, otherwise use a default
|
||||
if opt.RoleSessionName != "" {
|
||||
aro.RoleSessionName = opt.RoleSessionName
|
||||
}
|
||||
if opt.RoleSessionDuration != 0 {
|
||||
aro.Duration = time.Duration(opt.RoleSessionDuration)
|
||||
}
|
||||
if opt.RoleExternalID != "" {
|
||||
aro.ExternalID = &opt.RoleExternalID
|
||||
}
|
||||
}
|
||||
|
||||
// Create AssumeRole credentials provider
|
||||
awsConfig.Credentials = stscreds.NewAssumeRoleProvider(stsClient, opt.RoleARN, assumeRoleOptions)
|
||||
}
|
||||
|
||||
provider = loadProvider(opt.Provider)
|
||||
if provider == nil {
|
||||
fs.Logf("s3", "s3 provider %q not known - please set correctly", opt.Provider)
|
||||
|
||||
@@ -745,6 +745,68 @@ If none of these option actually end up providing `rclone` with AWS
|
||||
credentials then S3 interaction will be non-authenticated (see the
|
||||
[anonymous access](#anonymous-access) section for more info).
|
||||
|
||||
#### Assume Role (Cross-Account Access)
|
||||
|
||||
If you need to access S3 resources in a different AWS account, you can use IAM role assumption.
|
||||
This is useful for cross-account access scenarios where you have credentials in one account
|
||||
but need to access resources in another account.
|
||||
|
||||
To use assume role, configure the following parameters:
|
||||
|
||||
- `role_arn` - The ARN (Amazon Resource Name) of the IAM role to assume in the target account.
|
||||
Format: `arn:aws:iam::ACCOUNT-ID:role/ROLE-NAME`
|
||||
- `role_session_name` (optional) - A name for the assumed role session. If not specified,
|
||||
rclone will generate one automatically.
|
||||
- `role_session_duration` (optional) - Duration for which the assumed role credentials are valid.
|
||||
If not specified, AWS default duration will be used (typically 1 hour).
|
||||
- `role_external_id` (optional) - An external ID required by the role's trust policy for additional security.
|
||||
This is typically used when the role is accessed by a third party.
|
||||
|
||||
The assume role feature works with both direct credentials (`env_auth = false`) and environment-based
|
||||
authentication (`env_auth = true`). Rclone will first authenticate using the base credentials, then
|
||||
use those credentials to assume the specified role.
|
||||
|
||||
Example configuration for cross-account access:
|
||||
|
||||
```
|
||||
[s3-cross-account]
|
||||
type = s3
|
||||
provider = AWS
|
||||
env_auth = true
|
||||
region = us-east-1
|
||||
role_arn = arn:aws:iam::123456789012:role/CrossAccountS3Role
|
||||
role_session_name = rclone-session
|
||||
role_external_id = unique-role-external-id-12345
|
||||
```
|
||||
|
||||
In this example:
|
||||
- Base credentials are obtained from the environment (IAM role, credentials file, or environment variables)
|
||||
- These credentials are then used to assume the role `CrossAccountS3Role` in account `123456789012`
|
||||
- An external ID is provided for additional security as required by the role's trust policy
|
||||
|
||||
The target role's trust policy in the destination account must allow the source account or user to assume it.
|
||||
Example trust policy:
|
||||
|
||||
```json
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "arn:aws:iam::SOURCE-ACCOUNT-ID:root"
|
||||
},
|
||||
"Action": "sts:AssumeRole",
|
||||
"Condition": {
|
||||
"StringEquals": {
|
||||
"sts:ExternalID": "unique-role-external-id-12345"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### S3 Permissions
|
||||
|
||||
When using the `sync` subcommand of `rclone` the following minimum
|
||||
|
||||
2
go.mod
2
go.mod
@@ -25,6 +25,7 @@ require (
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.18.21
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.20.4
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.90.0
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.39.1
|
||||
github.com/aws/smithy-go v1.23.2
|
||||
github.com/buengese/sgzip v0.1.1
|
||||
github.com/cloudinary/cloudinary-go/v2 v2.13.0
|
||||
@@ -133,7 +134,6 @@ require (
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.13 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.30.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.39.1 // indirect
|
||||
github.com/bahlo/generic-list-go v0.2.0 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bodgit/plumbing v1.3.0 // indirect
|
||||
|
||||
Reference in New Issue
Block a user