class ManifestV3
Manifest Version 3. Not backwards compatible
Manifest Version 3. Not backwards compatible
Constants
- VERSION
- VERSION_STRING
Public Class Methods
# File lib/ec2/amitools/manifestv3.rb, line 34 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
# File lib/ec2/amitools/manifestv3.rb, line 178 def ManifestV3::version3?( xml ) doc = REXML::Document.new( xml ) version = REXML::XPath.first( doc.root, 'version' ) return (version and version.text and version.text.to_i == VERSION) 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/manifestv3.rb, line 228 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
Verify the signature
# File lib/ec2/amitools/manifestv3.rb, line 300 def authenticate(cert) image_xml = XMLUtil.get_xml( @doc.to_s, 'image' ) pubkey = Crypto::cert2pubkey(cert) Crypto::authenticate(image_xml, Format::hex2bin(signature), pubkey) end
Return the bundled size of the AMI.
# File lib/ec2/amitools/manifestv3.rb, line 257 def bundled_size() return get_element_text( 'image/bundled_size' ).to_i end
Return the bundler name.
# File lib/ec2/amitools/manifestv3.rb, line 262 def bundler_name() return get_element_text('bundler/name') end
Return the bundler release.
# File lib/ec2/amitools/manifestv3.rb, line 272 def bundler_release() return get_element_text('bundler/release') end
Return the bundler version.
# File lib/ec2/amitools/manifestv3.rb, line 267 def bundler_version() return get_element_text('bundler/version') end
Get cipher algorithm used.
# File lib/ec2/amitools/manifestv3.rb, line 219 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/manifestv3.rb, line 185 def digest() return get_element_text( 'image/digest' ) end
Get digest algorithm used.
# File lib/ec2/amitools/manifestv3.rb, line 214 def digest_algorithm() return REXML::XPath.first(@doc.root, 'image/digest/@algorithm').to_s end
for debugging only
# File lib/ec2/amitools/manifestv3.rb, line 45 def doc @doc end
The ec2 encrypted initialization vector hex encoded.
# File lib/ec2/amitools/manifestv3.rb, line 204 def ec2_encrypted_iv() return get_element_text( 'image/ec2_encrypted_iv' ) end
The ec2 encrypted key hex encoded.
# File lib/ec2/amitools/manifestv3.rb, line 194 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/manifestv3.rb, line 52 def init( name, user, # The user's account number. 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 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_STRING 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 # 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 ) # 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 ) # size - the size of the uncompressed 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/manifestv3.rb, line 189 def name() return get_element_text( 'image/name' ) end
A list of PartInformation
instances representing the AMI parts.
# File lib/ec2/amitools/manifestv3.rb, line 240 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/manifestv3.rb, line 278 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 image element and sign it. image_xml = XMLUtil.get_xml( @doc.to_s, 'image' ) sig = Crypto::sign( 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/manifestv3.rb, line 295 def signature get_element_text('signature') end
Return the size of the AMI.
# File lib/ec2/amitools/manifestv3.rb, line 252 def size() return get_element_text( 'image/size' ).to_i() end
Return the manifest as an XML string.
# File lib/ec2/amitools/manifestv3.rb, line 307 def to_s() return @doc.to_s end
# File lib/ec2/amitools/manifestv3.rb, line 311 def user() return get_element_text( 'image/user' ) end
The user encrypted initialization vector hex encoded.
# File lib/ec2/amitools/manifestv3.rb, line 209 def user_encrypted_iv() return get_element_text( 'image/user_encrypted_iv' ) end
The user encrypted key hex encoded.
# File lib/ec2/amitools/manifestv3.rb, line 199 def user_encrypted_key() return get_element_text( 'image/user_encrypted_key' ) end
# File lib/ec2/amitools/manifestv3.rb, line 315 def version() return get_element_text( 'version' ).to_i end
Private Instance Methods
# File lib/ec2/amitools/manifestv3.rb, line 321 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