Permalink
Browse files

Merge pull request #127 from dudyk/IAM

Add support for IAM roles and temp tokens
  • Loading branch information...
2 parents 701cde0 + dc590d6 commit 0af72ed6a6ef9366743d727a53f49995414e1254 @mludvig mludvig committed Mar 3, 2013
Showing with 81 additions and 1 deletion.
  1. +4 −0 S3/CloudFront.py
  2. +71 −1 S3/Config.py
  3. +3 −0 S3/S3.py
  4. +3 −0 S3/SimpleDB.py
View
4 S3/CloudFront.py
@@ -534,6 +534,10 @@ def create_request(self, operation, dist_id = None, request_id = None, headers =
if not headers.has_key("x-amz-date"):
headers["x-amz-date"] = time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime())
+ if len(self.config.access_token)>0:
+ self.config.refresh_role()
+ headers['x-amz-security-token']=self.config.access_token
+
signature = self.sign_request(headers)
headers["Authorization"] = "AWS "+self.config.access_key+":"+signature
View
72 S3/Config.py
@@ -7,15 +7,19 @@
from logging import debug, info, warning, error
import re
import os
+import sys
import Progress
from SortedDict import SortedDict
+import httplib
+import json
class Config(object):
_instance = None
_parsed_files = []
_doc = {}
access_key = ""
secret_key = ""
+ access_token = ""
host_base = "s3.amazonaws.com"
host_bucket = "%(bucket)s.s3.amazonaws.com"
simpledb_host = "sdb.amazonaws.com"
@@ -103,7 +107,73 @@ def __new__(self, configfile = None):
def __init__(self, configfile = None):
if configfile:
- self.read_config_file(configfile)
+ try:
+ self.read_config_file(configfile)
+ except IOError, e:
+ if 'AWS_CREDENTIAL_FILE' in os.environ:
+ self.env_config()
+ if len(self.access_key)==0:
+ self.role_config()
+
+ def role_config(self):
+ conn = httplib.HTTPConnection(host='169.254.169.254',timeout=0.1)
+ try:
+ conn.request('GET', "/latest/meta-data/iam/security-credentials/")
+ resp = conn.getresponse()
+ files = resp.read()
+ if resp.status == 200 and len(files)>1:
+ conn.request('GET', "/latest/meta-data/iam/security-credentials/%s"%files)
+ resp=conn.getresponse()
+ if resp.status == 200:
+ creds=json.load(resp)
+ Config().update_option('access_key', creds['AccessKeyId'].encode('ascii'))
+ Config().update_option('secret_key', creds['SecretAccessKey'].encode('ascii'))
+ Config().update_option('access_token', creds['Token'].encode('ascii'))
+ else:
+ raise IOError
+ else:
+ raise IOError
+ except:
+ raise
+
+ def role_refresh(self):
+ try:
+ self.role_config()
+ except:
+ warning("Could not refresh role")
+
+ def env_config(self):
+ cred_content = ""
+ try:
+ cred_file = open(os.environ['AWS_CREDENTIAL_FILE'],'r')
+ cred_content = cred_file.read()
+ except IOError, e:
+ debug("Error %d accessing credentials file %s" % (e.errno,os.environ['AWS_CREDENTIAL_FILE']))
+ r_data = re.compile("^\s*(?P<orig_key>\w+)\s*=\s*(?P<value>.*)")
+ r_quotes = re.compile("^\"(.*)\"\s*$")
+ if len(cred_content)>0:
+ for line in cred_content.splitlines():
+ is_data = r_data.match(line)
+ is_data = r_data.match(line)
+ if is_data:
+ data = is_data.groupdict()
+ if r_quotes.match(data["value"]):
+ data["value"] = data["value"][1:-1]
+ if data["orig_key"]=="AWSAccessKeyId":
+ data["key"] = "access_key"
+ elif data["orig_key"]=="AWSSecretKey":
+ data["key"] = "secret_key"
+ else:
+ del data["key"]
+ if "key" in data:
+ Config().update_option(data["key"], data["value"])
+ if data["key"] in ("access_key", "secret_key", "gpg_passphrase"):
+ print_value = (data["value"][:2]+"...%d_chars..."+data["value"][-1:]) % (len(data["value"]) - 3)
+ else:
+ print_value = data["value"]
+ debug("env_Config: %s->%s" % (data["key"], print_value))
+
+
def option_list(self):
retval = []
View
3 S3/S3.py
@@ -92,6 +92,9 @@ def __init__(self, s3, method_string, resource, headers, params = {}):
# Add in any extra headers from s3 config object
if self.s3.config.extra_headers:
self.headers.update(self.s3.config.extra_headers)
+ if len(self.s3.config.access_token)>0:
+ self.s3.config.role_refresh()
+ self.headers['x-amz-security-token']=self.s3.config.access_token
self.resource = resource
self.method_string = method_string
self.params = params
View
3 S3/SimpleDB.py
@@ -131,6 +131,9 @@ def send_request(self, *args, **kwargs):
def create_request(self, Action, DomainName, parameters = None):
if not parameters:
parameters = SortedDict()
+ if len(self.config.access_token) > 0:
+ self.config.refresh_role()
+ parameters['Signature']=self.config.access_token
parameters['AWSAccessKeyId'] = self.config.access_key
parameters['Version'] = self.Version
parameters['SignatureVersion'] = self.SignatureVersion

0 comments on commit 0af72ed

Please sign in to comment.