ruby-amt 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. data/AUTHORS +1 -0
  2. data/COPYING +15 -0
  3. data/ChangeLog +392 -0
  4. data/GPL +674 -0
  5. data/Rakefile +292 -0
  6. data/VERSION +1 -0
  7. data/doc/default.css +211 -0
  8. data/doc/default.template +78 -0
  9. data/doc/documentation.page +40 -0
  10. data/doc/img/bg.jpg +0 -0
  11. data/doc/img/image.jpg +0 -0
  12. data/doc/img/line.jpg +0 -0
  13. data/doc/img/shadow.jpg +0 -0
  14. data/doc/index.page +61 -0
  15. data/doc/installation.page +115 -0
  16. data/doc/news.page +25 -0
  17. data/doc/news/release_0_1_0.page +16 -0
  18. data/doc/virtual +2 -0
  19. data/lib/amt/pt_status.rb +59 -0
  20. data/lib/amt/service.rb +16 -0
  21. data/lib/amt/service/basic.rb +159 -0
  22. data/lib/amt/service/hardware_asset.rb +83 -0
  23. data/lib/amt/service/hardware_asset/amt_information_table.rb +49 -0
  24. data/lib/amt/service/hardware_asset/asset.rb +118 -0
  25. data/lib/amt/service/hardware_asset/baseboard.rb +31 -0
  26. data/lib/amt/service/hardware_asset/bios.rb +65 -0
  27. data/lib/amt/service/hardware_asset/computer_system.rb +30 -0
  28. data/lib/amt/service/hardware_asset/fru.rb +37 -0
  29. data/lib/amt/service/hardware_asset/media_device.rb +63 -0
  30. data/lib/amt/service/hardware_asset/memory_module.rb +91 -0
  31. data/lib/amt/service/hardware_asset/portable_battery.rb +80 -0
  32. data/lib/amt/service/hardware_asset/processor.rb +123 -0
  33. data/lib/amt/service/hardware_asset/vpro_verification_table.rb +120 -0
  34. data/lib/amt/service/network_administration.rb +181 -0
  35. data/lib/amt/service/network_administration/structures.rb +29 -0
  36. data/lib/amt/service/remote_control.rb +73 -0
  37. data/lib/amt/service/remote_control/structures.rb +120 -0
  38. data/lib/amt/service/security_administration.rb +430 -0
  39. data/lib/amt/service/security_administration/structures.rb +117 -0
  40. data/lib/amt/system.rb +134 -0
  41. data/lib/amt/utility.rb +33 -0
  42. data/lib/amt/utility/bit_struct.rb +164 -0
  43. data/lib/amt/utility/enum.rb +119 -0
  44. data/lib/amt/version.rb +8 -0
  45. data/setup.rb +1585 -0
  46. metadata +125 -0
