myENA / consul-backinator

Command line Consul backup and restore utility supporting KVs, ACLs and Queries
Mozilla Public License 2.0
226 stars 22 forks source link

Allow use of AWS IAM roles #27

Closed mickengland closed 7 years ago

mickengland commented 7 years ago

I am setting up backups from a Jenkins instance in EC2 that has an associated role allowing it to write to the consul-backups S3 bucket. I would like to have consul-backinator use the role rather than asking for credentials.

aaronhurt commented 7 years ago

@mickengland The latest release is using the official AWS SDK and should support IAM profiles. How are you executing consul-backinator?

aaronhurt commented 7 years ago

In theory using the official aws-sdk-go package should make consul-backinator behave very similar to the AWS CLI as documented here: http://docs.aws.amazon.com/cli/latest/topic/config-vars.html

Have you tried setting the AWS_PROFILE environment variable?

mickengland commented 7 years ago

I believe AWS_PROFILE is used for pointing to a specific profile in .aws/config and .aws/credentials. I am wanting to use IAM Roles assigned to an EC2 instance not profile credentials. I can use the AWS Cli with no credentials on the instance at all. I am currently doing a local backup and then an aws s3 sync which works with no credentials. I would like to be able to just run something like this:

$ consul-backinator backup -file s3://my-bucket/path/to/object?region=us-east-1

and let it use the permissions associated with the instance profile through IAM Roles. The process is documented here.

aaronhurt commented 7 years ago

I see, I was assuming that the session mechanism of the official API looked for the IAM information by default. However, from your testing that does not seem to be the case.

I'll need to look around for documentation and/or examples on using/defaulting to IAM credentials if available from within the aws-sdk-go packages.

aaronhurt commented 7 years ago

@mickengland sorry for the delay in testing but this works just as you described in my test ec2 instance:

[ec2-user@ip-172-31-70-104 consul-backinator]$ ./consul-backinator backup -file s3://ahurt-testing/junk/backup?region=us-east-1
2017/06/09 18:25:20 [Success] Backed up 1 keys from / to s3://ahurt-testing/junk/backup?region=us-east-1
Keep your backup and signature files in a safe place.
You will need both to restore your data.
[ec2-user@ip-172-31-70-104 consul-backinator]$ ./consul-backinator dump -file s3://ahurt-testing/junk/backup?region=us-east-1
[
  {
    "Key": "testing",
    "CreateIndex": 422,
    "ModifyIndex": 422,
    "LockIndex": 0,
    "Flags": 0,
    "Value": "aGVsbG8=",
    "Session": ""
  }
]
[ec2-user@ip-172-31-70-104 consul-backinator]$

I tested this with a new t2.micro instance associated with a simple IAM profile that just allowed full access to the s3 service.

aaronhurt commented 7 years ago

@mickengland just checking in to see if you are still having this issue?

mickengland commented 7 years ago

Thanks. I will test this again today and let you know.

aaronhurt commented 7 years ago

I was just using the latest release version 1.6 code in my test. I'm also thinking about removing the requirement to pass the region. Forcing the region to be passed doesn't make much sense in the case of AWS+IAM and any other endpoint should complain if it can't determine the final destination.

mickengland commented 7 years ago

Hmm this is still not working for me with version 1.6 and an IAM role that allows write access to my bucket. The aws s3 cp command is working fine but backinator gives:

[Error] Failed to dump data: AccessDenied: Access Denied I am working round this by doing a local backup and the using the cli to push to S3.

aaronhurt commented 7 years ago

I think this is a permission issue ... would you mind pasting your IAM profile? In testing I was using a very simple profile:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "s3:*",
            "Resource": "*"
        }
    ]
}
aaronhurt commented 7 years ago

That error Failed to dump data means you are trying to do a dump operation. That will require read access to the bucket. The rest of the message AccessDenied: Access Denied is coming from the aws-sdk-go package which is relaying the error from the upstream S3 endpoint.

jamiesonio commented 7 years ago

So conventional s3 read/write permissioning for IAM does not seem to work in this case, I have managed to get this working with an instance role using the below IAM permissions. The issue that was encountered was that Backinator must have "s3:CreateBucket" permissions on the target s3 bucket otherwise it will receive an IAM permission error when it attempts to create the bucket

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetBucketLocation",
                "s3:ListAllMyBuckets"
            ],
            "Resource": "arn:aws:s3:::*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket",
                "s3:CreateBucket"
            ],
            "Resource": [
                "arn:aws:s3:::$BucketName"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:*"
            ],
            "Resource": [
                "arn:aws:s3:::$BucketName/*"
            ]
        }
    ]
}
aaronhurt commented 7 years ago

@jamiesonio nice find. I thought the code returned should be the s3.ErrCodeBucketAlreadyExists if it already existed which should mean that execution would continue. Let me do some more investigation in my own instance.

aaronhurt commented 7 years ago

@jamiesonio @mickengland This now makes sense. Thank you for the policy dump - that really helped. I'm no longer failing just because we don't have permission to create the bucket. I can now successfully perform a backup operation using your above policy WITHOUT the CreateBucket permission. Please re-open if the latest commit does not fix the issue.

aaronhurt commented 7 years ago

@jamiesonio @mickengland confirmation would also be appreciated if you have the time. Thank you again.

jamiesonio commented 7 years ago

@leprechau - I have tested the latest with the below IAM policy and can confirm it is working as expected. Thank you very much for the fix.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetBucketLocation",
                "s3:ListAllMyBuckets"
            ],
            "Resource": "arn:aws:s3:::*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::$BucketName"
            ]
        },
        {
            "Effect": "Allow",
      "Action": [
        "s3:PutObject",
        "s3:GetObject",
        "s3:DeleteObject"
      ],
            "Resource": [
                "arn:aws:s3:::$BucketName/*"
            ]
        }
    ]
}
aaronhurt commented 7 years ago

@jamiesonio awesome, thank you!