def test_name_validation(self): name = 'Test123 ()[]./-\'@_' self.assertEquals(name, aws_service.validate_image_name(name)) with self.assertRaises(aws_service.ImageNameError): aws_service.validate_image_name(None) with self.assertRaises(aws_service.ImageNameError): aws_service.validate_image_name('ab') with self.assertRaises(aws_service.ImageNameError): aws_service.validate_image_name('a' * 129) for c in '?!#$%^&*~`{}\|"<>': with self.assertRaises(aws_service.ImageNameError): aws_service.validate_image_name('test' + c)
def test_name_validation(self): name = "Test123 ()[]./-'@_" self.assertEquals(name, aws_service.validate_image_name(name)) with self.assertRaises(aws_service.ImageNameError): aws_service.validate_image_name(None) with self.assertRaises(aws_service.ImageNameError): aws_service.validate_image_name("ab") with self.assertRaises(aws_service.ImageNameError): aws_service.validate_image_name("a" * 129) for c in '?!#$%^&*~`{}\|"<>': with self.assertRaises(aws_service.ImageNameError): aws_service.validate_image_name("test" + c)
def _connect_and_validate(aws_svc, values, encryptor_ami_id): """ Connect to the AWS service and validate command-line options :param aws_svc: the BaseAWSService implementation :param values: object that was generated by argparse """ if values.encrypted_ami_name: try: aws_service.validate_image_name(values.encrypted_ami_name) except aws_service.ImageNameError as e: raise ValidationError(e.message) regions = [str(r.name) for r in aws_svc.get_regions()] if values.region not in regions: raise ValidationError( 'Invalid region %s. Must be one of %s.' % (values.region, str(regions))) aws_svc.connect(values.region, key_name=values.key_name) try: if values.key_name: aws_svc.get_key_pair(values.key_name) if values.validate: _validate_subnet_and_security_groups( aws_svc, values.subnet_id, values.security_group_ids) error_msg = aws_svc.validate_guest_ami(values.ami) if error_msg: raise ValidationError(error_msg) error_msg = aws_svc.validate_encryptor_ami(encryptor_ami_id) if error_msg: raise ValidationError(error_msg) else: log.debug('Skipping validation') if values.encrypted_ami_name: filters = {'name': values.encrypted_ami_name} if aws_svc.get_images(filters=filters): raise ValidationError( 'There is already an image named %s' % values.encrypted_ami_name ) except EC2ResponseError as e: raise ValidationError(e.message)
def main(): parser = argparse.ArgumentParser() parser.add_argument( '-v', '--verbose', dest='verbose', action='store_true', help='Print status information to the console' ) parser.add_argument( '--version', action='version', version='brkt-cli version %s' % VERSION ) subparsers = parser.add_subparsers() encrypt_ami_parser = subparsers.add_parser('encrypt-ami') encrypt_ami_args.setup_encrypt_ami_args(encrypt_ami_parser) argv = sys.argv[1:] values = parser.parse_args(argv) region = values.region # Initialize logging. Log messages are written to stderr and are # prefixed with a compact timestamp, so that the user knows how long # each operation took. if values.verbose: log_level = logging.DEBUG else: # Boto logs auth errors and 401s at ERROR level by default. boto.log.setLevel(logging.FATAL) log_level = logging.INFO # Set the log level of our modules explicitly. We can't set the # default log level to INFO because we would see INFO messages from # boto and other 3rd party libraries in the command output. logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%H:%M:%S') global log log = logging.getLogger(__name__) log.setLevel(log_level) aws_service.log.setLevel(log_level) encryptor_service.log.setLevel(log_level) if values.encrypted_ami_name: try: aws_service.validate_image_name(values.encrypted_ami_name) except aws_service.ImageNameError as e: print(e.message, file=sys.stderr) return 1 # Validate the region. regions = [str(r.name) for r in boto.vpc.regions()] if region not in regions: print( 'Invalid region %s. Must be one of %s.' % (region, str(regions)), file=sys.stderr ) return 1 encryptor_ami = values.encryptor_ami if not encryptor_ami: try: encryptor_ami = encrypt_ami.get_encryptor_ami(region) except: log.exception('Failed to get encryptor AMI.') return 1 session_id = util.make_nonce() default_tags = encrypt_ami.get_default_tags(session_id, encryptor_ami) try: # Connect to AWS. aws_svc = aws_service.AWSService( session_id, encryptor_ami, default_tags=default_tags) aws_svc.connect(region, key_name=values.key_name) except NoAuthHandlerFound: msg = ( 'Unable to connect to AWS. Are your AWS_ACCESS_KEY_ID and ' 'AWS_SECRET_ACCESS_KEY environment variables set?' ) if values.verbose: log.exception(msg) else: log.error(msg) return 1 try: if values.key_name: # Validate the key pair name. aws_svc.get_key_pair(values.key_name) if not values.no_validate_ami: error = aws_svc.validate_guest_ami(values.ami) if error: print(error, file=sys.stderr) return 1 error = aws_svc.validate_encryptor_ami(encryptor_ami) if error: print(error, file=sys.stderr) return 1 log.info('Starting encryptor session %s', aws_svc.session_id) encrypted_image_id = encrypt_ami.encrypt( aws_svc=aws_svc, enc_svc_cls=encryptor_service.EncryptorService, image_id=values.ami, encryptor_ami=encryptor_ami, encrypted_ami_name=values.encrypted_ami_name ) # Print the AMI ID to stdout, in case the caller wants to process # the output. Log messages go to stderr. print(encrypted_image_id) return 0 except EC2ResponseError as e: if e.error_code == 'AuthFailure': msg = 'Check your AWS login credentials and permissions' if values.verbose: log.exception(msg) else: log.error(msg + ': ' + e.error_message) elif e.error_code == 'InvalidKeyPair.NotFound': if values.verbose: log.exception(e.error_message) else: log.error(e.error_message) elif e.error_code == 'UnauthorizedOperation': if values.verbose: log.exception(e.error_message) else: log.error(e.error_message) log.error( 'Unauthorized operation. Check the IAM policy for your ' 'AWS account.' ) else: raise except util.BracketError as e: if values.verbose: log.exception(e.message) else: log.error(e.message) except KeyboardInterrupt: if values.verbose: log.exception('Interrupted by user') else: log.error('Interrupted by user') return 1
def command_encrypt_ami(values, log): region = values.region # Initialize logging. Log messages are written to stderr and are # prefixed with a compact timestamp, so that the user knows how long # each operation took. if values.verbose: log_level = logging.DEBUG else: # Boto logs auth errors and 401s at ERROR level by default. boto.log.setLevel(logging.FATAL) log_level = logging.INFO if values.encrypted_ami_name: try: aws_service.validate_image_name(values.encrypted_ami_name) except aws_service.ImageNameError as e: print(e.message, file=sys.stderr) return 1 # Validate the region. regions = [str(r.name) for r in boto.vpc.regions()] if region not in regions: print( 'Invalid region %s. Must be one of %s.' % (region, str(regions)), file=sys.stderr ) return 1 encryptor_ami = values.encryptor_ami if not encryptor_ami: try: encryptor_ami = encrypt_ami.get_encryptor_ami(region) except: log.exception('Failed to get encryptor AMI.') return 1 session_id = util.make_nonce() default_tags = encrypt_ami.get_default_tags(session_id, encryptor_ami) try: # Connect to AWS. aws_svc = aws_service.AWSService( session_id, default_tags=default_tags) aws_svc.connect(region, key_name=values.key_name) except NoAuthHandlerFound: msg = ( 'Unable to connect to AWS. Are your AWS_ACCESS_KEY_ID and ' 'AWS_SECRET_ACCESS_KEY environment variables set?' ) if values.verbose: log.exception(msg) else: log.error(msg) return 1 try: if values.key_name: # Validate the key pair name. aws_svc.get_key_pair(values.key_name) if not values.no_validate_ami: error = aws_svc.validate_guest_ami(values.ami) if error: print(error, file=sys.stderr) return 1 error = aws_svc.validate_encryptor_ami(encryptor_ami) if error: print(error, file=sys.stderr) return 1 log.info('Starting encryptor session %s', aws_svc.session_id) encrypted_image_id = encrypt_ami.encrypt( aws_svc=aws_svc, enc_svc_cls=encryptor_service.EncryptorService, image_id=values.ami, encryptor_ami=encryptor_ami, encrypted_ami_name=values.encrypted_ami_name ) # Print the AMI ID to stdout, in case the caller wants to process # the output. Log messages go to stderr. print(encrypted_image_id) return 0 except EC2ResponseError as e: if e.error_code == 'AuthFailure': msg = 'Check your AWS login credentials and permissions' if values.verbose: log.exception(msg) else: log.error(msg + ': ' + e.error_message) elif e.error_code == 'InvalidKeyPair.NotFound': if values.verbose: log.exception(e.error_message) else: log.error(e.error_message) elif e.error_code == 'UnauthorizedOperation': if values.verbose: log.exception(e.error_message) else: log.error(e.error_message) log.error( 'Unauthorized operation. Check the IAM policy for your ' 'AWS account.' ) else: raise except util.BracketError as e: if values.verbose: log.exception(e.message) else: log.error(e.message) except KeyboardInterrupt: if values.verbose: log.exception('Interrupted by user') else: log.error('Interrupted by user') return 1
def command_update_encrypted_ami(values, log): encrypted_ami_name = None if values.encrypted_ami_name: try: aws_service.validate_image_name(values.encrypted_ami_name) encrypted_ami_name = values.encrypted_ami_name except aws_service.ImageNameError as e: print(e.message, file=sys.stderr) return 1 region = values.region nonce = util.make_nonce() default_tags = encrypt_ami.get_default_tags(nonce, '') aws_svc = aws_service.AWSService( nonce, default_tags=default_tags) if not aws_svc.validate_region(region): print ('Invalid region %s' % region, file=sys.stderr) return 1 aws_svc.connect(region) encrypted_ami = values.ami if not values.no_validate_ami: guest_ami_error = aws_svc.validate_guest_encrypted_ami(encrypted_ami) if guest_ami_error: print ('Encrypted AMI verification failed: %s' % guest_ami_error, file=sys.stderr) return 1 else: log.info('skipping AMI verification') updater_ami = values.updater_ami updater_ami_error = aws_svc.validate_encryptor_ami(values.updater_ami) if updater_ami_error: log.error('Update failed: %s', updater_ami_error) return 1 # Initial validation done log.info('Updating %s', encrypted_ami) # snapshot the guest's volume guest_snapshot, volume_info, error = \ update_encrypted_ami.retrieve_guest_volume_snapshot( aws_svc, encrypted_ami) if not guest_snapshot: log.error('failed to launch instance %s: %s' % (encrypted_ami, error)) return 1 log.info('Launching metavisor update encryptor instance') updater_ami_block_devices = \ update_encrypted_ami.snapshot_updater_ami_block_devices( aws_svc, encrypted_ami, updater_ami, guest_snapshot.id, volume_info['size']) ami = encrypt_ami.register_new_ami( aws_svc, updater_ami_block_devices[encrypt_ami.NAME_METAVISOR_GRUB_SNAPSHOT], updater_ami_block_devices[encrypt_ami.NAME_METAVISOR_ROOT_SNAPSHOT], updater_ami_block_devices[encrypt_ami.NAME_METAVISOR_LOG_SNAPSHOT], guest_snapshot, volume_info['type'], volume_info['iops'], encrypted_ami, encrypted_ami_name=encrypted_ami_name) log.info('Done.') print(ami) return 0