zaws 0.0.5 → 0.1.1

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 (282) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +2 -0
  3. data/.travis.yml +9 -18
  4. data/Gemfile +0 -0
  5. data/Gemfile.lock +26 -35
  6. data/Gemfile.lock.linux +69 -0
  7. data/Gemfile.lock.mac +81 -0
  8. data/Gemfile.lock.windows +77 -0
  9. data/LICENSE +0 -0
  10. data/README.md +11 -0
  11. data/Rakefile +1 -7
  12. data/archive/cloud_trail/cloud_trail.feature +124 -0
  13. data/bin/win_zaws.bat +2 -0
  14. data/lib/zaws.rb +54 -41
  15. data/lib/zaws/command/ai.rb +34 -0
  16. data/lib/zaws/command/bucket.rb +35 -0
  17. data/lib/zaws/command/cloud_trail.rb +43 -0
  18. data/lib/zaws/command/compute.rb +152 -87
  19. data/lib/zaws/command/config.rb +42 -0
  20. data/lib/zaws/command/elasticip.rb +19 -9
  21. data/lib/zaws/command/hosted_zone.rb +31 -18
  22. data/lib/zaws/command/iam.rb +37 -0
  23. data/lib/zaws/command/load_balancer.rb +54 -51
  24. data/lib/zaws/command/nessus.rb +41 -0
  25. data/lib/zaws/command/newrelic.rb +30 -0
  26. data/lib/zaws/command/route_table.rb +135 -122
  27. data/lib/zaws/command/security_group.rb +95 -82
  28. data/lib/zaws/command/subnet.rb +58 -46
  29. data/lib/zaws/command/sumo.rb +34 -0
  30. data/lib/zaws/command/vpc.rb +53 -0
  31. data/lib/zaws/external/awscli/awscli.rb +65 -0
  32. data/lib/zaws/external/awscli/commands.rb +10 -0
  33. data/lib/zaws/external/awscli/commands/aws.rb +40 -0
  34. data/lib/zaws/external/awscli/commands/ec2.rb +74 -0
  35. data/lib/zaws/external/awscli/commands/ec2/allocate_address.rb +42 -0
  36. data/lib/zaws/external/awscli/commands/ec2/assign_private_ip_addresses.rb +49 -0
  37. data/lib/zaws/external/awscli/commands/ec2/associate_address.rb +48 -0
  38. data/lib/zaws/external/awscli/commands/ec2/associate_route_table.rb +48 -0
  39. data/lib/zaws/external/awscli/commands/ec2/authorize_security_group_ingress.rb +70 -0
  40. data/lib/zaws/external/awscli/commands/ec2/create_route.rb +60 -0
  41. data/lib/zaws/external/awscli/commands/ec2/create_route_table.rb +40 -0
  42. data/lib/zaws/external/awscli/commands/ec2/create_security_group.rb +58 -0
  43. data/lib/zaws/external/awscli/commands/ec2/create_subnet.rb +62 -0
  44. data/lib/zaws/external/awscli/commands/ec2/create_tags.rb +53 -0
  45. data/lib/zaws/external/awscli/commands/ec2/create_vpc.rb +21 -0
  46. data/lib/zaws/external/awscli/commands/ec2/delete_route.rb +54 -0
  47. data/lib/zaws/external/awscli/commands/ec2/delete_route_table.rb +46 -0
  48. data/lib/zaws/external/awscli/commands/ec2/delete_security_group.rb +46 -0
  49. data/lib/zaws/external/awscli/commands/ec2/delete_subnet.rb +46 -0
  50. data/lib/zaws/external/awscli/commands/ec2/describe_addresses.rb +41 -0
  51. data/lib/zaws/external/awscli/commands/ec2/describe_images.rb +58 -0
  52. data/lib/zaws/external/awscli/commands/ec2/describe_instances.rb +56 -0
  53. data/lib/zaws/external/awscli/commands/ec2/describe_route_tables.rb +44 -0
  54. data/lib/zaws/external/awscli/commands/ec2/describe_security_groups.rb +50 -0
  55. data/lib/zaws/external/awscli/commands/ec2/describe_subnets.rb +48 -0
  56. data/lib/zaws/external/awscli/commands/ec2/describe_vpc_peering_connections.rb +23 -0
  57. data/lib/zaws/external/awscli/commands/ec2/describe_vpcs.rb +26 -0
  58. data/lib/zaws/external/awscli/commands/ec2/disable_vgw_route_propagation.rb +48 -0
  59. data/lib/zaws/external/awscli/commands/ec2/disassociate-address.rb +42 -0
  60. data/lib/zaws/external/awscli/commands/ec2/disassociate_route_table.rb +41 -0
  61. data/lib/zaws/external/awscli/commands/ec2/enable_vgw_route_propagation.rb +48 -0
  62. data/lib/zaws/external/awscli/commands/ec2/filter.rb +115 -0
  63. data/lib/zaws/external/awscli/commands/ec2/modify_instance_attribute.rb +62 -0
  64. data/lib/zaws/external/awscli/commands/ec2/network_interfaces.rb +63 -0
  65. data/lib/zaws/external/awscli/commands/ec2/release_address.rb +42 -0
  66. data/lib/zaws/external/awscli/commands/ec2/revoke_security_group_ingress.rb +70 -0
  67. data/lib/zaws/external/awscli/commands/ec2/run_instances.rb +21 -0
  68. data/lib/zaws/external/awscli/commands/ec2/stop_instances.rb +21 -0
  69. data/lib/zaws/external/awscli/commands/ec2/terminate_instances.rb +40 -0
  70. data/lib/zaws/external/awscli/commands/ec2/unassign_private_ip_addresses.rb +49 -0
  71. data/lib/zaws/external/awscli/commands/elb.rb +19 -0
  72. data/lib/zaws/external/awscli/commands/elb/create_load_balancer.rb +64 -0
  73. data/lib/zaws/external/awscli/commands/elb/create_load_balancer_listeners.rb +47 -0
  74. data/lib/zaws/external/awscli/commands/elb/delete_load_balancer.rb +40 -0
  75. data/lib/zaws/external/awscli/commands/elb/delete_load_balancer_listeners.rb +49 -0
  76. data/lib/zaws/external/awscli/commands/elb/deregister_instances_with_load_balancer.rb +49 -0
  77. data/lib/zaws/external/awscli/commands/elb/describe_load_balancers.rb +30 -0
  78. data/lib/zaws/external/awscli/commands/elb/register_instances_with_load_balancer.rb +49 -0
  79. data/lib/zaws/external/awscli/commands/iam.rb +31 -0
  80. data/lib/zaws/external/awscli/commands/iam/GetPolicy.rb +21 -0
  81. data/lib/zaws/external/awscli/commands/iam/GetPolicyVersion.rb +21 -0
  82. data/lib/zaws/external/awscli/commands/iam/GetRolePolicy.rb +21 -0
  83. data/lib/zaws/external/awscli/commands/route53.rb +19 -0
  84. data/lib/zaws/external/awscli/commands/route53/list_hosted_zones.rb +30 -0
  85. data/lib/zaws/external/awscli/commands/route53/list_resource_record_sets.rb +41 -0
  86. data/lib/zaws/external/awscli/commands/s3/ls.rb +34 -0
  87. data/lib/zaws/external/awscli/commands/s3/mb.rb +41 -0
  88. data/lib/zaws/external/awscli/commands/s3/sync.rb +48 -0
  89. data/lib/zaws/external/awscli/credentials.rb +22 -0
  90. data/lib/zaws/external/awscli/data.rb +10 -0
  91. data/lib/zaws/external/awscli/data/ec2.rb +33 -0
  92. data/lib/zaws/external/awscli/data/ec2/instance.rb +162 -0
  93. data/lib/zaws/external/awscli/data/ec2/security_group.rb +51 -0
  94. data/lib/zaws/external/awscli/data/ec2/subnet.rb +59 -0
  95. data/lib/zaws/external/awscli/data/ec2/vpc.rb +85 -0
  96. data/lib/zaws/external/awscli/data/iam.rb +34 -0
  97. data/lib/zaws/external/awscli/data/iam/policy.rb +42 -0
  98. data/lib/zaws/external/awscli/data/iam/policy_document.rb +52 -0
  99. data/lib/zaws/external/awscli/data/iam/policy_version.rb +42 -0
  100. data/lib/zaws/external/awscli/data/iam/role_policy.rb +52 -0
  101. data/lib/zaws/external/awscli/generators/result/ec2/addresses.rb +70 -0
  102. data/lib/zaws/external/awscli/generators/result/ec2/allocation_id.rb +39 -0
  103. data/lib/zaws/external/awscli/generators/result/ec2/association_id.rb +29 -0
  104. data/lib/zaws/external/awscli/generators/result/ec2/images.rb +46 -0
  105. data/lib/zaws/external/awscli/generators/result/ec2/instances.rb +57 -0
  106. data/lib/zaws/external/awscli/generators/result/ec2/ip_permissions.rb +70 -0
  107. data/lib/zaws/external/awscli/generators/result/ec2/network_interfaces.rb +53 -0
  108. data/lib/zaws/external/awscli/generators/result/ec2/private_ip_addresses.rb +41 -0
  109. data/lib/zaws/external/awscli/generators/result/ec2/route_tables.rb +80 -0
  110. data/lib/zaws/external/awscli/generators/result/ec2/routes.rb +58 -0
  111. data/lib/zaws/external/awscli/generators/result/ec2/security_groups.rb +73 -0
  112. data/lib/zaws/external/awscli/generators/result/ec2/subnets.rb +88 -0
  113. data/lib/zaws/external/awscli/generators/result/ec2/tags.rb +34 -0
  114. data/lib/zaws/external/awscli/generators/result/ec2/virtual_gateway.rb +32 -0
  115. data/lib/zaws/external/awscli/generators/result/elb/listeners.rb +65 -0
  116. data/lib/zaws/external/awscli/generators/result/elb/load_balancers.rb +61 -0
  117. data/lib/zaws/external/awscli/generators/result/route53/hosted_zones.rb +52 -0
  118. data/lib/zaws/external/awscli/regions.rb +13 -0
  119. data/lib/zaws/external/nessusapi/data/agents.rb +36 -0
  120. data/lib/zaws/external/nessusapi/data/scanners.rb +35 -0
  121. data/lib/zaws/external/nessusapi/nessusapi.rb +57 -0
  122. data/lib/zaws/external/nessusapi/reources.rb +10 -0
  123. data/lib/zaws/external/nessusapi/resources/agents.rb +18 -0
  124. data/lib/zaws/external/nessusapi/resources/agents/list.rb +20 -0
  125. data/lib/zaws/external/nessusapi/resources/scanners.rb +18 -0
  126. data/lib/zaws/external/nessusapi/resources/scanners/list.rb +20 -0
  127. data/lib/zaws/external/newrelicapi/data/servers.rb +36 -0
  128. data/lib/zaws/external/newrelicapi/newrelic_client.rb +64 -0
  129. data/lib/zaws/external/newrelicapi/newrelic_creds.rb +60 -0
  130. data/lib/zaws/external/newrelicapi/newrelicapi.rb +46 -0
  131. data/lib/zaws/external/newrelicapi/resources/servers.rb +18 -0
  132. data/lib/zaws/external/newrelicapi/resources/servers/list.rb +20 -0
  133. data/lib/zaws/external/sumoapi/data/collectors.rb +35 -0
  134. data/lib/zaws/external/sumoapi/data/sources.rb +35 -0
  135. data/lib/zaws/external/sumoapi/resources/collectors.rb +18 -0
  136. data/lib/zaws/external/sumoapi/resources/collectors/list.rb +20 -0
  137. data/lib/zaws/external/sumoapi/resources/sources.rb +18 -0
  138. data/lib/zaws/external/sumoapi/resources/sources/list.rb +20 -0
  139. data/lib/zaws/external/sumoapi/sumo_client.rb +63 -0
  140. data/lib/zaws/external/sumoapi/sumo_creds.rb +67 -0
  141. data/lib/zaws/external/sumoapi/sumoapi.rb +56 -0
  142. data/lib/zaws/helper/data_lattice.rb +22 -0
  143. data/lib/zaws/helper/filestore.rb +48 -0
  144. data/lib/zaws/helper/filter.rb +15 -0
  145. data/lib/zaws/helper/inifile.rb +632 -0
  146. data/lib/zaws/helper/nessus_client.rb +143 -0
  147. data/lib/zaws/helper/nessus_creds.rb +67 -0
  148. data/lib/zaws/helper/option.rb +14 -15
  149. data/lib/zaws/helper/output.rb +81 -29
  150. data/lib/zaws/helper/process_hash.rb +47 -0
  151. data/lib/zaws/helper/shell.rb +0 -0
  152. data/lib/zaws/helper/verbose.rb +15 -0
  153. data/lib/zaws/helper/zfile.rb +8 -8
  154. data/lib/zaws/services/ai.rb +35 -0
  155. data/lib/zaws/services/ai/query.rb +135 -0
  156. data/lib/zaws/services/aws.rb +41 -0
  157. data/lib/zaws/services/chef.rb +0 -0
  158. data/lib/zaws/services/cloud_trail.rb +76 -0
  159. data/lib/zaws/services/config.rb +31 -0
  160. data/lib/zaws/services/ec2.rb +47 -0
  161. data/lib/zaws/services/ec2/compute.rb +352 -0
  162. data/lib/zaws/services/ec2/elasticip.rb +82 -0
  163. data/lib/zaws/services/ec2/route_table.rb +210 -0
  164. data/lib/zaws/services/ec2/security_group.rb +186 -0
  165. data/lib/zaws/services/ec2/subnet.rb +111 -0
  166. data/lib/zaws/services/ec2/vpc.rb +69 -0
  167. data/lib/zaws/{elb.rb → services/elb.rb} +3 -2
  168. data/lib/zaws/services/elb/load_balancer.rb +160 -0
  169. data/lib/zaws/services/iam.rb +25 -0
  170. data/lib/zaws/services/iam/policy.rb +25 -0
  171. data/lib/zaws/services/iam/role.rb +23 -0
  172. data/lib/zaws/services/nessus.rb +24 -0
  173. data/lib/zaws/services/nessus/agents.rb +19 -0
  174. data/lib/zaws/services/nessus/scanners.rb +19 -0
  175. data/lib/zaws/services/newrelic.rb +21 -0
  176. data/lib/zaws/services/newrelic/servers.rb +19 -0
  177. data/lib/zaws/{route53.rb → services/route53.rb} +1 -1
  178. data/lib/zaws/services/route53/hosted_zone.rb +36 -0
  179. data/lib/zaws/services/s3.rb +15 -0
  180. data/lib/zaws/services/s3/bucket.rb +42 -0
  181. data/lib/zaws/services/sumo.rb +21 -0
  182. data/lib/zaws/services/sumo/collectors.rb +19 -0
  183. data/lib/zaws/services/vmware.rb +0 -0
  184. data/lib/zaws/version.rb +1 -1
  185. data/shove_all.sh +6 -0
  186. data/shove_all_mac.sh +6 -0
  187. data/shove_all_windows.sh +6 -0
  188. data/spec/spec_helper.rb +0 -0
  189. data/spec/zaws/command/ec2/compute/assoc_security_group_spec.rb +135 -0
  190. data/spec/zaws/command/ec2/compute/compute_spec.rb +321 -0
  191. data/spec/zaws/command/ec2/compute/images_spec.rb +69 -0
  192. data/spec/zaws/command/ec2/compute/management_spec.rb +364 -0
  193. data/spec/zaws/command/ec2/compute/network_spec.rb +93 -0
  194. data/spec/zaws/command/ec2/compute/node_spec.rb +70 -0
  195. data/spec/zaws/command/ec2/compute/secondary_ip_spec.rb +212 -0
  196. data/spec/zaws/command/ec2/compute/storage_spec.rb +63 -0
  197. data/spec/zaws/command/ec2/elasticip_spec.rb +271 -0
  198. data/spec/zaws/command/ec2/route_table_spec.rb +844 -0
  199. data/spec/zaws/command/ec2/security_group_spec.rb +710 -0
  200. data/spec/zaws/command/ec2/subnet_spec.rb +273 -0
  201. data/spec/zaws/command/ec2/vpc_spec.rb +180 -0
  202. data/spec/zaws/command/elb/load_balancer_spec.rb +633 -0
  203. data/spec/zaws/command/iam/policy_spec.rb +101 -0
  204. data/spec/zaws/command/iam/role_policy_spec.rb +35 -0
  205. data/spec/zaws/command/route53/hosted_zone_spec.rb +100 -0
  206. data/spec/zaws/command/s3/bucket_spec.rb +70 -0
  207. data/spec/zaws/external/awscli/data/ec2/instance_spec.rb +90 -0
  208. data/spec/zaws/external/awscli/data/iam/policy_document_spec.rb +56 -0
  209. data/spec/zaws/external/awscli/data/iam/role_policy_spec.rb +54 -0
  210. data/spec/zaws/external/awscli/get_aws_version_spec.rb +18 -0
  211. data/spec/zaws/helper/option_spec.rb +54 -0
  212. data/spec/zaws/helper/output_spec.rb +144 -0
  213. data/spec/zaws/helper/process_hash_spec.rb +48 -0
  214. data/spec/zaws/helper/shell_spec.rb +56 -0
  215. data/spec/zaws/nessus/scanners.json +0 -0
  216. data/spec/zaws/version_spec.rb +18 -0
  217. data/zaws.gemspec +1 -3
  218. metadata +260 -189
  219. data/feature/compute/assoc_security_group.feature +0 -55
  220. data/feature/compute/compute.feature +0 -138
  221. data/feature/compute/secondary_ip.feature +0 -107
  222. data/feature/compute/view.feature +0 -23
  223. data/feature/compute/view_images.feature +0 -24
  224. data/feature/elasticip/elasticip.feature +0 -138
  225. data/feature/elasticip/view.feature +0 -18
  226. data/feature/hosted_zone/view.feature +0 -17
  227. data/feature/hosted_zone/view_record.feature +0 -29
  228. data/feature/load_balancer/instance_registration.feature +0 -120
  229. data/feature/load_balancer/listener.feature +0 -86
  230. data/feature/load_balancer/load_balancer.feature +0 -101
  231. data/feature/load_balancer/view.feature +0 -18
  232. data/feature/route_table/assoc_subnet.feature +0 -128
  233. data/feature/route_table/route_propagation.feature +0 -93
  234. data/feature/route_table/route_table.feature +0 -91
  235. data/feature/route_table/route_to_gateway.feature +0 -69
  236. data/feature/route_table/route_to_instance.feature +0 -115
  237. data/feature/route_table/view.feature +0 -25
  238. data/feature/security_group/ingress_cidr.feature +0 -144
  239. data/feature/security_group/ingress_group.feature +0 -184
  240. data/feature/security_group/security_group.feature +0 -107
  241. data/feature/security_group/view.feature +0 -23
  242. data/feature/subnet/subnet.feature +0 -94
  243. data/feature/subnet/view.feature +0 -24
  244. data/feature/support/env.rb +0 -14
  245. data/feature/version.feature +0 -6
  246. data/lib/zaws/aws.rb +0 -26
  247. data/lib/zaws/ec2.rb +0 -40
  248. data/lib/zaws/ec2/compute.rb +0 -247
  249. data/lib/zaws/ec2/elasticip.rb +0 -79
  250. data/lib/zaws/ec2/route_table.rb +0 -207
  251. data/lib/zaws/ec2/security_group.rb +0 -154
  252. data/lib/zaws/ec2/subnet.rb +0 -109
  253. data/lib/zaws/elb/load_balancer.rb +0 -157
  254. data/lib/zaws/route53/hosted_zone.rb +0 -36
  255. data/spec/zaws/ec2/compute/add_volume_spec.rb +0 -39
  256. data/spec/zaws/ec2/compute/block_device_mapping_spec.rb +0 -31
  257. data/spec/zaws/ec2/compute/instance_id_by_external_id_spec.rb +0 -23
  258. data/spec/zaws/ec2/compute/instance_ping_spec.rb +0 -34
  259. data/spec/zaws/ec2/compute/instance_running_spec.rb +0 -47
  260. data/spec/zaws/ec2/compute/network_interface_json_spec.rb +0 -57
  261. data/spec/zaws/ec2/compute/nosdcheck_spec.rb +0 -17
  262. data/spec/zaws/ec2/compute/tag_instance_spec.rb +0 -21
  263. data/spec/zaws/ec2/security_group/id_by_name_spec.rb +0 -32
  264. data/spec/zaws/ec2/subnet/available_spec.rb +0 -22
  265. data/spec/zaws/ec2/subnet/declare_spec.rb +0 -31
  266. data/spec/zaws/ec2/subnet/exists_spec.rb +0 -33
  267. data/spec/zaws/ec2/subnet/id_array_by_cidrblock_array_spec.rb +0 -48
  268. data/spec/zaws/ec2/subnet/id_by_cidrblock_spec.rb +0 -35
  269. data/spec/zaws/ec2/subnet/id_by_ip_spec.rb +0 -42
  270. data/spec/zaws/ec2/subnet/view_spec.rb +0 -34
  271. data/spec/zaws/elb/load_balancer/calculated_listener_spec.rb +0 -18
  272. data/spec/zaws/helper/option/absent_spec.rb +0 -14
  273. data/spec/zaws/helper/option/exclusive_spec.rb +0 -14
  274. data/spec/zaws/helper/option/exists_spec.rb +0 -18
  275. data/spec/zaws/helper/option/minimum_spec.rb +0 -14
  276. data/spec/zaws/helper/output/binary_nagios_check_spec.rb +0 -19
  277. data/spec/zaws/helper/output/colorize_spec.rb +0 -30
  278. data/spec/zaws/helper/output/opt_exclusive_spec.rb +0 -14
  279. data/spec/zaws/helper/output/opt_minimum_spec.rb +0 -15
  280. data/spec/zaws/helper/output/opt_required_spec.rb +0 -12
  281. data/spec/zaws/helper/shell/cli_spec.rb +0 -33
  282. data/spec/zaws/helper/shell/if_then_spec.rb +0 -24