@@ -0,0 +1,117 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'amt/service/security_administration'
4
+ require 'amt/utility'
5
+
6
+ module AMT
7
+ module Service
8
+ class SecurityAdministration
9
+
10
+ # Enumeration containing names of AMT interfaces that can be enabled/disabled. Used for
11
+ # SecurityAdministration#set_enabled_interfaces and
12
+ # SecurityAdministration#get_enabled_interfaces.
13
+ class EnabledInterface < AMT::Utility::Enum
14
+ multi_add %w[WebUI SerialOverLAN IdeRedirection]
15
+ end
16
+
17
+ # The AMT SOAP interface enumeration. Used for SecurityAdministration#set_tls_options
18
+ # and SecurityAdministration#get_tls_options.
19
+ class Interface < AMT::Utility::Enum
20
+ multi_add %w[NetworkInterface LocalHostInterface]
21
+ end
22
+
23
+ # The TLS Authentication method enumeration. Used for SecurityAdministration#set_tls_options
24
+ # and SecurityAdministration#get_tls_options.
25
+ class TlsAuthentication < AMT::Utility::Enum
26
+ multi_add %w[NoAuth ServerAuth MutualAuth]
27
+ end
28
+
29
+ # Struct class containing version information as returned by
30
+ # SecurityAdministration#get_core_version.
31
+ CoreVersion = Struct.new(:major, :minor, :micro)
32
+
33
+ # Mapping of provisioning mode name to value. Used for SecurityAdministration#unprovision and
34
+ # SecurityAdministration#get_provisioning_mode.
35
+ class ProvisioningMode < AMT::Utility::Enum
36
+ multi_add(0 => :current, 1 => :enterprise, 2 => :small_business, 3 => :remote_connectivity)
37
+ end
38
+
39
+ # Struct class containing information about an user ACL. The +user+ field may either contain a
40
+ # binary String identifying a Kerberos SID or a User class instance, the +access_permission+
41
+ # field contains an instance of AccessPermission and +realms+ contains a list of UserAclRealm
42
+ # instances. Used for SecurityAdministration#add_user_acl_entry_ex and
43
+ # SecurityAdministration#update_user_acl_entry_ex.
44
+ UserAclEntryEx = Struct.new(:user, :access_permission, :realms)
45
+
46
+ # Class containing information about a user. Either a plain text password or an already hashed
47
+ # password must be provided. If a plain text password is provided, the hashed password is
48
+ # automatically calculated.
49
+ class User
50
+
51
+ # The username to be used. May only contain 7-bit ASCII characters, in the range of 33- 126,
52
+ # excluding ‘:’, ‘,’, ‘<’, ‘>’, ‘&’, and ‘”’ characters. Length is limited to 16 characters.
53
+ attr_reader :username
54
+
55
+ # The password for the user. This or #hashed_password must be set.
56
+ attr_reader :password
57
+
58
+ # The hashed password for the user. This or #password must be set.
59
+ attr_reader :hashed_password
60
+
61
+
62
+ # Create a new User object with the given +username+ and, optionally, +password+.
63
+ def initialize(username, password = nil)
64
+ self.username = username
65
+ self.password = password
66
+ end
67
+
68
+ # Contains the characters that are allowed in the username.
69
+ ALLOWED_USERNAME_CHARS = (33..126).to_a - ":,<>&\"".unpack('c*')
70
+
71
+ # Set the username to +value+. If the username is not valid, an ArgumentError is raised.
72
+ def username=(value)
73
+ value.each_byte do |b|
74
+ ALLOWED_USERNAME_CHARS.include?(b) || raise(ArgumentError, "invalid character in username")
75
+ end
76
+ raise(ArgumentError, 'username length is limited to 16 characters') if value.length > 16
77
+ raise(ArgumentError, 'username must not be empty') if value.length == 0
78
+ @username = value
79
+ end
80
+
81
+ # Set the #password to +value+ and clear the #hashed_password.
82
+ def password=(value)
83
+ @hashed_password, @password = nil, value
84
+ end
85
+
86
+ # Set the #hashed_password to +value+ and clear the #password.
87
+ def hashed_password=(value)
88
+ @password, @hashed_password = nil, value
89
+ end
90
+
91
+ end
92
+
93
+ # Access permissions enumeration. Used in the UserAclEntryEx structure.
94
+ class AccessPermission < AMT::Utility::Enum
95
+ multi_add %w[LocalAccessPermission NetworkAccessPermission AnyAccessPermission]
96
+ end
97
+
98
+ # The user ACL realms enumeration. Used in the UserAclEntryEx structure.
99
+ class UserAclRealm < AMT::Utility::Enum
100
+ multi_add(0 => :invalid, 1 => :rcs, 2 => :redirection, 3 => :pt_administration,
101
+ 4 => :hardware_asset, 5 => :remote_control, 6 => :storage,
102
+ 7 => :event_manager, 8 => :storage_admin, 9 => :agent_presence_local,
103
+ 10 => :agent_presence_remote, 11 => :circuit_breaker, 12 => :network_time,
104
+ 13 => :general_info, 14 => :firmware_update, 15 => :eit, 16 => :local_un,
105
+ 17 => :endpoint_access_control, 18 => :endpoint_access_control_admin,
106
+ 19 => :event_log_reader, 20 => :security_audit_log, 21 => :user_access_control,
107
+ 22 => :reserved, 23 => :anti_theft)
108
+ end
109
+
110
+ # Struct class containing the fields for a global power policy (used by
111
+ # SecurityAdministration#set_global_power_policy and
112
+ # SecurityAdministration#get_global_power_policy).
113
+ GlobalPowerPolicy = Struct.new(:idle_wake_timeout)
114
+
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,134 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ ##
4
+ # This is the API documentation for ruby-amt!
5
+ #
6
+ # Have a look at the \AMT module which provides a good starting point!
7
+
8
+
9
+ #
10
+ # The ruby-amt library provides access to the SOAP services provided by Intel AMT devices. Before
11
+ # you decide whether to use the library or not, you should know the following:
12
+ #
13
+ # * The library has been designed to be used with Intel AMT 5.0 devices. This is the reason why no
14
+ # deprecated methods have been implemented.
15
+ #
16
+ # * Furthermore, the library has been designed to be used with Intel AMT devices in SMB mode. So
17
+ # SOAP methods which are only useful for devices in Enterprise Mode have not been implemented. One
18
+ # reason is that I don't have access to devices in Enterprise Mode and therefore cannot test these
19
+ # methods.
20
+ #
21
+ # = Short Overview
22
+ #
23
+ # The library provides a "low-level" implementation of the client side of the SOAP services (as
24
+ # classes in AMT::Service) as well as a class (AMT::System) for high-level access. The adjective
25
+ # "low-level" is not really correct since the implementation of the client side of the SOAP services
26
+ # is not done by generating code from WSDL files (which normally results in a direct mapping of the
27
+ # SOAP methods and data structures) but by hand-crafting the code and providing simple but adequate
28
+ # data structures.
29
+ #
30
+ # So, although the SOAP service classes directly represent SOAP services and their methods, their
31
+ # usage in an application is actually quite simple. However, there are some AMT work flows which
32
+ # require calling more than one method or getting available states before actually setting
33
+ # something. This can easily be overlooked by people not acquainted with Intel AMT. Therefore there
34
+ # exists a class for high-level access to the AMT functionality of a system which takes this burden
35
+ # of you.
36
+ #
37
+ # = Library Organization
38
+ #
39
+ # This module houses all modules/classes that are in the ruby-amt library. There are three main
40
+ # modules/classes:
41
+ #
42
+ # [AMT::Service]
43
+ # This module contains all SOAP service classes. There is a one-to-one mapping from
44
+ # the Intel AMT SOAP services to classes in this module. Note that not all SOAP services are
45
+ # implemented because some are not really useful for a management application.
46
+ #
47
+ # [AMT::Utility]
48
+ # This module houses utility classes that are used by other classes (mostly the service classes).
49
+ #
50
+ # [AMT::System]
51
+ # This is the class that can be used for high-level access to the functionality of an AMT system.
52
+ #
53
+ # = Library Usage
54
+ #
55
+ # == Direct use of SOAP Service Classes
56
+ #
57
+ # All service classes are derived from AMT::Service::Basic and have the same initialization
58
+ # parameters. You need to provide at least the hostname of the AMT device, a username and a
59
+ # password.
60
+ #
61
+ # You don't need to load an individual service class, just use
62
+ #
63
+ # require 'amt/service'
64
+ #
65
+ # since this will automatically load any service class and any data structures that are needed on
66
+ # demand.
67
+ #
68
+ # For example, the AMT::Service::RemoteControl service can be created like this:
69
+ #
70
+ # rcs = AMT::Service::RemoteControl.new('amt.example.com', 'admin', 'P@ssw0rD')
71
+ #
72
+ # After that you can just call the method you would like to invoke on the AMT system. But before
73
+ # that you should read the method description sothat you know what parameters to pass. Since the
74
+ # SOAP service classes are not created from WSDL files, they provide a nicer, more Ruby like
75
+ # interface to the SOAP methods. However, this also means that the method signature sometimes
76
+ # differs a little bit from the method signature as defined in the "Network Interface Guide" (which
77
+ # can be found in the Intel AMT SDK).
78
+ #
79
+ # Take the AMT::Service::RemoteControl#get_system_power_state as example:
80
+ #
81
+ # sps = rcs.get_system_power_state
82
+ #
83
+ # Since this method takes no parameters, there is no difference in this respect. The method would
84
+ # nominally return a bit structure as an unsigned 32 bit integer. However, this has been changed
85
+ # sothat it returns an instance of AMT::Service::RemoteControl::SystemPowerState which provides easy
86
+ # access to the fields of the bit structure. For example:
87
+ #
88
+ # sps.power_state # => :s0
89
+ # sps.watchdog_expired? # => false
90
+ # sps.power_source # => :ac
91
+ #
92
+ # Such a conversion of input or output arguments is true for all implemented methods. The special
93
+ # data structures needed by a service are defined in the namespace of the service. For example, all
94
+ # data structures needed as input or returned as output for the RemoteControl service are defined
95
+ # unter AMT::Service::RemoteControl.
96
+ #
97
+ # So how does one provide input parameters? We take the AMT::Service::RemoteControl#remote_control
98
+ # method as example. You can learn from the method description that it has one mandatory and several
99
+ # optional arguments. Additionally, it is stated which type the arguments have. In its simplest
100
+ # form, one needs to provide just a value for the +command+ parameter which should be an instance of
101
+ # AMT::Service::RemoteControl::RemoteControlCommand. Checking out the class we see that it is a
102
+ # subclass of AMT::Utility::Enum. This allows us to use any of the following ways to power up an AMT
103
+ # system which is currently powered down:
104
+ #
105
+ # rcs.remote_control(AMT::Service::RemoteControl::RemoteControlCommand.for(:0x11))
106
+ # rcs.remote_control(AMT::Service::RemoteControl::RemoteControlCommand.for(:power_up))
107
+ # rcs.remote_control(0x11)
108
+ # rcs.remote_control(:power_up)
109
+ #
110
+ # As you can see, one doesn't actually need to create an instance of the RemoteControlCommand class,
111
+ # one just needs to provide either a valid enumeration value or enumeration name! <b>This is true
112
+ # everywhere a subclass of AMT::Utility::Enum is expected.</b>
113
+ #
114
+ # A simliar short-cut is available when an instance of a subclass of AMT::Utility::BitStruct is
115
+ # expected - see AMT::Utility::BitStruct.new !
116
+ #
117
+ # Here is a final example with some optional parameters:
118
+ #
119
+ # rcs.remote_control(:power_up, 343, :boot_options => [:lock_keyboard], :special_command => :pxe_boot)
120
+ #
121
+ #
122
+ # == High-level Interface
123
+ #
124
+ # The high-level interface is not implemented currently.
125
+ #
126
+ module AMT
127
+
128
+ # High-level access to AMT functionality.
129
+ #
130
+ # NOT IMPLEMENTED
131
+ class System
132
+ end
133
+
134
+ end
@@ -0,0 +1,33 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module AMT
4
+
5
+ # This module houses utility classes that are used by the other AMT classes.
6
+ module Utility
7
+
8
+ autoload :BitStruct, 'amt/utility/bit_struct'
9
+ autoload :Enum, 'amt/utility/enum'
10
+
11
+
12
+ # Create a UUID string from binary data which can either have a length of 16 characters (then it
13
+ # is considered to be a binary UUID) or a length of 32 characters (an already unpacked binary
14
+ # UUID).
15
+ def self.binary_to_uuid(data)
16
+ data = data.unpack('H32').first if data.length == 16
17
+ a = data.scan(/../)
18
+ a[0,4].reverse.join('') + "-" + a[4,2].reverse.join('') + "-" + a[6,2].reverse.join('') +
19
+ "-" + a[8,2].join('') + "-" + a[10,6].join('')
20
+ end
21
+
22
+ # Convert a UUID string to binary data.
23
+ def self.uuid_to_binary(uuid)
24
+ [uuid[0,8].scan(/../).reverse.join('') +
25
+ uuid[9,4].scan(/../).reverse.join('') +
26
+ uuid[14,4].scan(/../).reverse.join('') +
27
+ uuid[19,4].scan(/../).join('') +
28
+ uuid[24,12].scan(/../).join('')].pack('H32')
29
+ end
30
+
31
+ end
32
+
33
+ end
@@ -0,0 +1,164 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module AMT
4
+
5
+ module Utility
6
+
7
+ # A very simple base class which can be used to extract information from a number based on its
8
+ # bits, or to set it.
9
+ #
10
+ # It isn't useful to create objects directly from this class but one should create a subclass
11
+ # and use the provided class methods to define how to interpret the bits of a number.
12
+ class BitStruct
13
+
14
+ # Interpret the bit with the +index+ (starting from zero) as boolean flag named +name+ (should
15
+ # be a Symbol). If the bit at the index is +1+, the flag is interpreted as +true+. The
16
+ # optional parameter +desc+ can be used to provide a textual representation of the +true+
17
+ # state.
18
+ #
19
+ # This method also adds accessor methods for the property. For example, if the property is
20
+ # called +amt_enabled+, the created getter method is called <tt>#amt_enabled?</tt> and the
21
+ # setter method is called <tt>#amt_enabled!</tt>. Note the trailing question/exclamation
22
+ # marks.
23
+ #
24
+ # Example usage:
25
+ #
26
+ # boolean 5, :amt_enabled, 'AMT is enabled'
27
+ def self.boolean(index, name, desc = name.to_s)
28
+ index = (0x1 << index)
29
+ (@boolean ||= []) << [name, desc]
30
+ define_method("#{name}?") do
31
+ @value & index == index
32
+ end
33
+ define_method("#{name}!") do
34
+ @value |= index
35
+ end
36
+ end
37
+
38
+
39
+ # Same as BitStruct.boolean but +mask+ defines a bit mask and the value is only +true+ if all
40
+ # bits specified by the bit mask (ie. all bits that are +1+ in the bit mask) are set.
41
+ #
42
+ # Example usage:
43
+ #
44
+ # mboolean 0b101, :amt_enabled, 'AMT is enabled'
45
+ def self.mboolean(mask, name, desc = name.to_s)
46
+ (@boolean ||= []) << [name, desc]
47
+ define_method("#{name}?") do
48
+ @value & mask == mask
49
+ end
50
+ define_method("#{name}!") do
51
+ @value |= mask
52
+ end
53
+ end
54
+
55
+
56
+ # Interpret the bits in the +bit_range+ (starting from zero) as unsigned integer named +name+
57
+ # (should be a Symbol). The optional parameter +desc+ can be used to provide a textual
58
+ # representation of the meaning of the value.
59
+ #
60
+ # This method also adds accessor methods for the property. For example, if the property is
61
+ # called +version+, the created getter method is called <tt>#version</tt> and the setter
62
+ # method is called <tt>#version=</tt>.
63
+ #
64
+ # Example usage:
65
+ #
66
+ # unsigned 2..5, :version, 'The integer version of the AMT device'
67
+ def self.unsigned(bit_range, name, desc = name.to_s)
68
+ mask = (2**(bit_range.end - bit_range.begin + 1) - 1) << bit_range.begin
69
+ (@unsigned ||= []) << [name, desc]
70
+ define_method(name) do
71
+ (@value & mask) >> bit_range.begin
72
+ end
73
+ define_method("#{name}=") do |number|
74
+ @value |= (number << bit_range.begin) & mask
75
+ end
76
+ end
77
+
78
+ # Interpret the bits in the +bit_range+ (starting from zero) as unsigned integer value of an
79
+ # enumeration called +name+ (should be a Symbol).
80
+ #
81
+ # The parameter +values+ specifies the mapping from number to meaning (normally a String). The
82
+ # optional parameter +desc+ can be used to provide a textual representation of the meaning of
83
+ # the enumeration.
84
+ #
85
+ # This method also adds accessor methods for the property. For example, if the property is
86
+ # called +version+, the created getter method is called <tt>#version</tt> and the setter
87
+ # method is called <tt>#version=</tt>.
88
+ #
89
+ # Example usage:
90
+ #
91
+ # enum 0..1, :device_type, {0 => 'Foo', 1 => 'Bar', 2 => 'Baz', 3 => Quux'}
92
+ def self.enum(bit_range, name, values, desc = name.to_s)
93
+ mask = (2**(bit_range.end - bit_range.begin + 1) - 1) << bit_range.begin
94
+ (@enum ||= []) << [name, values, desc]
95
+ define_method(name) do
96
+ values[(@value & mask) >> bit_range.begin]
97
+ end
98
+ define_method("#{name}=") do |number|
99
+ @value |= (number << bit_range.begin) & mask
100
+ end
101
+ end
102
+
103
+ # Return a hash of all defined fields for this class. The hash keys are <tt>:boolean</tt> for
104
+ # the boolean properties, <tt>:unsigned</tt> for the unsigned integer properties and
105
+ # <tt>:enum</tt> for the enumeration properties. The hash values are arrays with information
106
+ # (depending on the type of the field) about the fields.
107
+ def self.fields
108
+ {:boolean => @boolean || [], :unsigned => @unsigned || [], :enum => @enum || []}
109
+ end
110
+
111
+ # The integer value which should be interpreted bit-wise.
112
+ attr_reader :value
113
+
114
+ # Create a new object. If +value+ is an integer, it is used directly and interpreted bit-wise.
115
+ # If +value+ is an array, it is processed in the following way:
116
+ #
117
+ # * symbols are interpreted as boolean fields
118
+ # * two-item arrays where the first item is a symbol and the second an integer are interpreted
119
+ # as unsigned or enum fields (depending in which category the symbol falls).
120
+ def initialize(value = 0)
121
+ if value.kind_of?(Integer)
122
+ @value = value
123
+ elsif value.kind_of?(Array)
124
+ @value = 0
125
+ value.each do |sym, val|
126
+ if val.nil?
127
+ send("#{sym}!")
128
+ else
129
+ send("#{sym}=", val)
130
+ end
131
+ end
132
+ else
133
+ raise ArgumentError, 'invalid argument type specified'
134
+ end
135
+ end
136
+
137
+ def inspect #:nodoc:
138
+ bools = self.class.fields[:boolean].select {|n,d| send("#{n}?")}.collect {|n, d| n.to_s}
139
+ unsigns = self.class.fields[:unsigned].collect {|n, d| "#{n}=#{send(n)}"}
140
+ enum = self.class.fields[:enum].collect {|n, d| "#{n}=#{send(n)}"}
141
+ "#<#{self.class.name} #{(bools + unsigns + enum).join(', ')}>"
142
+ end
143
+
144
+ # Return an array with textual representations for output purposes of the the fields specified
145
+ # by +used_fields+.
146
+ def list(used_fields = [:boolean, :unsigned, :enum])
147
+ result = []
148
+ if used_fields.include?(:boolean)
149
+ result += self.class.fields[:boolean].select {|n,d| send("#{n}?")}.collect {|n,d| d}
150
+ end
151
+ if used_fields.include?(:unsigned)
152
+ result += self.class.fields[:unsigned].collect {|n, d| "#{d}=#{send(n)}"}
153
+ end
154
+ if used_fields.include?(:enum)
155
+ result += self.class.fields[:enum].collect {|n, d| "#{d}=#{send(n)}"}
156
+ end
157
+ result
158
+ end
159
+
160
+ end
161
+
162
+ end
163
+
164
+ end