~tribaal/txaws/xss-hardening

« back to all changes in this revision

Viewing changes to txaws/ec2/client.py

  • Committer: Duncan McGreggor
  • Date: 2009-09-05 01:13:43 UTC
  • mfrom: (17 trunk)
  • mto: This revision was merged to the branch mainline in revision 19.
  • Revision ID: duncan@canonical.com-20090905011343-fvhohjrbf27wfqmv
Merged trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
from txaws.ec2.exception import EC2Error
22
22
 
23
23
 
24
 
__all__ = ['EC2Client']
 
24
__all__ = ["EC2Client"]
25
25
 
26
26
 
27
27
def ec2_error_wrapper(error):
54
54
 
55
55
    def describe_instances(self):
56
56
        """Describe current instances."""
57
 
        q = self.query_factory('DescribeInstances', self.creds, self.endpoint)
 
57
        q = self.query_factory("DescribeInstances", self.creds, self.endpoint)
58
58
        d = q.submit()
59
59
        return d.addCallback(self._parse_instances)
60
60
 
131
131
        instanceset = {}
132
132
        for pos, instance_id in enumerate(instance_ids):
133
133
            instanceset["InstanceId.%d" % (pos+1)] = instance_id
134
 
        q = self.query_factory('TerminateInstances', self.creds, self.endpoint,
 
134
        q = self.query_factory("TerminateInstances", self.creds, self.endpoint,
135
135
                               instanceset)
136
136
        d = q.submit()
137
137
        return d.addCallback(self._parse_terminate_instances)
279
279
 
280
280
    def describe_snapshots(self, *snapshot_ids):
281
281
        """Describe available snapshots."""
282
 
        snapshotset = {}
 
282
        snapshot_set = {}
283
283
        for pos, snapshot_id in enumerate(snapshot_ids):
284
 
            snapshotset["SnapshotId.%d" % (pos + 1)] = snapshot_id
 
284
            snapshot_set["SnapshotId.%d" % (pos + 1)] = snapshot_id
285
285
        q = self.query_factory(
286
 
            "DescribeSnapshots", self.creds, self.endpoint, snapshotset)
 
286
            "DescribeSnapshots", self.creds, self.endpoint, snapshot_set)
287
287
        d = q.submit()
288
288
        return d.addCallback(self._parse_snapshots)
289
289
 
354
354
            attach_time[:19], "%Y-%m-%dT%H:%M:%S")
355
355
        return {"status": status, "attach_time": attach_time}
356
356
 
 
357
    def describe_keypairs(self, *keypair_names):
 
358
        """Returns information about key pairs available."""
 
359
        keypair_set = {}
 
360
        for pos, keypair_name in enumerate(keypair_names):
 
361
            keypair_set["KeyPair.%d" % (pos + 1)] = keypair_name
 
362
        q = self.query_factory("DescribeKeyPairs", self.creds, self.endpoint,
 
363
                               keypair_set)
 
364
        d = q.submit()
 
365
        return d.addCallback(self._parse_describe_keypairs)
 
366
 
 
367
    def _parse_describe_keypairs(self, xml_bytes):
 
368
        results = []
 
369
        root = XML(xml_bytes)
 
370
        for keypair_data in root.find("keySet"):
 
371
            key_name = keypair_data.findtext("keyName")
 
372
            key_fingerprint = keypair_data.findtext("keyFingerprint")
 
373
            results.append(model.Keypair(key_name, key_fingerprint))
 
374
        return results
 
375
 
 
376
    def create_keypair(self, keypair_name):
 
377
        """
 
378
        Create a new 2048 bit RSA key pair and return a unique ID that can be
 
379
        used to reference the created key pair when launching new instances.
 
380
        """
 
381
        q = self.query_factory(
 
382
            "CreateKeyPair", self.creds, self.endpoint,
 
383
            {"KeyName": keypair_name})
 
384
        d = q.submit()
 
385
        return d.addCallback(self._parse_create_keypair)
 
386
 
 
387
    def _parse_create_keypair(self, xml_bytes):
 
388
        results = []
 
389
        keypair_data = XML(xml_bytes)
 
390
        key_name = keypair_data.findtext("keyName")
 
391
        key_fingerprint = keypair_data.findtext("keyFingerprint")
 
392
        key_material = keypair_data.findtext("keyMaterial")
 
393
        return model.Keypair(key_name, key_fingerprint, key_material)
 
394
 
 
395
    def delete_keypair(self, keypair_name):
 
396
        """Delete a given keypair."""
 
397
        q = self.query_factory(
 
398
            "DeleteKeyPair", self.creds, self.endpoint,
 
399
            {"KeyName": keypair_name})
 
400
        d = q.submit()
 
401
        return d.addCallback(self._parse_delete_keypair)
 
402
 
 
403
    def _parse_delete_keypair(self, xml_bytes):
 
404
        results = []
 
405
        keypair_data = XML(xml_bytes)
 
406
        result = keypair_data.findtext("return")
 
407
        if not result:
 
408
            result = False
 
409
        elif result.lower() == "true":
 
410
            result = True
 
411
        else:
 
412
            result = False
 
413
        return result
 
414
 
357
415
 
358
416
class Query(object):
359
417
    """A query that may be submitted to EC2."""
367
425
        if api_version is None:
368
426
            api_version = version.aws_api
369
427
        self.params = {
370
 
            'Version': api_version,
371
 
            'SignatureVersion': '2',
372
 
            'SignatureMethod': 'HmacSHA1',
373
 
            'Action': action,
374
 
            'AWSAccessKeyId': self.creds.access_key,
375
 
            'Timestamp': iso8601time(time_tuple),
 
428
            "Version": api_version,
 
429
            "SignatureVersion": "2",
 
430
            "SignatureMethod": "HmacSHA1",
 
431
            "Action": action,
 
432
            "AWSAccessKeyId": self.creds.access_key,
 
433
            "Timestamp": iso8601time(time_tuple),
376
434
            }
377
435
        if other_params:
378
436
            self.params.update(other_params)
382
440
        """Return the canonical query params (used in signing)."""
383
441
        result = []
384
442
        for key, value in self.sorted_params():
385
 
            result.append('%s=%s' % (self.encode(key), self.encode(value)))
386
 
        return '&'.join(result)
 
443
            result.append("%s=%s" % (self.encode(key), self.encode(value)))
 
444
        return "&".join(result)
387
445
 
388
446
    def encode(self, a_string):
389
447
        """Encode a_string as per the canonicalisation encoding rules.
391
449
        See the AWS dev reference page 90 (2008-12-01 version).
392
450
        @return: a_string encoded.
393
451
        """
394
 
        return quote(a_string, safe='~')
 
452
        return quote(a_string, safe="~")
395
453
 
396
454
    def signing_text(self):
397
455
        """Return the text to be signed when signing the query."""
407
465
        submitting the query. Signing is done automatically - this is a public
408
466
        method to facilitate testing.
409
467
        """
410
 
        self.params['Signature'] = self.creds.sign(self.signing_text())
 
468
        self.params["Signature"] = self.creds.sign(self.signing_text())
411
469
 
412
470
    def sorted_params(self):
413
471
        """Return the query params sorted appropriately for signing."""