@@ -0,0 +1,35 @@
1
+ module ZAWS
2
+ class Sumoapi
3
+ class Data
4
+ class Sources
5
+
6
+ def initialize(shellout, sumoapi)
7
+ @shellout=shellout
8
+ @sumoapi=sumoapi
9
+ @instance_hash=nil
10
+ end
11
+
12
+ def validJSON
13
+ return (@instance_hash.nil?)
14
+ end
15
+
16
+ def load(data, verbose)
17
+ @instance_raw_data = data
18
+ verbose.puts(@instance_raw_data) if verbose
19
+ @instance_hash=data
20
+ end
21
+
22
+ def view(verbose,sourceid)
23
+ details = @sumoapi.filestore.retrieve("sources#{sourceid}")
24
+ if details.nil?
25
+ load(@sumoapi.resource_sources.list.execute(verbose,sourceid),verbose)
26
+ @sumoapi.filestore.store("sources#{sourceid}",@instance_hash,Time.now + @sumoapi.filestore.timeout)
27
+ else
28
+ load(details,verbose)
29
+ end
30
+ return @instance_raw_data
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,18 @@
1
+ module ZAWS
2
+ class Sumoapi
3
+ class Resources
4
+ class Collectors
5
+ def initialize(shellout, nessusapi)
6
+ @shellout=shellout
7
+ @nessusapi=nessusapi
8
+ end
9
+
10
+ def list
11
+ @_list ||= (ZAWS::Sumoapi::Resources::Collectors::List.new(@shellout, @nessusapi))
12
+ return @_list
13
+ end
14
+
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,20 @@
1
+ module ZAWS
2
+ class Sumoapi
3
+ class Resources
4
+ class Collectors
5
+ class List
6
+
7
+ def initialize(shellout,sumoapi)
8
+ @shellout=shellout
9
+ @sumoapi=sumoapi
10
+ end
11
+
12
+ def execute(verbose=nil)
13
+ @sumoapi.client.get("/api/v1/collectors")
14
+ end
15
+
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,18 @@
1
+ module ZAWS
2
+ class Sumoapi
3
+ class Resources
4
+ class Sources
5
+ def initialize(shellout, nessusapi)
6
+ @shellout=shellout
7
+ @nessusapi=nessusapi
8
+ end
9
+
10
+ def list
11
+ @_list ||= (ZAWS::Sumoapi::Resources::Sources::List.new(@shellout, @nessusapi))
12
+ return @_list
13
+ end
14
+
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,20 @@
1
+ module ZAWS
2
+ class Sumoapi
3
+ class Resources
4
+ class Sources
5
+ class List
6
+
7
+ def initialize(shellout,sumoapi)
8
+ @shellout=shellout
9
+ @sumoapi=sumoapi
10
+ end
11
+
12
+ def execute(verbose=nil,sourceid)
13
+ @sumoapi.client.get("/api/v1/collectors/#{sourceid}/sources")
14
+ end
15
+
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,63 @@
1
+ require 'excon'
2
+ require 'json'
3
+
4
+ module ZAWS
5
+ class Sumoapi
6
+ class SumoClient
7
+
8
+ autoload :SumoCreds, "zaws/sumoapi/sumo_creds"
9
+
10
+ # @param [SumoClient::Creds] creds
11
+ def initialize(creds)
12
+ @creds = creds
13
+ end
14
+
15
+ def url
16
+ @creds.url
17
+ end
18
+
19
+ # Make a GET request expecting a JSON response.
20
+ def get(path, query = {}, options = {})
21
+ # Handle nil or empty Array
22
+ options[:query] = query.to_h if query
23
+ options[:idempotent] = true
24
+ json_request('GET', path, options)
25
+ end
26
+
27
+ # Make a POST request expecting a JSON response.
28
+ def post(path, body, options = {})
29
+ options[:body] = body
30
+ json_request('POST', path, options)
31
+ end
32
+
33
+ # Make a PUT request expecting a JSON response.
34
+ def put(path, body, options = {})
35
+ options[:body] = body
36
+ json_request('PUT', path, options)
37
+ end
38
+
39
+ def delete(path, options = {})
40
+ options[:idempotent] = true
41
+ json_request('DELETE', path, options)
42
+ end
43
+
44
+ def json_request(method, path, options = {})
45
+ if options[:body] && !options[:body].instance_of?(String)
46
+ options[:body] = options[:body].to_json
47
+ end
48
+ options[:headers] ||= {}
49
+ options[:headers]['Content-Type'] = 'application/json'
50
+ response = request(method, path, options)
51
+ JSON.parse(response.body) if (response.body.length > 0 && response.headers['content-type'].match(/json/))
52
+ end
53
+
54
+ def request(method, path, options = {})
55
+ connection = Excon.new(@creds.url, :user => "#{@creds.access_id}", :password => "#{@creds.access_key}")
56
+ options[:expects] ||= [200]
57
+ options[:method] = method
58
+ options[:path] = path
59
+ connection.request(options)
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,67 @@
1
+ require 'yaml'
2
+
3
+ module ZAWS
4
+ class Sumoapi
5
+ class SumoCreds
6
+ # Simple container for credentials
7
+ class Creds
8
+
9
+ # @param [String] nessus_url
10
+ # @param [String] access_key
11
+ # @param [String] secret_key
12
+ def initialize(nessus_url, access_key, secret_key)
13
+ @creds = {}
14
+ @creds[:url] = nessus_url
15
+ @creds[:access_key] = access_key
16
+ @creds[:secret_key] = secret_key
17
+ end
18
+
19
+ def url
20
+ fetch_creds[:url]
21
+ end
22
+
23
+ def access_id
24
+ fetch_creds[:access_id]
25
+ end
26
+
27
+ def access_key
28
+ fetch_creds[:access_key]
29
+ end
30
+
31
+ private
32
+
33
+ def fetch_creds
34
+ # Nothing to do in the base class
35
+ @creds
36
+ end
37
+ end
38
+
39
+ # Subclass that loads creds from a YAML file.
40
+ class Creds::YamlFile < Creds
41
+ FILENAME = '.sumo.yml'
42
+
43
+ def initialize(home)
44
+ @creds_file = File.join(home, FILENAME)
45
+ end
46
+
47
+ private
48
+
49
+ def fetch_creds
50
+ unless @creds
51
+ fail("Missing file #{@creds_file}") unless File.exist?(@creds_file)
52
+ file_creds = YAML.load(File.read(@creds_file))
53
+ file_creds ||= {}
54
+ ['url', 'accessID', 'accessKey'].each do |key|
55
+ fail("Missing #{key} value in #{@creds_file}") unless file_creds[key]
56
+ end
57
+ @creds = {}
58
+ @creds[:url] = file_creds['url']
59
+ @creds[:access_id] = file_creds['accessID']
60
+ @creds[:access_key] = file_creds['accessKey']
61
+ end
62
+ @creds
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,56 @@
1
+ module ZAWS
2
+ class Sumoapi
3
+
4
+ attr_accessor :home
5
+
6
+ def initialize(shellout)
7
+ @shellout=shellout
8
+ end
9
+
10
+ def filestore
11
+ @filestore ||= ZAWS::Repository::Filestore.new()
12
+ @filestore.location="#{@home}/.sumoapi"
13
+ unless File.directory?(@filestore.location)
14
+ FileUtils.mkdir_p(@filestore.location)
15
+ end
16
+ @filestore.timeout = 600
17
+ return @filestore
18
+ end
19
+
20
+ def remove_creds
21
+ if File.directory?("#{@home}/.sumoapi")
22
+ FileUtils.rmtree("#{@home}/.sumoapi")
23
+ end
24
+ if File.exist?("#{@home}/.sumo.yml")
25
+ File.delete("#{@home}/.sumo.yml")
26
+ end
27
+ end
28
+
29
+ def resource_collectors
30
+ @_resource_collectors ||= (ZAWS::Sumoapi::Resources::Collectors.new(@shellout, self))
31
+ return @_resource_collectors
32
+ end
33
+
34
+ def resource_sources
35
+ @_resource_sources ||= (ZAWS::Sumoapi::Resources::Sources.new(@shellout, self))
36
+ return @_resource_sources
37
+ end
38
+
39
+ def client
40
+ fail("Home is null! Make sure its set before getting the client.") if @home== nil
41
+ creds = ZAWS::Sumoapi::SumoCreds::Creds::YamlFile.new(@home)
42
+ @_client ||= (ZAWS::Sumoapi::SumoClient.new(creds))
43
+ end
44
+
45
+ def data_collectors
46
+ @_data_collectors ||= (ZAWS::Sumoapi::Data::Collectors.new(@shellout, self))
47
+ return @_data_collectors
48
+ end
49
+
50
+ def data_sources
51
+ @_data_sources ||= (ZAWS::Sumoapi::Data::Sources.new(@shellout, self))
52
+ return @_data_sources
53
+ end
54
+
55
+ end
56
+ end
@@ -0,0 +1,22 @@
1
+ module ZAWS
2
+ module Helper
3
+ class DataLattice
4
+
5
+ def initialize()
6
+ @lattice = nil
7
+ end
8
+
9
+ def load(data)
10
+ nessus_agents(data)
11
+ aws_instance(data)
12
+ sumologic_collector(data)
13
+ end
14
+
15
+ def save(filename)
16
+
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+
@@ -0,0 +1,48 @@
1
+ require 'yaml'
2
+ require 'date'
3
+ require 'digest/md5'
4
+
5
+ module ZAWS
6
+ class Repository
7
+ class Filestore
8
+ attr_accessor :location
9
+ attr_accessor :timeout
10
+
11
+ def initialize(empty=false)
12
+ @empty=empty
13
+ end
14
+
15
+ def store(key,value,expires,command=nil)
16
+ return if @empty
17
+ storage = {}
18
+ storage['value']=value
19
+ storage['expires']=expires.strftime('%s')
20
+ if command.nil?
21
+ filename=key
22
+ else
23
+ storage['command']=command
24
+ filename=key+Digest::MD5.hexdigest(command)
25
+ end
26
+ File.open("#{@location}/#{filename}","w") do |file|
27
+ file.write storage.to_yaml
28
+ end
29
+ end
30
+
31
+ def retrieve(key,command=nil)
32
+ return if @empty
33
+ if command.nil?
34
+ filename=key
35
+ else
36
+ filename=key+Digest::MD5.hexdigest(command)
37
+ end
38
+ if File.exists?("#{@location}/#{filename}")
39
+ storage = YAML.load(File.read("#{@location}/#{filename}"))
40
+ if storage['expires'].to_i > Time.now.to_i
41
+ return storage['value']
42
+ end
43
+ end
44
+ end
45
+
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,15 @@
1
+ module ZAWS
2
+ module Helper
3
+ class Filter
4
+
5
+ def self.filter(comline, filters)
6
+ result = comline + " --filter"
7
+ filters.each do |key, item|
8
+ result = result + " 'Name=#{key},Values=#{item}'"
9
+ end
10
+ return result
11
+ end
12
+
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,632 @@
1
+ #encoding: UTF-8
2
+
3
+ # This class represents the INI file and can be used to parse, modify,
4
+ # and write INI files.
5
+
6
+ module ZAWS
7
+ module Helper
8
+ class IniFile
9
+ include Enumerable
10
+
11
+ class Error < StandardError; end
12
+ VERSION = '3.0.0'
13
+
14
+ # Public: Open an INI file and load the contents.
15
+ #
16
+ # filename - The name of the file as a String
17
+ # opts - The Hash of options (default: {})
18
+ # :comment - String containing the comment character(s)
19
+ # :parameter - String used to separate parameter and value
20
+ # :encoding - Encoding String for reading / writing
21
+ # :default - The String name of the default global section
22
+ #
23
+ # Examples
24
+ #
25
+ # IniFile.load('file.ini')
26
+ # #=> IniFile instance
27
+ #
28
+ # IniFile.load('does/not/exist.ini')
29
+ # #=> nil
30
+ #
31
+ # Returns an IniFile instance or nil if the file could not be opened.
32
+ def self.load( filename, opts = {} )
33
+ return unless File.file? filename
34
+ new(opts.merge(:filename => filename))
35
+ end
36
+
37
+ # Get and set the filename
38
+ attr_accessor :filename
39
+
40
+ # Get and set the encoding
41
+ attr_accessor :encoding
42
+
43
+ # Public: Create a new INI file from the given set of options. If :content
44
+ # is provided then it will be used to populate the INI file. If a :filename
45
+ # is provided then the contents of the file will be parsed and stored in the
46
+ # INI file. If neither the :content or :filename is provided then an empty
47
+ # INI file is created.
48
+ #
49
+ # opts - The Hash of options (default: {})
50
+ # :content - The String/Hash containing the INI contents
51
+ # :comment - String containing the comment character(s)
52
+ # :parameter - String used to separate parameter and value
53
+ # :encoding - Encoding String for reading / writing
54
+ # :default - The String name of the default global section
55
+ # :filename - The filename as a String
56
+ #
57
+ # Examples
58
+ #
59
+ # IniFile.new
60
+ # #=> an empty IniFile instance
61
+ #
62
+ # IniFile.new( :content => "[global]\nfoo=bar" )
63
+ # #=> an IniFile instance
64
+ #
65
+ # IniFile.new( :filename => 'file.ini', :encoding => 'UTF-8' )
66
+ # #=> an IniFile instance
67
+ #
68
+ # IniFile.new( :content => "[global]\nfoo=bar", :comment => '#' )
69
+ # #=> an IniFile instance
70
+ #
71
+ def initialize( opts = {} )
72
+ @comment = opts.fetch(:comment, ';#')
73
+ @param = opts.fetch(:parameter, '=')
74
+ @encoding = opts.fetch(:encoding, nil)
75
+ @default = opts.fetch(:default, 'global')
76
+ @filename = opts.fetch(:filename, nil)
77
+ content = opts.fetch(:content, nil)
78
+
79
+ @ini = Hash.new {|h,k| h[k] = Hash.new}
80
+
81
+ if content.is_a?(Hash) then merge!(content)
82
+ elsif content then parse(content)
83
+ elsif @filename then read
84
+ end
85
+ end
86
+
87
+ # Public: Write the contents of this IniFile to the file system. If left
88
+ # unspecified, the currently configured filename and encoding will be used.
89
+ # Otherwise the filename and encoding can be specified in the options hash.
90
+ #
91
+ # opts - The default options Hash
92
+ # :filename - The filename as a String
93
+ # :encoding - The encoding as a String
94
+ #
95
+ # Returns this IniFile instance.
96
+ def write( opts = {} )
97
+ filename = opts.fetch(:filename, @filename)
98
+ encoding = opts.fetch(:encoding, @encoding)
99
+ mode = encoding ? "w:#{encoding}" : "w"
100
+
101
+ File.open(filename, mode) do |f|
102
+ @ini.each do |section,hash|
103
+ f.puts "[#{section}]"
104
+ hash.each {|param,val| f.puts "#{param} #{@param} #{escape_value val}"}
105
+ f.puts
106
+ end
107
+ end
108
+
109
+ self
110
+ end
111
+ alias :save :write
112
+
113
+ # Public: Read the contents of the INI file from the file system and replace
114
+ # and set the state of this IniFile instance. If left unspecified the
115
+ # currently configured filename and encoding will be used when reading from
116
+ # the file system. Otherwise the filename and encoding can be specified in
117
+ # the options hash.
118
+ #
119
+ # opts - The default options Hash
120
+ # :filename - The filename as a String
121
+ # :encoding - The encoding as a String
122
+ #
123
+ # Returns this IniFile instance if the read was successful; nil is returned
124
+ # if the file could not be read.
125
+ def read( opts = {} )
126
+ filename = opts.fetch(:filename, @filename)
127
+ encoding = opts.fetch(:encoding, @encoding)
128
+ return unless File.file? filename
129
+
130
+ mode = encoding ? "r:#{encoding}" : "r"
131
+ File.open(filename, mode) { |fd| parse fd }
132
+ self
133
+ end
134
+ alias :restore :read
135
+
136
+ # Returns this IniFile converted to a String.
137
+ def to_s
138
+ s = []
139
+ @ini.each do |section,hash|
140
+ s << "[#{section}]"
141
+ hash.each {|param,val| s << "#{param} #{@param} #{escape_value val}"}
142
+ s << ""
143
+ end
144
+ s.join("\n")
145
+ end
146
+
147
+ # Returns this IniFile converted to a Hash.
148
+ def to_h
149
+ @ini.dup
150
+ end
151
+
152
+ # Public: Creates a copy of this inifile with the entries from the
153
+ # other_inifile merged into the copy.
154
+ #
155
+ # other - The other IniFile.
156
+ #
157
+ # Returns a new IniFile.
158
+ def merge( other )
159
+ self.dup.merge!(other)
160
+ end
161
+
162
+ # Public: Merges other_inifile into this inifile, overwriting existing
163
+ # entries. Useful for having a system inifile with user overridable settings
164
+ # elsewhere.
165
+ #
166
+ # other - The other IniFile.
167
+ #
168
+ # Returns this IniFile.
169
+ def merge!( other )
170
+ return self if other.nil?
171
+
172
+ my_keys = @ini.keys
173
+ other_keys = case other
174
+ when IniFile
175
+ other.instance_variable_get(:@ini).keys
176
+ when Hash
177
+ other.keys
178
+ else
179
+ raise Error, "cannot merge contents from '#{other.class.name}'"
180
+ end
181
+
182
+ (my_keys & other_keys).each do |key|
183
+ case other[key]
184
+ when Hash
185
+ @ini[key].merge!(other[key])
186
+ when nil
187
+ nil
188
+ else
189
+ raise Error, "cannot merge section #{key.inspect} - unsupported type: #{other[key].class.name}"
190
+ end
191
+ end
192
+
193
+ (other_keys - my_keys).each do |key|
194
+ @ini[key] = case other[key]
195
+ when Hash
196
+ other[key].dup
197
+ when nil
198
+ {}
199
+ else
200
+ raise Error, "cannot merge section #{key.inspect} - unsupported type: #{other[key].class.name}"
201
+ end
202
+ end
203
+
204
+ self
205
+ end
206
+
207
+ # Public: Yield each INI file section, parameter, and value in turn to the
208
+ # given block.
209
+ #
210
+ # block - The block that will be iterated by the each method. The block will
211
+ # be passed the current section and the parameter/value pair.
212
+ #
213
+ # Examples
214
+ #
215
+ # inifile.each do |section, parameter, value|
216
+ # puts "#{parameter} = #{value} [in section - #{section}]"
217
+ # end
218
+ #
219
+ # Returns this IniFile.
220
+ def each
221
+ return unless block_given?
222
+ @ini.each do |section,hash|
223
+ hash.each do |param,val|
224
+ yield section, param, val
225
+ end
226
+ end
227
+ self
228
+ end
229
+
230
+ # Public: Yield each section in turn to the given block.
231
+ #
232
+ # block - The block that will be iterated by the each method. The block will
233
+ # be passed the current section as a Hash.
234
+ #
235
+ # Examples
236
+ #
237
+ # inifile.each_section do |section|
238
+ # puts section.inspect
239
+ # end
240
+ #
241
+ # Returns this IniFile.
242
+ def each_section
243
+ return unless block_given?
244
+ @ini.each_key {|section| yield section}
245
+ self
246
+ end
247
+
248
+ # Public: Remove a section identified by name from the IniFile.
249
+ #
250
+ # section - The section name as a String.
251
+ #
252
+ # Returns the deleted section Hash.
253
+ def delete_section( section )
254
+ @ini.delete section.to_s
255
+ end
256
+
257
+ # Public: Get the section Hash by name. If the section does not exist, then
258
+ # it will be created.
259
+ #
260
+ # section - The section name as a String.
261
+ #
262
+ # Examples
263
+ #
264
+ # inifile['global']
265
+ # #=> global section Hash
266
+ #
267
+ # Returns the Hash of parameter/value pairs for this section.
268
+ def []( section )
269
+ return nil if section.nil?
270
+ @ini[section.to_s]
271
+ end
272
+
273
+ # Public: Set the section to a hash of parameter/value pairs.
274
+ #
275
+ # section - The section name as a String.
276
+ # value - The Hash of parameter/value pairs.
277
+ #
278
+ # Examples
279
+ #
280
+ # inifile['tenderloin'] = { 'gritty' => 'yes' }
281
+ # #=> { 'gritty' => 'yes' }
282
+ #
283
+ # Returns the value Hash.
284
+ def []=( section, value )
285
+ @ini[section.to_s] = value
286
+ end
287
+
288
+ # Public: Create a Hash containing only those INI file sections whose names
289
+ # match the given regular expression.
290
+ #
291
+ # regex - The Regexp used to match section names.
292
+ #
293
+ # Examples
294
+ #
295
+ # inifile.match(/^tree_/)
296
+ # #=> Hash of matching sections
297
+ #
298
+ # Return a Hash containing only those sections that match the given regular
299
+ # expression.
300
+ def match( regex )
301
+ @ini.dup.delete_if { |section, _| section !~ regex }
302
+ end
303
+
304
+ # Public: Check to see if the IniFile contains the section.
305
+ #
306
+ # section - The section name as a String.
307
+ #
308
+ # Returns true if the section exists in the IniFile.
309
+ def has_section?( section )
310
+ @ini.has_key? section.to_s
311
+ end
312
+
313
+ # Returns an Array of section names contained in this IniFile.
314
+ def sections
315
+ @ini.keys
316
+ end
317
+
318
+ # Public: Freeze the state of this IniFile object. Any attempts to change
319
+ # the object will raise an error.
320
+ #
321
+ # Returns this IniFile.
322
+ def freeze
323
+ super
324
+ @ini.each_value {|h| h.freeze}
325
+ @ini.freeze
326
+ self
327
+ end
328
+
329
+ # Public: Mark this IniFile as tainted -- this will traverse each section
330
+ # marking each as tainted.
331
+ #
332
+ # Returns this IniFile.
333
+ def taint
334
+ super
335
+ @ini.each_value {|h| h.taint}
336
+ @ini.taint
337
+ self
338
+ end
339
+
340
+ # Public: Produces a duplicate of this IniFile. The duplicate is independent
341
+ # of the original -- i.e. the duplicate can be modified without changing the
342
+ # original. The tainted state of the original is copied to the duplicate.
343
+ #
344
+ # Returns a new IniFile.
345
+ def dup
346
+ other = super
347
+ other.instance_variable_set(:@ini, Hash.new {|h,k| h[k] = Hash.new})
348
+ @ini.each_pair {|s,h| other[s].merge! h}
349
+ other.taint if self.tainted?
350
+ other
351
+ end
352
+
353
+ # Public: Produces a duplicate of this IniFile. The duplicate is independent
354
+ # of the original -- i.e. the duplicate can be modified without changing the
355
+ # original. The tainted state and the frozen state of the original is copied
356
+ # to the duplicate.
357
+ #
358
+ # Returns a new IniFile.
359
+ def clone
360
+ other = dup
361
+ other.freeze if self.frozen?
362
+ other
363
+ end
364
+
365
+ # Public: Compare this IniFile to some other IniFile. For two INI files to
366
+ # be equivalent, they must have the same sections with the same parameter /
367
+ # value pairs in each section.
368
+ #
369
+ # other - The other IniFile.
370
+ #
371
+ # Returns true if the INI files are equivalent and false if they differ.
372
+ def eql?( other )
373
+ return true if equal? other
374
+ return false unless other.instance_of? self.class
375
+ @ini == other.instance_variable_get(:@ini)
376
+ end
377
+ alias :== :eql?
378
+
379
+ # Escape special characters.
380
+ #
381
+ # value - The String value to escape.
382
+ #
383
+ # Returns the escaped value.
384
+ def escape_value( value )
385
+ value = value.to_s.dup
386
+ value.gsub!(%r/\\([0nrt])/, '\\\\\1')
387
+ value.gsub!(%r/\n/, '\n')
388
+ value.gsub!(%r/\r/, '\r')
389
+ value.gsub!(%r/\t/, '\t')
390
+ value.gsub!(%r/\0/, '\0')
391
+ value
392
+ end
393
+
394
+ # Parse the given content and store the information in this IniFile
395
+ # instance. All data will be cleared out and replaced with the information
396
+ # read from the content.
397
+ #
398
+ # content - A String or a file descriptor (must respond to `each_line`)
399
+ #
400
+ # Returns this IniFile.
401
+ def parse( content )
402
+ parser = Parser.new(@ini, @param, @comment, @default)
403
+ parser.parse(content)
404
+ self
405
+ end
406
+
407
+ # The IniFile::Parser has the responsibility of reading the contents of an
408
+ # .ini file and storing that information into a ruby Hash. The object being
409
+ # parsed must respond to `each_line` - this includes Strings and any IO
410
+ # object.
411
+ class Parser
412
+
413
+ attr_writer :section
414
+ attr_accessor :property
415
+ attr_accessor :value
416
+
417
+ # Create a new IniFile::Parser that can be used to parse the contents of
418
+ # an .ini file.
419
+ #
420
+ # hash - The Hash where parsed information will be stored
421
+ # param - String used to separate parameter and value
422
+ # comment - String containing the comment character(s)
423
+ # default - The String name of the default global section
424
+ #
425
+ def initialize( hash, param, comment, default )
426
+ @hash = hash
427
+ @default = default
428
+
429
+ comment = comment.to_s.empty? ? "\\z" : "\\s*(?:[#{comment}].*)?\\z"
430
+
431
+ @section_regexp = %r/\A\s*\[([^\]]+)\]#{comment}/
432
+ @ignore_regexp = %r/\A#{comment}/
433
+ @property_regexp = %r/\A(.*?)(?<!\\)#{param}(.*)\z/
434
+
435
+ @open_quote = %r/\A\s*(".*)\z/
436
+ @close_quote = %r/\A(.*(?<!\\)")#{comment}/
437
+ @full_quote = %r/\A\s*(".*(?<!\\)")#{comment}/
438
+ @trailing_slash = %r/\A(.*)(?<!\\)\\#{comment}/
439
+ @normal_value = %r/\A(.*?)#{comment}/
440
+ end
441
+
442
+ # Returns `true` if the current value starts with a leading double quote.
443
+ # Otherwise returns false.
444
+ def leading_quote?
445
+ value && value =~ %r/\A"/
446
+ end
447
+
448
+ # Given a string, attempt to parse out a value from that string. This
449
+ # value might be continued on the following line. So this method returns
450
+ # `true` if it is expecting more data.
451
+ #
452
+ # string - String to parse
453
+ #
454
+ # Returns `true` if the next line is also part of the current value.
455
+ # Returns `fase` if the string contained a complete value.
456
+ def parse_value( string )
457
+ continuation = false
458
+
459
+ # if our value starts with a double quote, then we are in a
460
+ # line continuation situation
461
+ if leading_quote?
462
+ # check for a closing quote at the end of the string
463
+ if string =~ @close_quote
464
+ value << $1
465
+
466
+ # otherwise just append the string to the value
467
+ else
468
+ value << string
469
+ continuation = true
470
+ end
471
+
472
+ # not currently processing a continuation line
473
+ else
474
+ case string
475
+ when @full_quote
476
+ self.value = $1
477
+
478
+ when @open_quote
479
+ self.value = $1
480
+ continuation = true
481
+
482
+ when @trailing_slash
483
+ self.value ? self.value << $1 : self.value = $1
484
+ continuation = true
485
+
486
+ when @normal_value
487
+ self.value ? self.value << $1 : self.value = $1
488
+
489
+ else
490
+ error
491
+ end
492
+ end
493
+
494
+ if continuation
495
+ self.value << $/ if leading_quote?
496
+ else
497
+ process_property
498
+ end
499
+
500
+ continuation
501
+ end
502
+
503
+ # Parse the ini file contents. This will clear any values currently stored
504
+ # in the ini hash.
505
+ #
506
+ # content - Any object that responds to `each_line`
507
+ #
508
+ # Returns nil.
509
+ def parse( content )
510
+ return unless content
511
+
512
+ continuation = false
513
+
514
+ @hash.clear
515
+ @line = nil
516
+ self.section = nil
517
+
518
+ content.each_line do |line|
519
+ @line = line.chomp
520
+
521
+ if continuation
522
+ continuation = parse_value @line
523
+ else
524
+ case @line
525
+ when @ignore_regexp
526
+ nil
527
+ when @section_regexp
528
+ self.section = @hash[$1]
529
+ when @property_regexp
530
+ self.property = $1.strip
531
+ error if property.empty?
532
+
533
+ continuation = parse_value $2
534
+ else
535
+ error
536
+ end
537
+ end
538
+ end
539
+
540
+ # check here if we have a dangling value ... usually means we have an
541
+ # unmatched open quote
542
+ if leading_quote?
543
+ error "Unmatched open quote"
544
+ elsif property && value
545
+ process_property
546
+ elsif value
547
+ error
548
+ end
549
+
550
+ nil
551
+ end
552
+
553
+ # Store the property/value pair in the currently active section. This
554
+ # method checks for continuation of the value to the next line.
555
+ #
556
+ # Returns nil.
557
+ def process_property
558
+ property.strip!
559
+ value.strip!
560
+
561
+ self.value = $1 if value =~ %r/\A"(.*)(?<!\\)"\z/m
562
+
563
+ section[property] = typecast(value)
564
+
565
+ self.property = nil
566
+ self.value = nil
567
+ end
568
+
569
+ # Returns the current section Hash.
570
+ def section
571
+ @section ||= @hash[@default]
572
+ end
573
+
574
+ # Raise a parse error using the given message and appending the current line
575
+ # being parsed.
576
+ #
577
+ # msg - The message String to use.
578
+ #
579
+ # Raises IniFile::Error
580
+ def error( msg = 'Could not parse line' )
581
+ raise Error, "#{msg}: #{@line.inspect}"
582
+ end
583
+
584
+ # Attempt to typecast the value string. We are looking for boolean values,
585
+ # integers, floats, and empty strings. Below is how each gets cast, but it
586
+ # is pretty logical and straightforward.
587
+ #
588
+ # "true" --> true
589
+ # "false" --> false
590
+ # "" --> nil
591
+ # "42" --> 42
592
+ # "3.14" --> 3.14
593
+ # "foo" --> "foo"
594
+ #
595
+ # Returns the typecast value.
596
+ def typecast( value )
597
+ case value
598
+ when %r/\Atrue\z/i; true
599
+ when %r/\Afalse\z/i; false
600
+ when %r/\A\s*\z/i; nil
601
+ else
602
+ Integer(value) rescue \
603
+ Float(value) rescue \
604
+ unescape_value(value)
605
+ end
606
+ end
607
+
608
+ # Unescape special characters found in the value string. This will convert
609
+ # escaped null, tab, carriage return, newline, and backslash into their
610
+ # literal equivalents.
611
+ #
612
+ # value - The String value to unescape.
613
+ #
614
+ # Returns the unescaped value.
615
+ def unescape_value( value )
616
+ value = value.to_s
617
+ value.gsub!(%r/\\[0nrt\\]/) { |char|
618
+ case char
619
+ when '\0'; "\0"
620
+ when '\n'; "\n"
621
+ when '\r'; "\r"
622
+ when '\t'; "\t"
623
+ when '\\\\'; "\\"
624
+ end
625
+ }
626
+ value
627
+ end
628
+ end
629
+
630
+ end # IniFile
631
+ end
632
+ end