class ManifestV20070829
Manifest Version 2007-08-29. Not backwards compatible
Manifest Version 2007-08-29. Not backwards compatible
Constants
- VERSION
- VERSION_STRING
Public Class Methods
# File lib/ec2/amitools/manifestv20070829.rb, line 39 def initialize(xml = nil) if xml == nil @doc = REXML::Document.new else # Convert to string if necessary. xml = (xml.kind_of?(IO) ? xml.read : xml) @doc = REXML::Document.new(xml) end end
Expose the version
# File lib/ec2/amitools/manifestv20070829.rb, line 24 def self.version VERSION end
# File lib/ec2/amitools/manifestv20070829.rb, line 200 def self::version20070829?(xml) doc = REXML::Document.new(xml) version = REXML::XPath.first(doc.root, 'version') return true if (version and version.text and version.text == VERSION_STRING) return (version and version.text and version.text == VERSION.to_s) end
Public Instance Methods
Retrieve a list of AMI bundle parts info. Each element is a hash with the following elements:
-
'digest'
-
'filename'
-
'index'
# File lib/ec2/amitools/manifestv20070829.rb, line 251 def ami_part_info_list parts = Array.new REXML::XPath.each(@doc.root,'image/parts/part') do |part| index = part.attribute('index').to_s.to_i filename = REXML::XPath.first(part, 'filename').text digest = REXML::XPath.first(part, 'digest').text parts << { 'digest'=>digest, 'filename'=>filename, 'index'=>index } end return parts end
Return the (optional) architecture of the AMI.
# File lib/ec2/amitools/manifestv20070829.rb, line 280 def arch() return get_element_text('machine_configuration/architecture') end
Verify the signature
# File lib/ec2/amitools/manifestv20070829.rb, line 329 def authenticate(cert) machine_configuration_xml = XMLUtil.get_xml(@doc.to_s, 'machine_configuration') || "" image_xml = XMLUtil.get_xml(@doc.to_s, 'image') pubkey = Crypto::cert2pubkey(cert) Crypto::authenticate(machine_configuration_xml + image_xml, Format::hex2bin(signature), pubkey) end
Return the bundled size of the AMI.
# File lib/ec2/amitools/manifestv20070829.rb, line 285 def bundled_size() return get_element_text('image/bundled_size').to_i end
Return the bundler name.
# File lib/ec2/amitools/manifestv20070829.rb, line 290 def bundler_name() return get_element_text('bundler/name') end
Return the bundler release.
# File lib/ec2/amitools/manifestv20070829.rb, line 300 def bundler_release() return get_element_text('bundler/release') end
Return the bundler version.
# File lib/ec2/amitools/manifestv20070829.rb, line 295 def bundler_version() return get_element_text('bundler/version') end
Get cipher algorithm used.
# File lib/ec2/amitools/manifestv20070829.rb, line 242 def cipher_algorithm() return REXML::XPath.first(@doc.root, 'image/ec2_encrypted_key/@algorithm').to_s end
Return the AMI's digest hex encoded.
# File lib/ec2/amitools/manifestv20070829.rb, line 208 def digest() return get_element_text('image/digest') end
Get digest algorithm used.
# File lib/ec2/amitools/manifestv20070829.rb, line 237 def digest_algorithm() return REXML::XPath.first(@doc.root, 'image/digest/@algorithm').to_s end
for debugging only
# File lib/ec2/amitools/manifestv20070829.rb, line 50 def doc @doc end
The ec2 encrypted initialization vector hex encoded.
# File lib/ec2/amitools/manifestv20070829.rb, line 227 def ec2_encrypted_iv() return get_element_text('image/ec2_encrypted_iv') end
The ec2 encrypted key hex encoded.
# File lib/ec2/amitools/manifestv20070829.rb, line 217 def ec2_encrypted_key() return get_element_text('image/ec2_encrypted_key') end
Initialize the manifest with AMI information. Return true
if the initialization was succesful. Raise an exception on error.
# File lib/ec2/amitools/manifestv20070829.rb, line 57 def init( name, user, # The user's account number. arch, # Target architecture for AMI. reserved, # Reserved for future use; pass nil. parts, # A list of parts filenames and digest pairs. size, # The size of the AMI in bytes. bundled_size, # The size of the bunled AMI in bytes. user_encrypted_key, # Hex encoded. ec2_encrypted_key, # Hex encoded. cipher_algorithm, # The cipher algorithm used to encrypted the AMI. user_encrypted_iv, # Hex encoded. ec2_encrypted_iv, # Hex encoded. digest, # Hex encoded. digest_algorithm, # The digest algorithm. privkey_filename, # The user's private key filename. bundler_name = nil, bundler_version = nil, bundler_release = nil) # Check reserved parameters are nil raise ArgumentError.new("reserved parameters not nil") unless reserved.nil? # Check non-String parameter types. raise ArgumentError.new("parts parameter type invalid") unless parts.is_a? Array # XML document. @doc = REXML::Document.new @doc << REXML::XMLDecl.new # manifest - the root element. manifest = REXML::Element.new('manifest') @doc.add_element(manifest) # version - indicate the manifest version. version = REXML::Element.new('version') version.text = VERSION manifest.add_element(version) # bundler information if bundler_name or bundler_version or bundler_release bundler_element = REXML::Element.new('bundler') manifest.add_element(bundler_element) [['name', bundler_name ], ['version', bundler_version ], ['release', bundler_release ]].each do |element_name, text| if element_name element = REXML::Element.new(element_name) element.text = text bundler_element.add_element(element) end end end # machine_configuration - the target hardware description of the AMI. machine_configuration = REXML::Element.new('machine_configuration') manifest.add_element(machine_configuration) # image - the image element. image = REXML::Element.new('image') name_element = REXML::Element.new('name') name_element.text = name image.add_element(name_element) manifest.add_element(image) # user - the user's AWS access key ID. user_element = REXML::Element.new('user') user_element.text = user image.add_element(user_element) # m_c arch - the target hardware architecture if arch arch_element = REXML::Element.new('architecture') arch_element.text = arch machine_configuration.add_element(arch_element) end # digest - the digest of the AMI. digest_element = REXML::Element.new('digest') digest_element.add_attribute('algorithm', digest_algorithm) digest_element.add_text(digest) image.add_element(digest_element) # size - the size of the uncompressed AMI. size_element = REXML::Element.new('size') size_element.text = size.to_s image.add_element(size_element) # bundled size - the size of the bundled AMI. bundled_size_element = REXML::Element.new('bundled_size') bundled_size_element.text = bundled_size.to_s image.add_element(bundled_size_element) # ec2 encrypted key element. ec2_encrypted_key_element = REXML::Element.new('ec2_encrypted_key') ec2_encrypted_key_element.add_attribute('algorithm', cipher_algorithm) ec2_encrypted_key_element.add_text(ec2_encrypted_key) image.add_element(ec2_encrypted_key_element) # user encrypted key element. user_encrypted_key_element = REXML::Element.new('user_encrypted_key') user_encrypted_key_element.add_attribute('algorithm', cipher_algorithm) user_encrypted_key_element.add_text(user_encrypted_key) image.add_element(user_encrypted_key_element) # ec2 encrypted iv element. ec2_encrypted_iv_element = REXML::Element.new('ec2_encrypted_iv') ec2_encrypted_iv_element.add_text(ec2_encrypted_iv) image.add_element(ec2_encrypted_iv_element) # user encrypted iv element. user_encrypted_iv_element = REXML::Element.new('user_encrypted_iv') user_encrypted_iv_element.add_text(user_encrypted_iv) image.add_element(user_encrypted_iv_element) # parts - list of the image parts. parts_element = REXML::Element.new('parts') parts_element.add_attributes({'count' => parts.size.to_s}) index=0 parts.each do |part| # Add image part element for each image part. part_element = REXML::Element.new('part') part_element.add_attribute('index', index.to_s) filename = REXML::Element.new('filename') filename.add_text(part[0]) part_element.add_element(filename) digest = REXML::Element.new('digest') digest.add_attribute('algorithm', digest_algorithm) digest.add_text(Format::bin2hex(part[1])) part_element.add_element(digest) parts_element.add_element(part_element) index+=1 end image.add_element(parts_element) # Sign the manifest. sign(privkey_filename) return true end
# File lib/ec2/amitools/manifestv20070829.rb, line 212 def name() return get_element_text('image/name') end
A list of PartInformation
instances representing the AMI parts.
# File lib/ec2/amitools/manifestv20070829.rb, line 263 def parts() parts = [] REXML::XPath.each(@doc.root,'image/parts/part') do |part| index = part.attribute('index').to_s.to_i filename = REXML::XPath.first(part, 'filename').text digest = Format::hex2bin(REXML::XPath.first(part, 'digest').text) parts[index] = PartInformation.new(filename, digest) end return parts end
Sign the manifest. If it is already signed, the signature and certificate will be replaced
# File lib/ec2/amitools/manifestv20070829.rb, line 306 def sign(privkey_filename) unless privkey_filename.kind_of? String and File::exist?(privkey_filename) raise ArgumentError.new("privkey_filename parameter invalid") end # Get the XML for <machine_configuration> and <image> elements and sign them. machine_configuration_xml = XMLUtil.get_xml(@doc.to_s, 'machine_configuration') || "" image_xml = XMLUtil.get_xml(@doc.to_s, 'image') sig = Crypto::sign(machine_configuration_xml + image_xml, privkey_filename) # Create the signature and certificate elements. signature = REXML::Element.new('signature') signature.add_text(Format::bin2hex(sig)) @doc.root.delete_element('signature') @doc.root.add_element(signature) end
Return the signature
# File lib/ec2/amitools/manifestv20070829.rb, line 324 def signature get_element_text('signature') end
Return the size of the AMI.
# File lib/ec2/amitools/manifestv20070829.rb, line 275 def size() return get_element_text('image/size').to_i() end
Return the manifest as an XML string.
# File lib/ec2/amitools/manifestv20070829.rb, line 337 def to_s() return @doc.to_s end
# File lib/ec2/amitools/manifestv20070829.rb, line 341 def user() return get_element_text('image/user') end
The user encrypted initialization vector hex encoded.
# File lib/ec2/amitools/manifestv20070829.rb, line 232 def user_encrypted_iv() return get_element_text('image/user_encrypted_iv') end
The user encrypted key hex encoded.
# File lib/ec2/amitools/manifestv20070829.rb, line 222 def user_encrypted_key() return get_element_text('image/user_encrypted_key') end
# File lib/ec2/amitools/manifestv20070829.rb, line 345 def version() return get_element_text('version').to_i end
Private Instance Methods
# File lib/ec2/amitools/manifestv20070829.rb, line 351 def get_element_text(xpath) element = REXML::XPath.first(@doc.root, xpath) unless element raise "invalid AMI manifest, #{xpath} element not present" end unless element.text raise "invalid AMI manifest, #{xpath} element empty" end return element.text end