From 5de7ed52929dfedba5dc0778b378837d9808f87e Mon Sep 17 00:00:00 2001 From: Vincent Viallet Date: Thu, 12 Dec 2013 12:23:58 +0800 Subject: [PATCH] Add ec2_key module. --- cloud/ec2_key | 211 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 cloud/ec2_key diff --git a/cloud/ec2_key b/cloud/ec2_key new file mode 100644 index 00000000000..7a4926171f2 --- /dev/null +++ b/cloud/ec2_key @@ -0,0 +1,211 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + + +DOCUMENTATION = ''' +--- +module: ec2_key +version_added: "1.3" +short_description: maintain an ec2 key pair. +description: + - maintains ec2 key pairs. This module has a dependency on python-boto >= 2.5 +options: + name: + description: + - Name of the key pair. + required: true + key_material: + description: + - Public key material. + required: false + region: + description: + - the EC2 region to use + required: false + default: null + aliases: [] + ec2_url: + description: + - Url to use to connect to EC2 or your Eucalyptus cloud (by default the module will use EC2 endpoints) + required: false + default: null + aliases: [] + ec2_secret_key: + description: + - EC2 secret key + required: false + default: null + aliases: ['aws_secret_key'] + ec2_access_key: + description: + - EC2 access key + required: false + default: null + aliases: ['aws_access_key'] + state: + version_added: "1.4" + description: + - create or delete security group + required: false + default: 'present' + aliases: [] + +requirements: [ "boto" ] +author: Vincent Viallet +''' + +EXAMPLES = ''' +# Creates a new ec2 key pair named `example` if not present, returns generated +# private key +- name: example ec2 key + local_action: + module: ec2_key + name: example + region: eu-west-1a + ec2_secret_key: SECRET + ec2_access_key: ACCESS + +# Creates a new ec2 key pair named `example` if not present using provided key +# material +- name: example2 ec2 key + local_action: + module: ec2_key + name: example2 + region: eu-west-1a + ec2_secret_key: SECRET + ec2_access_key: ACCESS + key_material: 'ssh-rsa AAAAxyz...== me@example.com' + state: present + +# Creates a new ec2 key pair named `example` if not present using provided key +# material +- name: example3 ec2 key + local_action: + module: ec2_key + name: example3 + region: eu-west-1a + ec2_secret_key: SECRET + ec2_access_key: ACCESS + key_material: "{{ item }}" + with_file: /path/to/public_key.id_rsa.pub + +# Removes ec2 key pair by name +- name: remove example key + local_action: + module: ec2_key + name: example + state: absent + region: eu-west-1a + ec2_secret_key: SECRET + ec2_access_key: ACCESS +''' + +try: + import boto.ec2 +except ImportError: + print "failed=True msg='boto required for this module'" + sys.exit(1) + +# Required if importing key +import base64 + +def main(): + module = AnsibleModule( + argument_spec=dict( + name=dict(required=True), + key_material=dict(required=False), + ec2_url=dict(aliases=['EC2_URL']), + ec2_secret_key=dict(aliases=['EC2_SECRET_KEY', 'aws_secret_key'], no_log=True), + ec2_access_key=dict(aliases=['EC2_ACCESS_KEY', 'aws_access_key']), + region=dict(choices=['eu-west-1', 'sa-east-1', 'us-east-1', 'ap-northeast-1', 'us-west-2', 'us-west-1', 'ap-southeast-1', 'ap-southeast-2']), + state = dict(default='present', choices=['present', 'absent']), + ), + supports_check_mode=True, + ) + + # def get_ec2_creds(module): + # return ec2_url, ec2_access_key, ec2_secret_key, region + ec2_url, ec2_access_key, ec2_secret_key, region = get_ec2_creds(module) + + name = module.params['name'] + state = module.params.get('state') + key_material = module.params.get('key_material') + + changed = False + + # If we have a region specified, connect to its endpoint. + if region: + try: + ec2 = boto.ec2.connect_to_region(region, aws_access_key_id=ec2_access_key, aws_secret_access_key=ec2_secret_key) + except boto.exception.NoAuthHandlerFound, e: + module.fail_json(msg=str(e)) + # Otherwise, no region so we fallback to the old connection method + else: + try: + if ec2_url: # if we have an URL set, connect to the specified endpoint + ec2 = boto.connect_ec2_endpoint(ec2_url, ec2_access_key, ec2_secret_key) + else: # otherwise it's Amazon. + ec2 = boto.connect_ec2(ec2_access_key, ec2_secret_key) + except boto.exception.NoAuthHandlerFound, e: + module.fail_json(msg=str(e)) + + # find the key if present + key = ec2.get_key_pair(name) + + # Ensure requested key is absent + if state == 'absent': + if key: + '''found a match, delete it''' + try: + key.delete() + except Exception, e: + module.fail_json(msg="Unable to key pair '%s' - %s" % (key, e)) + else: + key = None + changed = True + else: + '''no match found, no changes required''' + + # Ensure requested group is present + elif state == 'present': + if key: + '''existing key found''' + # Should check if the fingerprint is the same - but lack of info + # and different fingerprint provided (pub or private) depending if + # the key has been created of imported. + pass + + # if the group doesn't exist, create it now + else: + '''no match found, create it''' + if not module.check_mode: + if key_material: + '''We are providing the key, need to import''' + key = ec2.import_key_pair(name, key_material) + else: + ''' + No material provided, let AWS handle the key creation and + retrieve the private key + ''' + key = ec2.create_key_pair(name) + changed = True + else: + module.fail_json(msg="Unsupported state requested: %s" % state) + + if key: + data = { + 'name': key.name, + 'fingerprint': key.fingerprint + } + if key.material: + data.update({'private_key': key.material}) + + module.exit_json(changed=changed, key=data) + else: + module.exit_json(changed=changed, key=None) + +# import module snippets +from ansible.module_utils.basic import * +from ansible.module_utils.ec2 import * + +main()