aws-sdk-v1 1.52.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (560) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +7 -0
  3. data/LICENSE.txt +12 -0
  4. data/README.md +337 -0
  5. data/bin/aws-rb +179 -0
  6. data/ca-bundle.crt +3554 -0
  7. data/endpoints.json +1671 -0
  8. data/lib/aws-sdk-v1.rb +2 -0
  9. data/lib/aws-sdk.rb +1 -0
  10. data/lib/aws.rb +14 -0
  11. data/lib/aws/api_config/AutoScaling-2011-01-01.yml +1070 -0
  12. data/lib/aws/api_config/CloudFormation-2010-05-15.yml +372 -0
  13. data/lib/aws/api_config/CloudFront-2013-05-12.yml +2448 -0
  14. data/lib/aws/api_config/CloudFront-2013-08-26.yml +2599 -0
  15. data/lib/aws/api_config/CloudFront-2013-09-27.yml +2765 -0
  16. data/lib/aws/api_config/CloudFront-2013-11-11.yml +2886 -0
  17. data/lib/aws/api_config/CloudFront-2013-11-22.yml +2918 -0
  18. data/lib/aws/api_config/CloudFront-2014-01-31.yml +2934 -0
  19. data/lib/aws/api_config/CloudFront-2014-05-31.yml +3100 -0
  20. data/lib/aws/api_config/CloudSearch-2011-02-01.yml +681 -0
  21. data/lib/aws/api_config/CloudSearch-2013-01-01.yml +1164 -0
  22. data/lib/aws/api_config/CloudTrail-2013-11-01.yml +130 -0
  23. data/lib/aws/api_config/CloudWatch-2010-08-01.yml +433 -0
  24. data/lib/aws/api_config/DataPipeline-2012-10-29.yml +422 -0
  25. data/lib/aws/api_config/DirectConnect-2012-10-25.yml +735 -0
  26. data/lib/aws/api_config/DynamoDB-2011-12-05.yml +1168 -0
  27. data/lib/aws/api_config/DynamoDB-2012-08-10.yml +2105 -0
  28. data/lib/aws/api_config/EC2-2013-08-15.yml +4708 -0
  29. data/lib/aws/api_config/EC2-2013-10-01.yml +4726 -0
  30. data/lib/aws/api_config/EC2-2013-10-15.yml +4651 -0
  31. data/lib/aws/api_config/EC2-2014-02-01.yml +4755 -0
  32. data/lib/aws/api_config/EC2-2014-05-01.yml +4812 -0
  33. data/lib/aws/api_config/ELB-2012-06-01.yml +766 -0
  34. data/lib/aws/api_config/EMR-2009-03-31.yml +972 -0
  35. data/lib/aws/api_config/ElastiCache-2013-06-15.yml +1188 -0
  36. data/lib/aws/api_config/ElastiCache-2014-03-24.yml +1375 -0
  37. data/lib/aws/api_config/ElastiCache-2014-07-15.yml +1385 -0
  38. data/lib/aws/api_config/ElasticBeanstalk-2010-12-01.yml +854 -0
  39. data/lib/aws/api_config/ElasticTranscoder-2012-09-25.yml +3082 -0
  40. data/lib/aws/api_config/Glacier-2012-06-01.yml +649 -0
  41. data/lib/aws/api_config/IAM-2010-05-08.yml +1339 -0
  42. data/lib/aws/api_config/ImportExport-2010-06-01.yml +109 -0
  43. data/lib/aws/api_config/Kinesis-2013-12-02.yml +201 -0
  44. data/lib/aws/api_config/OpsWorks-2013-02-18.yml +2025 -0
  45. data/lib/aws/api_config/RDS-2013-05-15.yml +2464 -0
  46. data/lib/aws/api_config/RDS-2013-09-09.yml +2640 -0
  47. data/lib/aws/api_config/Redshift-2012-12-01.yml +2161 -0
  48. data/lib/aws/api_config/Route53-2012-12-12.yml +547 -0
  49. data/lib/aws/api_config/Route53-2013-04-01.yml +889 -0
  50. data/lib/aws/api_config/SNS-2010-03-31.yml +448 -0
  51. data/lib/aws/api_config/SQS-2012-11-05.yml +404 -0
  52. data/lib/aws/api_config/STS-2011-06-15.yml +151 -0
  53. data/lib/aws/api_config/SimpleDB-2009-04-15.yml +306 -0
  54. data/lib/aws/api_config/SimpleEmailService-2010-12-01.yml +346 -0
  55. data/lib/aws/api_config/SimpleWorkflow-2012-01-25.yml +2388 -0
  56. data/lib/aws/api_config/StorageGateway-2012-06-30.yml +748 -0
  57. data/lib/aws/api_config/StorageGateway-2013-06-30.yml +1025 -0
  58. data/lib/aws/api_config/Support-2013-04-15.yml +489 -0
  59. data/lib/aws/auto_scaling.rb +163 -0
  60. data/lib/aws/auto_scaling/activity.rb +102 -0
  61. data/lib/aws/auto_scaling/activity_collection.rb +81 -0
  62. data/lib/aws/auto_scaling/client.rb +48 -0
  63. data/lib/aws/auto_scaling/config.rb +18 -0
  64. data/lib/aws/auto_scaling/errors.rb +22 -0
  65. data/lib/aws/auto_scaling/group.rb +421 -0
  66. data/lib/aws/auto_scaling/group_collection.rb +96 -0
  67. data/lib/aws/auto_scaling/group_options.rb +155 -0
  68. data/lib/aws/auto_scaling/instance.rb +192 -0
  69. data/lib/aws/auto_scaling/instance_collection.rb +63 -0
  70. data/lib/aws/auto_scaling/launch_configuration.rb +162 -0
  71. data/lib/aws/auto_scaling/launch_configuration_collection.rb +160 -0
  72. data/lib/aws/auto_scaling/notification_configuration.rb +89 -0
  73. data/lib/aws/auto_scaling/notification_configuration_collection.rb +183 -0
  74. data/lib/aws/auto_scaling/scaling_policy.rb +142 -0
  75. data/lib/aws/auto_scaling/scaling_policy_collection.rb +72 -0
  76. data/lib/aws/auto_scaling/scaling_policy_options.rb +65 -0
  77. data/lib/aws/auto_scaling/scheduled_action.rb +141 -0
  78. data/lib/aws/auto_scaling/scheduled_action_collection.rb +202 -0
  79. data/lib/aws/auto_scaling/tag.rb +59 -0
  80. data/lib/aws/auto_scaling/tag_collection.rb +114 -0
  81. data/lib/aws/cloud_formation.rb +272 -0
  82. data/lib/aws/cloud_formation/client.rb +48 -0
  83. data/lib/aws/cloud_formation/config.rb +18 -0
  84. data/lib/aws/cloud_formation/errors.rb +22 -0
  85. data/lib/aws/cloud_formation/stack.rb +266 -0
  86. data/lib/aws/cloud_formation/stack_collection.rb +232 -0
  87. data/lib/aws/cloud_formation/stack_event.rb +73 -0
  88. data/lib/aws/cloud_formation/stack_event_collection.rb +47 -0
  89. data/lib/aws/cloud_formation/stack_options.rb +72 -0
  90. data/lib/aws/cloud_formation/stack_output.rb +53 -0
  91. data/lib/aws/cloud_formation/stack_resource.rb +117 -0
  92. data/lib/aws/cloud_formation/stack_resource_collection.rb +83 -0
  93. data/lib/aws/cloud_formation/stack_resource_summary_collection.rb +64 -0
  94. data/lib/aws/cloud_formation/stack_summary_collection.rb +123 -0
  95. data/lib/aws/cloud_front.rb +72 -0
  96. data/lib/aws/cloud_front/client.rb +57 -0
  97. data/lib/aws/cloud_front/config.rb +18 -0
  98. data/lib/aws/cloud_front/errors.rb +22 -0
  99. data/lib/aws/cloud_search.rb +73 -0
  100. data/lib/aws/cloud_search/client.rb +40 -0
  101. data/lib/aws/cloud_search/config.rb +18 -0
  102. data/lib/aws/cloud_search/errors.rb +22 -0
  103. data/lib/aws/cloud_trail.rb +72 -0
  104. data/lib/aws/cloud_trail/client.rb +35 -0
  105. data/lib/aws/cloud_trail/config.rb +18 -0
  106. data/lib/aws/cloud_trail/errors.rb +22 -0
  107. data/lib/aws/cloud_watch.rb +118 -0
  108. data/lib/aws/cloud_watch/alarm.rb +293 -0
  109. data/lib/aws/cloud_watch/alarm_collection.rb +153 -0
  110. data/lib/aws/cloud_watch/alarm_history_item.rb +50 -0
  111. data/lib/aws/cloud_watch/alarm_history_item_collection.rb +84 -0
  112. data/lib/aws/cloud_watch/client.rb +40 -0
  113. data/lib/aws/cloud_watch/config.rb +18 -0
  114. data/lib/aws/cloud_watch/errors.rb +22 -0
  115. data/lib/aws/cloud_watch/metric.rb +135 -0
  116. data/lib/aws/cloud_watch/metric_alarm_collection.rb +160 -0
  117. data/lib/aws/cloud_watch/metric_collection.rb +129 -0
  118. data/lib/aws/cloud_watch/metric_statistics.rb +69 -0
  119. data/lib/aws/core.rb +716 -0
  120. data/lib/aws/core/async_handle.rb +90 -0
  121. data/lib/aws/core/cacheable.rb +77 -0
  122. data/lib/aws/core/client.rb +787 -0
  123. data/lib/aws/core/collection.rb +263 -0
  124. data/lib/aws/core/collection/simple.rb +82 -0
  125. data/lib/aws/core/collection/with_limit_and_next_token.rb +71 -0
  126. data/lib/aws/core/collection/with_next_token.rb +97 -0
  127. data/lib/aws/core/configuration.rb +542 -0
  128. data/lib/aws/core/credential_providers.rb +639 -0
  129. data/lib/aws/core/data.rb +247 -0
  130. data/lib/aws/core/deprecations.rb +84 -0
  131. data/lib/aws/core/endpoints.rb +37 -0
  132. data/lib/aws/core/http/connection_pool.rb +369 -0
  133. data/lib/aws/core/http/curb_handler.rb +148 -0
  134. data/lib/aws/core/http/handler.rb +89 -0
  135. data/lib/aws/core/http/net_http_handler.rb +144 -0
  136. data/lib/aws/core/http/patch.rb +102 -0
  137. data/lib/aws/core/http/request.rb +259 -0
  138. data/lib/aws/core/http/response.rb +81 -0
  139. data/lib/aws/core/indifferent_hash.rb +88 -0
  140. data/lib/aws/core/inflection.rb +56 -0
  141. data/lib/aws/core/ini_parser.rb +42 -0
  142. data/lib/aws/core/json_client.rb +47 -0
  143. data/lib/aws/core/json_parser.rb +76 -0
  144. data/lib/aws/core/json_request_builder.rb +35 -0
  145. data/lib/aws/core/json_response_parser.rb +79 -0
  146. data/lib/aws/core/lazy_error_classes.rb +108 -0
  147. data/lib/aws/core/log_formatter.rb +428 -0
  148. data/lib/aws/core/managed_file.rb +32 -0
  149. data/lib/aws/core/meta_utils.rb +45 -0
  150. data/lib/aws/core/model.rb +62 -0
  151. data/lib/aws/core/naming.rb +30 -0
  152. data/lib/aws/core/option_grammar.rb +738 -0
  153. data/lib/aws/core/options/json_serializer.rb +82 -0
  154. data/lib/aws/core/options/validator.rb +155 -0
  155. data/lib/aws/core/options/xml_serializer.rb +118 -0
  156. data/lib/aws/core/page_result.rb +75 -0
  157. data/lib/aws/core/policy.rb +941 -0
  158. data/lib/aws/core/query_client.rb +41 -0
  159. data/lib/aws/core/query_error_parser.rb +24 -0
  160. data/lib/aws/core/query_request_builder.rb +47 -0
  161. data/lib/aws/core/query_response_parser.rb +35 -0
  162. data/lib/aws/core/region.rb +85 -0
  163. data/lib/aws/core/region_collection.rb +80 -0
  164. data/lib/aws/core/resource.rb +413 -0
  165. data/lib/aws/core/resource_cache.rb +40 -0
  166. data/lib/aws/core/response.rb +215 -0
  167. data/lib/aws/core/response_cache.rb +50 -0
  168. data/lib/aws/core/rest_error_parser.rb +24 -0
  169. data/lib/aws/core/rest_json_client.rb +40 -0
  170. data/lib/aws/core/rest_request_builder.rb +154 -0
  171. data/lib/aws/core/rest_response_parser.rb +66 -0
  172. data/lib/aws/core/rest_xml_client.rb +47 -0
  173. data/lib/aws/core/service_interface.rb +83 -0
  174. data/lib/aws/core/signers/base.rb +46 -0
  175. data/lib/aws/core/signers/cloud_front.rb +56 -0
  176. data/lib/aws/core/signers/s3.rb +159 -0
  177. data/lib/aws/core/signers/version_2.rb +72 -0
  178. data/lib/aws/core/signers/version_3.rb +86 -0
  179. data/lib/aws/core/signers/version_3_https.rb +61 -0
  180. data/lib/aws/core/signers/version_4.rb +228 -0
  181. data/lib/aws/core/signers/version_4/chunk_signed_stream.rb +191 -0
  182. data/lib/aws/core/uri_escape.rb +44 -0
  183. data/lib/aws/core/xml/frame.rb +245 -0
  184. data/lib/aws/core/xml/frame_stack.rb +85 -0
  185. data/lib/aws/core/xml/grammar.rb +307 -0
  186. data/lib/aws/core/xml/parser.rb +70 -0
  187. data/lib/aws/core/xml/root_frame.rb +65 -0
  188. data/lib/aws/core/xml/sax_handlers/libxml.rb +47 -0
  189. data/lib/aws/core/xml/sax_handlers/nokogiri.rb +56 -0
  190. data/lib/aws/core/xml/sax_handlers/ox.rb +41 -0
  191. data/lib/aws/core/xml/sax_handlers/rexml.rb +47 -0
  192. data/lib/aws/core/xml/stub.rb +123 -0
  193. data/lib/aws/data_pipeline.rb +72 -0
  194. data/lib/aws/data_pipeline/client.rb +36 -0
  195. data/lib/aws/data_pipeline/config.rb +18 -0
  196. data/lib/aws/data_pipeline/errors.rb +20 -0
  197. data/lib/aws/direct_connect.rb +73 -0
  198. data/lib/aws/direct_connect/client.rb +36 -0
  199. data/lib/aws/direct_connect/config.rb +18 -0
  200. data/lib/aws/direct_connect/errors.rb +22 -0
  201. data/lib/aws/dynamo_db.rb +230 -0
  202. data/lib/aws/dynamo_db/attribute_collection.rb +456 -0
  203. data/lib/aws/dynamo_db/batch_get.rb +213 -0
  204. data/lib/aws/dynamo_db/batch_write.rb +254 -0
  205. data/lib/aws/dynamo_db/binary.rb +35 -0
  206. data/lib/aws/dynamo_db/client.rb +129 -0
  207. data/lib/aws/dynamo_db/client/v20111205.rb +1266 -0
  208. data/lib/aws/dynamo_db/client/v20120810.rb +1409 -0
  209. data/lib/aws/dynamo_db/client_v2.rb +44 -0
  210. data/lib/aws/dynamo_db/config.rb +24 -0
  211. data/lib/aws/dynamo_db/errors.rb +20 -0
  212. data/lib/aws/dynamo_db/expectations.rb +40 -0
  213. data/lib/aws/dynamo_db/item.rb +133 -0
  214. data/lib/aws/dynamo_db/item_collection.rb +856 -0
  215. data/lib/aws/dynamo_db/item_data.rb +31 -0
  216. data/lib/aws/dynamo_db/keys.rb +41 -0
  217. data/lib/aws/dynamo_db/primary_key_element.rb +48 -0
  218. data/lib/aws/dynamo_db/resource.rb +33 -0
  219. data/lib/aws/dynamo_db/table.rb +492 -0
  220. data/lib/aws/dynamo_db/table_collection.rb +165 -0
  221. data/lib/aws/dynamo_db/types.rb +111 -0
  222. data/lib/aws/ec2.rb +428 -0
  223. data/lib/aws/ec2/attachment.rb +135 -0
  224. data/lib/aws/ec2/attachment_collection.rb +54 -0
  225. data/lib/aws/ec2/availability_zone.rb +86 -0
  226. data/lib/aws/ec2/availability_zone_collection.rb +43 -0
  227. data/lib/aws/ec2/block_device_mappings.rb +53 -0
  228. data/lib/aws/ec2/client.rb +154 -0
  229. data/lib/aws/ec2/collection.rb +36 -0
  230. data/lib/aws/ec2/config.rb +21 -0
  231. data/lib/aws/ec2/customer_gateway.rb +90 -0
  232. data/lib/aws/ec2/customer_gateway_collection.rb +73 -0
  233. data/lib/aws/ec2/dhcp_options.rb +106 -0
  234. data/lib/aws/ec2/dhcp_options_collection.rb +87 -0
  235. data/lib/aws/ec2/elastic_ip.rb +209 -0
  236. data/lib/aws/ec2/elastic_ip_collection.rb +93 -0
  237. data/lib/aws/ec2/errors.rb +32 -0
  238. data/lib/aws/ec2/export_task.rb +120 -0
  239. data/lib/aws/ec2/export_task_collection.rb +67 -0
  240. data/lib/aws/ec2/filtered_collection.rb +87 -0
  241. data/lib/aws/ec2/has_permissions.rb +44 -0
  242. data/lib/aws/ec2/image.rb +270 -0
  243. data/lib/aws/ec2/image_collection.rb +219 -0
  244. data/lib/aws/ec2/instance.rb +803 -0
  245. data/lib/aws/ec2/instance_collection.rb +402 -0
  246. data/lib/aws/ec2/internet_gateway.rb +122 -0
  247. data/lib/aws/ec2/internet_gateway/attachment.rb +78 -0
  248. data/lib/aws/ec2/internet_gateway_collection.rb +54 -0
  249. data/lib/aws/ec2/key_pair.rb +82 -0
  250. data/lib/aws/ec2/key_pair_collection.rb +99 -0
  251. data/lib/aws/ec2/network_acl.rb +256 -0
  252. data/lib/aws/ec2/network_acl/association.rb +56 -0
  253. data/lib/aws/ec2/network_acl/entry.rb +147 -0
  254. data/lib/aws/ec2/network_acl_collection.rb +64 -0
  255. data/lib/aws/ec2/network_interface.rb +237 -0
  256. data/lib/aws/ec2/network_interface/attachment.rb +100 -0
  257. data/lib/aws/ec2/network_interface_collection.rb +103 -0
  258. data/lib/aws/ec2/permission_collection.rb +174 -0
  259. data/lib/aws/ec2/region.rb +106 -0
  260. data/lib/aws/ec2/region_collection.rb +51 -0
  261. data/lib/aws/ec2/reserved_instances.rb +57 -0
  262. data/lib/aws/ec2/reserved_instances_collection.rb +40 -0
  263. data/lib/aws/ec2/reserved_instances_offering.rb +60 -0
  264. data/lib/aws/ec2/reserved_instances_offering_collection.rb +45 -0
  265. data/lib/aws/ec2/resource.rb +161 -0
  266. data/lib/aws/ec2/resource_tag_collection.rb +211 -0
  267. data/lib/aws/ec2/route_table.rb +205 -0
  268. data/lib/aws/ec2/route_table/association.rb +119 -0
  269. data/lib/aws/ec2/route_table/route.rb +119 -0
  270. data/lib/aws/ec2/route_table_collection.rb +72 -0
  271. data/lib/aws/ec2/security_group.rb +482 -0
  272. data/lib/aws/ec2/security_group/ip_permission.rb +135 -0
  273. data/lib/aws/ec2/security_group/ip_permission_collection.rb +82 -0
  274. data/lib/aws/ec2/security_group_collection.rb +133 -0
  275. data/lib/aws/ec2/snapshot.rb +143 -0
  276. data/lib/aws/ec2/snapshot_collection.rb +131 -0
  277. data/lib/aws/ec2/subnet.rb +161 -0
  278. data/lib/aws/ec2/subnet_collection.rb +119 -0
  279. data/lib/aws/ec2/tag.rb +81 -0
  280. data/lib/aws/ec2/tag_collection.rb +107 -0
  281. data/lib/aws/ec2/tagged_collection.rb +67 -0
  282. data/lib/aws/ec2/tagged_item.rb +85 -0
  283. data/lib/aws/ec2/volume.rb +185 -0
  284. data/lib/aws/ec2/volume_collection.rb +102 -0
  285. data/lib/aws/ec2/vpc.rb +174 -0
  286. data/lib/aws/ec2/vpc_collection.rb +70 -0
  287. data/lib/aws/ec2/vpn_connection.rb +99 -0
  288. data/lib/aws/ec2/vpn_connection/telemetry.rb +49 -0
  289. data/lib/aws/ec2/vpn_connection_collection.rb +96 -0
  290. data/lib/aws/ec2/vpn_gateway.rb +123 -0
  291. data/lib/aws/ec2/vpn_gateway/attachment.rb +45 -0
  292. data/lib/aws/ec2/vpn_gateway_collection.rb +77 -0
  293. data/lib/aws/elastic_beanstalk.rb +49 -0
  294. data/lib/aws/elastic_beanstalk/client.rb +36 -0
  295. data/lib/aws/elastic_beanstalk/config.rb +18 -0
  296. data/lib/aws/elastic_beanstalk/errors.rb +22 -0
  297. data/lib/aws/elastic_transcoder.rb +29 -0
  298. data/lib/aws/elastic_transcoder/client.rb +48 -0
  299. data/lib/aws/elastic_transcoder/config.rb +18 -0
  300. data/lib/aws/elastic_transcoder/errors.rb +23 -0
  301. data/lib/aws/elasticache.rb +49 -0
  302. data/lib/aws/elasticache/client.rb +41 -0
  303. data/lib/aws/elasticache/config.rb +18 -0
  304. data/lib/aws/elasticache/errors.rb +22 -0
  305. data/lib/aws/elb.rb +66 -0
  306. data/lib/aws/elb/availability_zone_collection.rb +138 -0
  307. data/lib/aws/elb/backend_server_policy_collection.rb +139 -0
  308. data/lib/aws/elb/client.rb +35 -0
  309. data/lib/aws/elb/config.rb +18 -0
  310. data/lib/aws/elb/errors.rb +26 -0
  311. data/lib/aws/elb/instance_collection.rb +168 -0
  312. data/lib/aws/elb/listener.rb +190 -0
  313. data/lib/aws/elb/listener_collection.rb +113 -0
  314. data/lib/aws/elb/listener_opts.rb +45 -0
  315. data/lib/aws/elb/load_balancer.rb +280 -0
  316. data/lib/aws/elb/load_balancer_collection.rb +146 -0
  317. data/lib/aws/elb/load_balancer_policy.rb +93 -0
  318. data/lib/aws/elb/load_balancer_policy_collection.rb +208 -0
  319. data/lib/aws/emr.rb +87 -0
  320. data/lib/aws/emr/client.rb +35 -0
  321. data/lib/aws/emr/config.rb +18 -0
  322. data/lib/aws/emr/errors.rb +22 -0
  323. data/lib/aws/emr/instance_group.rb +138 -0
  324. data/lib/aws/emr/instance_group_collection.rb +82 -0
  325. data/lib/aws/emr/job_flow.rb +307 -0
  326. data/lib/aws/emr/job_flow_collection.rb +183 -0
  327. data/lib/aws/errors.rb +162 -0
  328. data/lib/aws/glacier.rb +79 -0
  329. data/lib/aws/glacier/archive.rb +56 -0
  330. data/lib/aws/glacier/archive_collection.rb +146 -0
  331. data/lib/aws/glacier/client.rb +49 -0
  332. data/lib/aws/glacier/config.rb +19 -0
  333. data/lib/aws/glacier/errors.rb +22 -0
  334. data/lib/aws/glacier/resource.rb +30 -0
  335. data/lib/aws/glacier/vault.rb +145 -0
  336. data/lib/aws/glacier/vault_collection.rb +75 -0
  337. data/lib/aws/glacier/vault_notification_configuration.rb +29 -0
  338. data/lib/aws/iam.rb +408 -0
  339. data/lib/aws/iam/access_key.rb +185 -0
  340. data/lib/aws/iam/access_key_collection.rb +128 -0
  341. data/lib/aws/iam/account_alias_collection.rb +79 -0
  342. data/lib/aws/iam/client.rb +49 -0
  343. data/lib/aws/iam/collection.rb +83 -0
  344. data/lib/aws/iam/config.rb +18 -0
  345. data/lib/aws/iam/errors.rb +22 -0
  346. data/lib/aws/iam/group.rb +111 -0
  347. data/lib/aws/iam/group_collection.rb +132 -0
  348. data/lib/aws/iam/group_policy_collection.rb +47 -0
  349. data/lib/aws/iam/group_user_collection.rb +84 -0
  350. data/lib/aws/iam/login_profile.rb +111 -0
  351. data/lib/aws/iam/mfa_device.rb +52 -0
  352. data/lib/aws/iam/mfa_device_collection.rb +127 -0
  353. data/lib/aws/iam/policy.rb +46 -0
  354. data/lib/aws/iam/policy_collection.rb +188 -0
  355. data/lib/aws/iam/resource.rb +62 -0
  356. data/lib/aws/iam/server_certificate.rb +148 -0
  357. data/lib/aws/iam/server_certificate_collection.rb +138 -0
  358. data/lib/aws/iam/signing_certificate.rb +186 -0
  359. data/lib/aws/iam/signing_certificate_collection.rb +131 -0
  360. data/lib/aws/iam/user.rb +200 -0
  361. data/lib/aws/iam/user_collection.rb +133 -0
  362. data/lib/aws/iam/user_group_collection.rb +98 -0
  363. data/lib/aws/iam/user_policy.rb +90 -0
  364. data/lib/aws/iam/user_policy_collection.rb +45 -0
  365. data/lib/aws/iam/virtual_mfa_device.rb +139 -0
  366. data/lib/aws/iam/virtual_mfa_device_collection.rb +73 -0
  367. data/lib/aws/import_export.rb +73 -0
  368. data/lib/aws/import_export/client.rb +35 -0
  369. data/lib/aws/import_export/config.rb +19 -0
  370. data/lib/aws/import_export/errors.rb +22 -0
  371. data/lib/aws/kinesis.rb +53 -0
  372. data/lib/aws/kinesis/client.rb +35 -0
  373. data/lib/aws/kinesis/config.rb +18 -0
  374. data/lib/aws/kinesis/errors.rb +20 -0
  375. data/lib/aws/ops_works.rb +29 -0
  376. data/lib/aws/ops_works/client.rb +35 -0
  377. data/lib/aws/ops_works/config.rb +18 -0
  378. data/lib/aws/ops_works/errors.rb +20 -0
  379. data/lib/aws/rails.rb +195 -0
  380. data/lib/aws/rds.rb +70 -0
  381. data/lib/aws/rds/client.rb +42 -0
  382. data/lib/aws/rds/config.rb +18 -0
  383. data/lib/aws/rds/db_instance.rb +215 -0
  384. data/lib/aws/rds/db_instance_collection.rb +75 -0
  385. data/lib/aws/rds/db_snapshot.rb +163 -0
  386. data/lib/aws/rds/db_snapshot_collection.rb +89 -0
  387. data/lib/aws/rds/errors.rb +22 -0
  388. data/lib/aws/record.rb +139 -0
  389. data/lib/aws/record/abstract_base.rb +689 -0
  390. data/lib/aws/record/attributes.rb +388 -0
  391. data/lib/aws/record/conversion.rb +38 -0
  392. data/lib/aws/record/dirty_tracking.rb +287 -0
  393. data/lib/aws/record/errors.rb +143 -0
  394. data/lib/aws/record/exceptions.rb +51 -0
  395. data/lib/aws/record/hash_model.rb +204 -0
  396. data/lib/aws/record/hash_model/attributes.rb +195 -0
  397. data/lib/aws/record/hash_model/finder_methods.rb +172 -0
  398. data/lib/aws/record/hash_model/scope.rb +108 -0
  399. data/lib/aws/record/model.rb +453 -0
  400. data/lib/aws/record/model/attributes.rb +377 -0
  401. data/lib/aws/record/model/finder_methods.rb +232 -0
  402. data/lib/aws/record/model/scope.rb +212 -0
  403. data/lib/aws/record/naming.rb +31 -0
  404. data/lib/aws/record/scope.rb +203 -0
  405. data/lib/aws/record/validations.rb +694 -0
  406. data/lib/aws/record/validator.rb +246 -0
  407. data/lib/aws/record/validators/acceptance.rb +49 -0
  408. data/lib/aws/record/validators/block.rb +36 -0
  409. data/lib/aws/record/validators/confirmation.rb +41 -0
  410. data/lib/aws/record/validators/count.rb +106 -0
  411. data/lib/aws/record/validators/exclusion.rb +41 -0
  412. data/lib/aws/record/validators/format.rb +55 -0
  413. data/lib/aws/record/validators/inclusion.rb +54 -0
  414. data/lib/aws/record/validators/length.rb +105 -0
  415. data/lib/aws/record/validators/method.rb +31 -0
  416. data/lib/aws/record/validators/numericality.rb +136 -0
  417. data/lib/aws/record/validators/presence.rb +43 -0
  418. data/lib/aws/redshift.rb +51 -0
  419. data/lib/aws/redshift/client.rb +35 -0
  420. data/lib/aws/redshift/config.rb +18 -0
  421. data/lib/aws/redshift/errors.rb +22 -0
  422. data/lib/aws/route_53.rb +86 -0
  423. data/lib/aws/route_53/change_batch.rb +161 -0
  424. data/lib/aws/route_53/change_info.rb +72 -0
  425. data/lib/aws/route_53/client.rb +38 -0
  426. data/lib/aws/route_53/config.rb +18 -0
  427. data/lib/aws/route_53/errors.rb +22 -0
  428. data/lib/aws/route_53/hosted_zone.rb +134 -0
  429. data/lib/aws/route_53/hosted_zone_collection.rb +101 -0
  430. data/lib/aws/route_53/resource_record_set.rb +251 -0
  431. data/lib/aws/route_53/resource_record_set_collection.rb +110 -0
  432. data/lib/aws/s3.rb +156 -0
  433. data/lib/aws/s3/access_control_list.rb +265 -0
  434. data/lib/aws/s3/acl_object.rb +264 -0
  435. data/lib/aws/s3/acl_options.rb +204 -0
  436. data/lib/aws/s3/bucket.rb +742 -0
  437. data/lib/aws/s3/bucket_collection.rb +162 -0
  438. data/lib/aws/s3/bucket_lifecycle_configuration.rb +473 -0
  439. data/lib/aws/s3/bucket_tag_collection.rb +111 -0
  440. data/lib/aws/s3/bucket_version_collection.rb +79 -0
  441. data/lib/aws/s3/cipher_io.rb +120 -0
  442. data/lib/aws/s3/client.rb +2067 -0
  443. data/lib/aws/s3/client/xml.rb +266 -0
  444. data/lib/aws/s3/config.rb +48 -0
  445. data/lib/aws/s3/cors_rule.rb +108 -0
  446. data/lib/aws/s3/cors_rule_collection.rb +194 -0
  447. data/lib/aws/s3/data_options.rb +191 -0
  448. data/lib/aws/s3/encryption_utils.rb +146 -0
  449. data/lib/aws/s3/errors.rb +94 -0
  450. data/lib/aws/s3/multipart_upload.rb +353 -0
  451. data/lib/aws/s3/multipart_upload_collection.rb +76 -0
  452. data/lib/aws/s3/object_collection.rb +353 -0
  453. data/lib/aws/s3/object_metadata.rb +103 -0
  454. data/lib/aws/s3/object_upload_collection.rb +77 -0
  455. data/lib/aws/s3/object_version.rb +154 -0
  456. data/lib/aws/s3/object_version_collection.rb +89 -0
  457. data/lib/aws/s3/paginated_collection.rb +75 -0
  458. data/lib/aws/s3/policy.rb +74 -0
  459. data/lib/aws/s3/prefix_and_delimiter_collection.rb +47 -0
  460. data/lib/aws/s3/prefixed_collection.rb +85 -0
  461. data/lib/aws/s3/presign_v4.rb +136 -0
  462. data/lib/aws/s3/presigned_post.rb +554 -0
  463. data/lib/aws/s3/request.rb +62 -0
  464. data/lib/aws/s3/s3_object.rb +1784 -0
  465. data/lib/aws/s3/tree.rb +116 -0
  466. data/lib/aws/s3/tree/branch_node.rb +68 -0
  467. data/lib/aws/s3/tree/child_collection.rb +104 -0
  468. data/lib/aws/s3/tree/leaf_node.rb +94 -0
  469. data/lib/aws/s3/tree/node.rb +22 -0
  470. data/lib/aws/s3/tree/parent.rb +87 -0
  471. data/lib/aws/s3/uploaded_part.rb +82 -0
  472. data/lib/aws/s3/uploaded_part_collection.rb +84 -0
  473. data/lib/aws/s3/website_configuration.rb +102 -0
  474. data/lib/aws/simple_db.rb +218 -0
  475. data/lib/aws/simple_db/attribute.rb +156 -0
  476. data/lib/aws/simple_db/attribute_collection.rb +240 -0
  477. data/lib/aws/simple_db/client.rb +67 -0
  478. data/lib/aws/simple_db/config.rb +20 -0
  479. data/lib/aws/simple_db/consistent_read_option.rb +42 -0
  480. data/lib/aws/simple_db/delete_attributes.rb +62 -0
  481. data/lib/aws/simple_db/domain.rb +123 -0
  482. data/lib/aws/simple_db/domain_collection.rb +86 -0
  483. data/lib/aws/simple_db/domain_metadata.rb +110 -0
  484. data/lib/aws/simple_db/errors.rb +55 -0
  485. data/lib/aws/simple_db/expect_condition_option.rb +45 -0
  486. data/lib/aws/simple_db/item.rb +93 -0
  487. data/lib/aws/simple_db/item_collection.rb +654 -0
  488. data/lib/aws/simple_db/item_data.rb +73 -0
  489. data/lib/aws/simple_db/put_attributes.rb +60 -0
  490. data/lib/aws/simple_email_service.rb +443 -0
  491. data/lib/aws/simple_email_service/client.rb +37 -0
  492. data/lib/aws/simple_email_service/config.rb +18 -0
  493. data/lib/aws/simple_email_service/email_address_collection.rb +69 -0
  494. data/lib/aws/simple_email_service/errors.rb +22 -0
  495. data/lib/aws/simple_email_service/identity.rb +230 -0
  496. data/lib/aws/simple_email_service/identity_collection.rb +81 -0
  497. data/lib/aws/simple_email_service/quotas.rb +66 -0
  498. data/lib/aws/simple_workflow.rb +227 -0
  499. data/lib/aws/simple_workflow/activity_task.rb +178 -0
  500. data/lib/aws/simple_workflow/activity_task_collection.rb +123 -0
  501. data/lib/aws/simple_workflow/activity_type.rb +131 -0
  502. data/lib/aws/simple_workflow/activity_type_collection.rb +93 -0
  503. data/lib/aws/simple_workflow/client.rb +69 -0
  504. data/lib/aws/simple_workflow/config.rb +18 -0
  505. data/lib/aws/simple_workflow/count.rb +49 -0
  506. data/lib/aws/simple_workflow/decision_task.rb +603 -0
  507. data/lib/aws/simple_workflow/decision_task_collection.rb +223 -0
  508. data/lib/aws/simple_workflow/domain.rb +122 -0
  509. data/lib/aws/simple_workflow/domain_collection.rb +169 -0
  510. data/lib/aws/simple_workflow/errors.rb +20 -0
  511. data/lib/aws/simple_workflow/history_event.rb +276 -0
  512. data/lib/aws/simple_workflow/history_event_collection.rb +76 -0
  513. data/lib/aws/simple_workflow/option_formatters.rb +82 -0
  514. data/lib/aws/simple_workflow/resource.rb +94 -0
  515. data/lib/aws/simple_workflow/type.rb +89 -0
  516. data/lib/aws/simple_workflow/type_collection.rb +140 -0
  517. data/lib/aws/simple_workflow/workflow_execution.rb +384 -0
  518. data/lib/aws/simple_workflow/workflow_execution_collection.rb +617 -0
  519. data/lib/aws/simple_workflow/workflow_type.rb +177 -0
  520. data/lib/aws/simple_workflow/workflow_type_collection.rb +91 -0
  521. data/lib/aws/sns.rb +76 -0
  522. data/lib/aws/sns/client.rb +35 -0
  523. data/lib/aws/sns/config.rb +18 -0
  524. data/lib/aws/sns/errors.rb +22 -0
  525. data/lib/aws/sns/has_delivery_policy.rb +68 -0
  526. data/lib/aws/sns/message.rb +204 -0
  527. data/lib/aws/sns/originators/from_auto_scaling.rb +68 -0
  528. data/lib/aws/sns/policy.rb +47 -0
  529. data/lib/aws/sns/subscription.rb +165 -0
  530. data/lib/aws/sns/subscription_collection.rb +78 -0
  531. data/lib/aws/sns/topic.rb +403 -0
  532. data/lib/aws/sns/topic_collection.rb +62 -0
  533. data/lib/aws/sns/topic_subscription_collection.rb +54 -0
  534. data/lib/aws/sqs.rb +80 -0
  535. data/lib/aws/sqs/client.rb +53 -0
  536. data/lib/aws/sqs/config.rb +20 -0
  537. data/lib/aws/sqs/errors.rb +125 -0
  538. data/lib/aws/sqs/policy.rb +48 -0
  539. data/lib/aws/sqs/queue.rb +856 -0
  540. data/lib/aws/sqs/queue_collection.rb +186 -0
  541. data/lib/aws/sqs/received_message.rb +190 -0
  542. data/lib/aws/sqs/received_sns_message.rb +116 -0
  543. data/lib/aws/storage_gateway.rb +72 -0
  544. data/lib/aws/storage_gateway/client.rb +42 -0
  545. data/lib/aws/storage_gateway/config.rb +18 -0
  546. data/lib/aws/storage_gateway/errors.rb +22 -0
  547. data/lib/aws/sts.rb +164 -0
  548. data/lib/aws/sts/client.rb +55 -0
  549. data/lib/aws/sts/config.rb +18 -0
  550. data/lib/aws/sts/errors.rb +22 -0
  551. data/lib/aws/sts/federated_session.rb +56 -0
  552. data/lib/aws/sts/policy.rb +30 -0
  553. data/lib/aws/sts/session.rb +48 -0
  554. data/lib/aws/support.rb +29 -0
  555. data/lib/aws/support/client.rb +35 -0
  556. data/lib/aws/support/config.rb +18 -0
  557. data/lib/aws/support/errors.rb +20 -0
  558. data/lib/aws/version.rb +17 -0
  559. data/rails/init.rb +15 -0
  560. metadata +634 -0
@@ -0,0 +1,62 @@
1
+ # Copyright 2011-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"). You
4
+ # may not use this file except in compliance with the License. A copy of
5
+ # the License is located at
6
+ #
7
+ # http://aws.amazon.com/apache2.0/
8
+ #
9
+ # or in the "license" file accompanying this file. This file is
10
+ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11
+ # ANY KIND, either express or implied. See the License for the specific
12
+ # language governing permissions and limitations under the License.
13
+
14
+ require 'uri'
15
+ require 'time'
16
+
17
+ module AWS
18
+ class S3
19
+
20
+ # @api private
21
+ class Request < Core::Http::Request
22
+
23
+ include Core::UriEscape
24
+
25
+ # @return [bucket] S3 bucket name
26
+ attr_accessor :bucket
27
+
28
+ # @return [String] S3 object key
29
+ attr_accessor :key
30
+
31
+ # @api private
32
+ attr_accessor :force_path_style
33
+
34
+ def host
35
+ path_style? ? @host : "#{bucket}.#{@host}"
36
+ end
37
+
38
+ def path_style?
39
+ if force_path_style
40
+ true
41
+ else
42
+ Client.path_style_bucket_name?(bucket)
43
+ end
44
+ end
45
+
46
+ def uri
47
+ parts = []
48
+ parts << bucket if bucket and path_style?
49
+ parts << escape_path(key) if key
50
+
51
+ path = '/' + parts.join('/')
52
+ querystring = url_encoded_params
53
+
54
+ uri = ''
55
+ uri << path
56
+ uri << "?#{querystring}" if querystring
57
+ uri
58
+ end
59
+
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,1784 @@
1
+ # Copyright 2011-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"). You
4
+ # may not use this file except in compliance with the License. A copy of
5
+ # the License is located at
6
+ #
7
+ # http://aws.amazon.com/apache2.0/
8
+ #
9
+ # or in the "license" file accompanying this file. This file is
10
+ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11
+ # ANY KIND, either express or implied. See the License for the specific
12
+ # language governing permissions and limitations under the License.
13
+
14
+ require 'uri'
15
+ require 'base64'
16
+
17
+ module AWS
18
+ class S3
19
+
20
+ # Represents an object in S3. Objects live in a bucket and have
21
+ # unique keys.
22
+ #
23
+ # # Getting Objects
24
+ #
25
+ # You can get an object by its key.
26
+ #
27
+ # s3 = AWS::S3.new
28
+ # obj = s3.buckets['my-bucket'].objects['key'] # no request made
29
+ #
30
+ # You can also get objects by enumerating a objects in a bucket.
31
+ #
32
+ # bucket.objects.each do |obj|
33
+ # puts obj.key
34
+ # end
35
+ #
36
+ # See {ObjectCollection} for more information on finding objects.
37
+ #
38
+ # # Creating Objects
39
+ #
40
+ # You create an object by writing to it. The following two
41
+ # expressions are equivalent.
42
+ #
43
+ # obj = bucket.objects.create('key', 'data')
44
+ # obj = bucket.objects['key'].write('data')
45
+ #
46
+ # # Writing Objects
47
+ #
48
+ # To upload data to S3, you simply need to call {#write} on an object.
49
+ #
50
+ # obj.write('Hello World!')
51
+ # obj.read
52
+ # #=> 'Hello World!'
53
+ #
54
+ # ## Uploading Files
55
+ #
56
+ # You can upload a file to S3 in a variety of ways. Given a path
57
+ # to a file (as a string) you can do any of the following:
58
+ #
59
+ # # specify the data as a path to a file
60
+ # obj.write(Pathname.new(path_to_file))
61
+ #
62
+ # # also works this way
63
+ # obj.write(:file => path_to_file)
64
+ #
65
+ # # Also accepts an open file object
66
+ # file = File.open(path_to_file, 'rb')
67
+ # obj.write(file)
68
+ #
69
+ # All three examples above produce the same result. The file
70
+ # will be streamed to S3 in chunks. It will not be loaded
71
+ # entirely into memory.
72
+ #
73
+ # ## Streaming Uploads
74
+ #
75
+ # When you call {#write} with an IO-like object, it will be streamed
76
+ # to S3 in chunks.
77
+ #
78
+ # While it is possible to determine the size of many IO objects, you may
79
+ # have to specify the :content_length of your IO object.
80
+ # If the exact size can not be known, you may provide an
81
+ # `:estimated_content_length`. Depending on the size (actual or
82
+ # estimated) of your data, it will be uploaded in a single request or
83
+ # in multiple requests via {#multipart_upload}.
84
+ #
85
+ # You may also stream uploads to S3 using a block:
86
+ #
87
+ # obj.write do |buffer, bytes|
88
+ # # writing fewer than the requested number of bytes to the buffer
89
+ # # will cause write to stop yielding to the block
90
+ # end
91
+ #
92
+ # # Reading Objects
93
+ #
94
+ # You can read an object directly using {#read}. Be warned, this will
95
+ # load the entire object into memory and is not recommended for large
96
+ # objects.
97
+ #
98
+ # obj.write('abc')
99
+ # puts obj.read
100
+ # #=> abc
101
+ #
102
+ # ## Streaming Downloads
103
+ #
104
+ # If you want to stream an object from S3, you can pass a block
105
+ # to {#read}.
106
+ #
107
+ # File.open('output', 'wb') do |file|
108
+ # large_object.read do |chunk|
109
+ # file.write(chunk)
110
+ # end
111
+ # end
112
+ #
113
+ # # Encryption
114
+ #
115
+ # Amazon S3 can encrypt objects for you service-side. You can also
116
+ # use client-side encryption.
117
+ #
118
+ # ## Server Side Encryption
119
+ #
120
+ # You can specify to use server side encryption when writing an object.
121
+ #
122
+ # obj.write('data', :server_side_encryption => :aes256)
123
+ #
124
+ # You can also make this the default behavior.
125
+ #
126
+ # AWS.config(:s3_server_side_encryption => :aes256)
127
+ #
128
+ # s3 = AWS::S3.new
129
+ # s3.buckets['name'].objects['key'].write('abc') # will be encrypted
130
+ #
131
+ # ## Client Side Encryption
132
+ #
133
+ # Client side encryption utilizes envelope encryption, so that your keys are
134
+ # never sent to S3. You can use a symetric key or an asymmetric
135
+ # key pair.
136
+ #
137
+ # ### Symmetric Key Encryption
138
+ #
139
+ # An AES key is used for symmetric encryption. The key can be 128, 192,
140
+ # and 256 bit sizes. Start by generating key or read a previously
141
+ # generated key.
142
+ #
143
+ # # generate a new random key
144
+ # my_key = OpenSSL::Cipher.new("AES-256-ECB").random_key
145
+ #
146
+ # # read an existing key from disk
147
+ # my_key = File.read("my_key.der")
148
+ #
149
+ # Now you can encrypt locally and upload the encrypted data to S3.
150
+ # To do this, you need to provide your key.
151
+ #
152
+ # obj = bucket.objects["my-text-object"]
153
+ #
154
+ # # encrypt then upload data
155
+ # obj.write("MY TEXT", :encryption_key => my_key)
156
+ #
157
+ # # try read the object without decrypting, oops
158
+ # obj.read
159
+ # #=> '.....'
160
+ #
161
+ # Lastly, you can download and decrypt by providing the same key.
162
+ #
163
+ # obj.read(:encryption_key => my_key)
164
+ # #=> "MY TEXT"
165
+ #
166
+ # ### Asymmetric Key Pair
167
+ #
168
+ # A RSA key pair is used for asymmetric encryption. The public key is used
169
+ # for encryption and the private key is used for decryption. Start
170
+ # by generating a key.
171
+ #
172
+ # my_key = OpenSSL::PKey::RSA.new(1024)
173
+ #
174
+ # Provide your key to #write and the data will be encrypted before it
175
+ # is uploaded. Pass the same key to #read to decrypt the data
176
+ # when you download it.
177
+ #
178
+ # obj = bucket.objects["my-text-object"]
179
+ #
180
+ # # encrypt and upload the data
181
+ # obj.write("MY TEXT", :encryption_key => my_key)
182
+ #
183
+ # # download and decrypt the data
184
+ # obj.read(:encryption_key => my_key)
185
+ # #=> "MY TEXT"
186
+ #
187
+ # ### Configuring storage locations
188
+ #
189
+ # By default, encryption materials are stored in the object metadata.
190
+ # If you prefer, you can store the encryption materials in a separate
191
+ # object in S3. This object will have the same key + '.instruction'.
192
+ #
193
+ # # new object, does not exist yet
194
+ # obj = bucket.objects["my-text-object"]
195
+ #
196
+ # # no instruction file present
197
+ # bucket.objects['my-text-object.instruction'].exists?
198
+ # #=> false
199
+ #
200
+ # # store the encryption materials in the instruction file
201
+ # # instead of obj#metadata
202
+ # obj.write("MY TEXT",
203
+ # :encryption_key => MY_KEY,
204
+ # :encryption_materials_location => :instruction_file)
205
+ #
206
+ # bucket.objects['my-text-object.instruction'].exists?
207
+ # #=> true
208
+ #
209
+ # If you store the encryption materials in an instruction file, you
210
+ # must tell #read this or it will fail to find your encryption materials.
211
+ #
212
+ # # reading an encrypted file whos materials are stored in an
213
+ # # instruction file, and not metadata
214
+ # obj.read(:encryption_key => MY_KEY,
215
+ # :encryption_materials_location => :instruction_file)
216
+ #
217
+ # ### Configuring default behaviors
218
+ #
219
+ # You can configure the default key such that it will automatically
220
+ # encrypt and decrypt for you. You can do this globally or for a
221
+ # single S3 interface
222
+ #
223
+ # # all objects uploaded/downloaded with this s3 object will be
224
+ # # encrypted/decrypted
225
+ # s3 = AWS::S3.new(:s3_encryption_key => "MY_KEY")
226
+ #
227
+ # # set the key to always encrypt/decrypt
228
+ # AWS.config(:s3_encryption_key => "MY_KEY")
229
+ #
230
+ # You can also configure the default storage location for the encryption
231
+ # materials.
232
+ #
233
+ # AWS.config(:s3_encryption_materials_location => :instruction_file)
234
+ #
235
+ class S3Object
236
+
237
+ include Core::Model
238
+ include DataOptions
239
+ include ACLOptions
240
+ include AWS::S3::EncryptionUtils
241
+
242
+ # @param [Bucket] bucket The bucket this object belongs to.
243
+ # @param [String] key The object's key.
244
+ def initialize(bucket, key, opts = {})
245
+ super
246
+ @key = key
247
+ @bucket = bucket
248
+ end
249
+
250
+ # @return [String] The objects unique key
251
+ attr_reader :key
252
+
253
+ # @return [Bucket] The bucket this object is in.
254
+ attr_reader :bucket
255
+
256
+ # @api private
257
+ def inspect
258
+ "<#{self.class}:#{bucket.name}/#{key}>"
259
+ end
260
+
261
+ # @return [Boolean] Returns true if the other object belongs to the
262
+ # same bucket and has the same key.
263
+ def == other
264
+ other.kind_of?(S3Object) and other.bucket == bucket and other.key == key
265
+ end
266
+ alias_method :eql?, :==
267
+
268
+ # @return [Boolean] Returns `true` if the object exists in S3.
269
+ def exists?
270
+ head
271
+ rescue Errors::NoSuchKey => e
272
+ false
273
+ else
274
+ true
275
+ end
276
+
277
+ # Performs a HEAD request against this object and returns an object
278
+ # with useful information about the object, including:
279
+ #
280
+ # * metadata (hash of user-supplied key-value pairs)
281
+ # * content_length (integer, number of bytes)
282
+ # * content_type (as sent to S3 when uploading the object)
283
+ # * etag (typically the object's MD5)
284
+ # * server_side_encryption (the algorithm used to encrypt the
285
+ # object on the server side, e.g. `:aes256`)
286
+ #
287
+ # @param [Hash] options
288
+ # @option options [String] :version_id Which version of this object
289
+ # to make a HEAD request against.
290
+ # @return A head object response with metadata,
291
+ # content_length, content_type, etag and server_side_encryption.
292
+ def head options = {}
293
+ client.head_object(options.merge(
294
+ :bucket_name => bucket.name, :key => key))
295
+ end
296
+
297
+ # Returns the object's ETag.
298
+ #
299
+ # Generally the ETAG is the MD5 of the object. If the object was
300
+ # uploaded using multipart upload then this is the MD5 all of the
301
+ # upload-part-md5s.
302
+ #
303
+ # @return [String] Returns the object's ETag
304
+ def etag
305
+ head[:etag]
306
+ end
307
+
308
+ # Returns the object's last modified time.
309
+ #
310
+ # @return [Time] Returns the object's last modified time.
311
+ def last_modified
312
+ head[:last_modified]
313
+ end
314
+
315
+ # @return [Integer] Size of the object in bytes.
316
+ def content_length
317
+ head[:content_length]
318
+ end
319
+
320
+ # @note S3 does not compute content-type. It reports the content-type
321
+ # as was reported during the file upload.
322
+ # @return [String] Returns the content type as reported by S3,
323
+ # defaults to an empty string when not provided during upload.
324
+ def content_type
325
+ head[:content_type]
326
+ end
327
+
328
+ # @return [DateTime,nil]
329
+ def expiration_date
330
+ head[:expiration_date]
331
+ end
332
+
333
+ # @return [String,nil]
334
+ def expiration_rule_id
335
+ head[:expiration_rule_id]
336
+ end
337
+
338
+ # @return [Symbol, nil] Returns the algorithm used to encrypt
339
+ # the object on the server side, or `nil` if SSE was not used
340
+ # when storing the object.
341
+ def server_side_encryption
342
+ head[:server_side_encryption]
343
+ end
344
+
345
+ # @return [true, false] Returns true if the object was stored
346
+ # using server side encryption.
347
+ def server_side_encryption?
348
+ !server_side_encryption.nil?
349
+ end
350
+
351
+ # @return [Boolean] whether a {#restore} operation on the
352
+ # object is currently being performed on the object.
353
+ # @see #restore_expiration_date
354
+ # @since 1.7.2
355
+ def restore_in_progress?
356
+ head[:restore_in_progress]
357
+ end
358
+
359
+ # @return [DateTime] the time when the temporarily restored object
360
+ # will be removed from S3. Note that the original object will remain
361
+ # available in Glacier.
362
+ # @return [nil] if the object was not restored from an archived
363
+ # copy
364
+ # @since 1.7.2
365
+ def restore_expiration_date
366
+ head[:restore_expiration_date]
367
+ end
368
+
369
+ # @return [Boolean] whether the object is a temporary copy of an
370
+ # archived object in the Glacier storage class.
371
+ # @since 1.7.2
372
+ def restored_object?
373
+ !!head[:restore_expiration_date]
374
+ end
375
+
376
+ # Deletes the object from its S3 bucket.
377
+ #
378
+ # @param [Hash] options
379
+ #
380
+ # @option [String] :version_id (nil) If present the specified version
381
+ # of this object will be deleted. Only works for buckets that have
382
+ # had versioning enabled.
383
+ #
384
+ # @option [Boolean] :delete_instruction_file (false) Set this to `true`
385
+ # if you use client-side encryption and the encryption materials
386
+ # were stored in a separate object in S3 (key.instruction).
387
+ #
388
+ # @option [String] :mfa The serial number and current token code of
389
+ # the Multi-Factor Authentication (MFA) device for the user. Format
390
+ # is "SERIAL TOKEN" - with a space between the serial and token.
391
+ #
392
+ # @return [nil]
393
+ def delete options = {}
394
+ client.delete_object(options.merge(
395
+ :bucket_name => bucket.name,
396
+ :key => key))
397
+
398
+ if options[:delete_instruction_file]
399
+ client.delete_object(
400
+ :bucket_name => bucket.name,
401
+ :key => key + '.instruction')
402
+ end
403
+
404
+ nil
405
+
406
+ end
407
+
408
+ # Restores a temporary copy of an archived object from the
409
+ # Glacier storage tier. After the specified `days`, Amazon
410
+ # S3 deletes the temporary copy. Note that the object
411
+ # remains archived; Amazon S3 deletes only the restored copy.
412
+ #
413
+ # Restoring an object does not occur immediately. Use
414
+ # {#restore_in_progress?} to check the status of the operation.
415
+ #
416
+ # @option [Integer] :days (1) the number of days to keep the object
417
+ # @return [Boolean] `true` if a restore can be initiated.
418
+ # @since 1.7.2
419
+ def restore options = {}
420
+ options[:days] ||= 1
421
+
422
+ client.restore_object(
423
+ :bucket_name => bucket.name,
424
+ :key => key, :days => options[:days])
425
+
426
+ true
427
+ end
428
+
429
+ # @option [String] :version_id (nil) If present the metadata object
430
+ # will be for the specified version.
431
+ # @return [ObjectMetadata] Returns an instance of ObjectMetadata
432
+ # representing the metadata for this object.
433
+ def metadata options = {}
434
+ options[:config] = config
435
+ ObjectMetadata.new(self, options)
436
+ end
437
+
438
+ # Returns a collection representing all the object versions
439
+ # for this object.
440
+ #
441
+ # @example
442
+ #
443
+ # bucket.versioning_enabled? # => true
444
+ # version = bucket.objects["mykey"].versions.latest
445
+ #
446
+ # @return [ObjectVersionCollection]
447
+ def versions
448
+ ObjectVersionCollection.new(self)
449
+ end
450
+
451
+ # Uploads data to the object in S3.
452
+ #
453
+ # obj = s3.buckets['bucket-name'].objects['key']
454
+ #
455
+ # # strings
456
+ # obj.write("HELLO")
457
+ #
458
+ # # files (by path)
459
+ # obj.write(Pathname.new('path/to/file.txt'))
460
+ #
461
+ # # file objects
462
+ # obj.write(File.open('path/to/file.txt', 'rb'))
463
+ #
464
+ # # IO objects (must respond to #read and #eof?)
465
+ # obj.write(io)
466
+ #
467
+ # ### Multipart Uploads vs Single Uploads
468
+ #
469
+ # This method will intelligently choose between uploading the
470
+ # file in a signal request and using {#multipart_upload}.
471
+ # You can control this behavior by configuring the thresholds
472
+ # and you can disable the multipart feature as well.
473
+ #
474
+ # # always send the file in a single request
475
+ # obj.write(file, :single_request => true)
476
+ #
477
+ # # upload the file in parts if the total file size exceeds 100MB
478
+ # obj.write(file, :multipart_threshold => 100 * 1024 * 1024)
479
+ #
480
+ # @overload write(data, options = {})
481
+ #
482
+ # @param [String,Pathname,File,IO] data The data to upload.
483
+ # This may be a:
484
+ # * String
485
+ # * Pathname
486
+ # * File
487
+ # * IO
488
+ # * Any object that responds to `#read` and `#eof?`.
489
+ #
490
+ # @param options [Hash] Additional upload options.
491
+ #
492
+ # @option options [Integer] :content_length If provided, this
493
+ # option must match the total number of bytes written to S3.
494
+ # This options is *required* when it is not possible to
495
+ # automatically determine the size of `data`.
496
+ #
497
+ # @option options [Integer] :estimated_content_length When uploading
498
+ # data of unknown content length, you may specify this option to
499
+ # hint what mode of upload should take place. When
500
+ # `:estimated_content_length` exceeds the `:multipart_threshold`,
501
+ # then the data will be uploaded in parts, otherwise it will
502
+ # be read into memory and uploaded via {Client#put_object}.
503
+ #
504
+ # @option options [Boolean] :single_request (false) When `true`,
505
+ # this method will always upload the data in a single request
506
+ # (via {Client#put_object}). When `false`, this method will
507
+ # choose between {Client#put_object} and {#multipart_upload}.
508
+ #
509
+ # @option options [Integer] :multipart_threshold (16777216) Specifies
510
+ # the maximum size (in bytes) of a single-request upload. If the
511
+ # data exceeds this threshold, it will be uploaded via
512
+ # {#multipart_upload}. The default threshold is 16MB and can
513
+ # be configured via AWS.config(:s3_multipart_threshold => ...).
514
+ #
515
+ # @option options [Integer] :multipart_min_part_size (5242880) The
516
+ # minimum size of a part to upload to S3 when using
517
+ # {#multipart_upload}. S3 will reject parts smaller than 5MB
518
+ # (except the final part). The default is 5MB and can be
519
+ # configured via AWS.config(:s3_multipart_min_part_size => ...).
520
+ #
521
+ # @option options [Hash] :metadata A hash of metadata to be
522
+ # included with the object. These will be sent to S3 as
523
+ # headers prefixed with `x-amz-meta`. Each name, value pair
524
+ # must conform to US-ASCII.
525
+ #
526
+ # @option options [Symbol,String] :acl (:private) A canned access
527
+ # control policy. Valid values are:
528
+ #
529
+ # * `:private`
530
+ # * `:public_read`
531
+ # * `:public_read_write`
532
+ # * `:authenticated_read`
533
+ # * `:bucket_owner_read`
534
+ # * `:bucket_owner_full_control`
535
+ #
536
+ # @option options [String] :grant_read
537
+ #
538
+ # @option options [String] :grant_write
539
+ #
540
+ # @option options [String] :grant_read_acp
541
+ #
542
+ # @option options [String] :grant_write_acp
543
+ #
544
+ # @option options [String] :grant_full_control
545
+ #
546
+ # @option options [Boolean] :reduced_redundancy (false) When `true`,
547
+ # this object will be stored with Reduced Redundancy Storage.
548
+ #
549
+ # @option options :cache_control [String] Can be used to specify
550
+ # caching behavior. See
551
+ # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9
552
+ #
553
+ # @option options :content_disposition [String] Specifies
554
+ # presentational information for the object. See
555
+ # http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.5.1
556
+ #
557
+ # @option options :content_encoding [String] Specifies what
558
+ # content encodings have been applied to the object and thus
559
+ # what decoding mechanisms must be applied to obtain the
560
+ # media-type referenced by the `Content-Type` header field.
561
+ # See
562
+ # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.11
563
+ #
564
+ # @option options [String] :content_md5
565
+ # The base64 encoded content md5 of the data.
566
+ #
567
+ # @option options :content_type A standard MIME type
568
+ # describing the format of the object data.
569
+ #
570
+ # @option options [Symbol] :server_side_encryption (nil) If this
571
+ # option is set, the object will be stored using server side
572
+ # encryption. The only valid value is `:aes256`, which
573
+ # specifies that the object should be stored using the AES
574
+ # encryption algorithm with 256 bit keys. By default, this
575
+ # option uses the value of the `:s3_server_side_encryption`
576
+ # option in the current configuration; for more information,
577
+ # see {AWS.config}.
578
+ #
579
+ # @option options [OpenSSL::PKey::RSA, String] :encryption_key
580
+ # Set this to encrypt the data client-side using envelope
581
+ # encryption. The key must be an OpenSSL asymmetric key
582
+ # or a symmetric key string (16, 24 or 32 bytes in length).
583
+ #
584
+ # @option options [Symbol] :encryption_materials_location (:metadata)
585
+ # Set this to `:instruction_file` if you prefer to store the
586
+ # client-side encryption materials in a separate object in S3
587
+ # instead of in the object metadata.
588
+ #
589
+ # @option options [String] :expires The date and time at which the
590
+ # object is no longer cacheable.
591
+ #
592
+ # @option options [String] :website_redirect_location
593
+ #
594
+ # @return [S3Object, ObjectVersion] If the bucket has versioning
595
+ # enabled, this methods returns an {ObjectVersion}, otherwise
596
+ # this method returns `self`.
597
+ #
598
+ def write *args, &block
599
+
600
+ options = compute_write_options(*args, &block)
601
+
602
+ add_storage_class_option(options)
603
+ add_sse_options(options)
604
+ add_cse_options(options)
605
+
606
+ if use_multipart?(options)
607
+ write_with_multipart(options)
608
+ else
609
+ write_with_put_object(options)
610
+ end
611
+
612
+ end
613
+
614
+ # Performs a multipart upload. Use this if you have specific
615
+ # needs for how the upload is split into parts, or if you want
616
+ # to have more control over how the failure of an individual
617
+ # part upload is handled. Otherwise, {#write} is much simpler
618
+ # to use.
619
+ #
620
+ # Note: After you initiate multipart upload and upload one or
621
+ # more parts, you must either complete or abort multipart
622
+ # upload in order to stop getting charged for storage of the
623
+ # uploaded parts. Only after you either complete or abort
624
+ # multipart upload, Amazon S3 frees up the parts storage and
625
+ # stops charging you for the parts storage.
626
+ #
627
+ # @example Uploading an object in two parts
628
+ #
629
+ # bucket.objects.myobject.multipart_upload do |upload|
630
+ # upload.add_part("a" * 5242880)
631
+ # upload.add_part("b" * 2097152)
632
+ # end
633
+ #
634
+ # @example Uploading parts out of order
635
+ #
636
+ # bucket.objects.myobject.multipart_upload do |upload|
637
+ # upload.add_part("b" * 2097152, :part_number => 2)
638
+ # upload.add_part("a" * 5242880, :part_number => 1)
639
+ # end
640
+ #
641
+ # @example Aborting an upload after parts have been added
642
+ #
643
+ # bucket.objects.myobject.multipart_upload do |upload|
644
+ # upload.add_part("b" * 2097152, :part_number => 2)
645
+ # upload.abort
646
+ # end
647
+ #
648
+ # @example Starting an upload and completing it later by ID
649
+ #
650
+ # upload = bucket.objects.myobject.multipart_upload
651
+ # upload.add_part("a" * 5242880)
652
+ # upload.add_part("b" * 2097152)
653
+ # id = upload.id
654
+ #
655
+ # # later or in a different process
656
+ # upload = bucket.objects.myobject.multipart_uploads[id]
657
+ # upload.complete(:remote_parts)
658
+ #
659
+ # @yieldparam [MultipartUpload] upload A handle to the upload.
660
+ # {MultipartUpload#close} is called in an `ensure` clause so
661
+ # that the upload will always be either completed or
662
+ # aborted.
663
+ #
664
+ # @param [Hash] options Options for the upload.
665
+ #
666
+ # @option options [Hash] :metadata A hash of metadata to be
667
+ # included with the object. These will be sent to S3 as
668
+ # headers prefixed with `x-amz-meta`. Each name, value pair
669
+ # must conform to US-ASCII.
670
+ #
671
+ # @option options [Symbol] :acl (private) A canned access
672
+ # control policy. Valid values are:
673
+ #
674
+ # * `:private`
675
+ # * `:public_read`
676
+ # * `:public_read_write`
677
+ # * `:authenticated_read`
678
+ # * `:bucket_owner_read`
679
+ # * `:bucket_owner_full_control`
680
+ #
681
+ # @option options [Boolean] :reduced_redundancy (false) If true,
682
+ # Reduced Redundancy Storage will be enabled for the uploaded
683
+ # object.
684
+ #
685
+ # @option options :cache_control [String] Can be used to specify
686
+ # caching behavior. See
687
+ # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9
688
+ #
689
+ # @option options :content_disposition [String] Specifies
690
+ # presentational information for the object. See
691
+ # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec19.5.1
692
+ #
693
+ # @option options :content_encoding [String] Specifies what
694
+ # content encodings have been applied to the object and thus
695
+ # what decoding mechanisms must be applied to obtain the
696
+ # media-type referenced by the `Content-Type` header field.
697
+ # See
698
+ # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.11
699
+ #
700
+ # @option options :content_type A standard MIME type
701
+ # describing the format of the object data.
702
+ #
703
+ # @option options [Symbol] :server_side_encryption (nil) If this
704
+ # option is set, the object will be stored using server side
705
+ # encryption. The only valid value is `:aes256`, which
706
+ # specifies that the object should be stored using the AES
707
+ # encryption algorithm with 256 bit keys. By default, this
708
+ # option uses the value of the `:s3_server_side_encryption`
709
+ # option in the current configuration; for more information,
710
+ # see {AWS.config}.
711
+ #
712
+ # @return [S3Object, ObjectVersion] If the bucket has versioning
713
+ # enabled, returns the {ObjectVersion} representing the
714
+ # version that was uploaded. If versioning is disabled,
715
+ # returns self.
716
+ #
717
+ def multipart_upload(options = {})
718
+
719
+ options = options.dup
720
+ add_sse_options(options)
721
+
722
+ upload = multipart_uploads.create(options)
723
+
724
+ if block_given?
725
+ begin
726
+ yield(upload)
727
+ upload.close
728
+ rescue => e
729
+ upload.abort
730
+ raise e
731
+ end
732
+ else
733
+ upload
734
+ end
735
+ end
736
+
737
+ # @example Abort any in-progress uploads for the object:
738
+ #
739
+ # object.multipart_uploads.each(&:abort)
740
+ #
741
+ # @return [ObjectUploadCollection] Returns an object representing the
742
+ # collection of uploads that are in progress for this object.
743
+ def multipart_uploads
744
+ ObjectUploadCollection.new(self)
745
+ end
746
+
747
+ # Moves an object to a new key.
748
+ #
749
+ # This works by copying the object to a new key and then
750
+ # deleting the old object. This function returns the
751
+ # new object once this is done.
752
+ #
753
+ # bucket = s3.buckets['old-bucket']
754
+ # old_obj = bucket.objects['old-key']
755
+ #
756
+ # # renaming an object returns a new object
757
+ # new_obj = old_obj.move_to('new-key')
758
+ #
759
+ # old_obj.key #=> 'old-key'
760
+ # old_obj.exists? #=> false
761
+ #
762
+ # new_obj.key #=> 'new-key'
763
+ # new_obj.exists? #=> true
764
+ #
765
+ # If you need to move an object to a different bucket, pass
766
+ # `:bucket` or `:bucket_name`.
767
+ #
768
+ # obj = s3.buckets['old-bucket'].objects['old-key']
769
+ # obj.move_to('new-key', :bucket_name => 'new_bucket')
770
+ #
771
+ # If the copy succeeds, but the then the delete fails, an error
772
+ # will be raised.
773
+ #
774
+ # @param [String] target The key to move this object to.
775
+ #
776
+ # @param [Hash] options
777
+ #
778
+ # @option (see #copy_to)
779
+ #
780
+ # @return [S3Object] Returns a new object with the new key.
781
+ #
782
+ def move_to target, options = {}
783
+ copy = copy_to(target, options)
784
+ delete
785
+ copy
786
+ end
787
+ alias_method :rename_to, :move_to
788
+
789
+ # Copies data from one S3 object to another.
790
+ #
791
+ # S3 handles the copy so the clients does not need to fetch the data
792
+ # and upload it again. You can also change the storage class and
793
+ # metadata of the object when copying.
794
+ #
795
+ # @note This operation does not copy the ACL, storage class
796
+ # (standard vs. reduced redundancy) or server side encryption
797
+ # setting from the source object. If you don't specify any of
798
+ # these options when copying, the object will have the default
799
+ # values as described below.
800
+ #
801
+ # @param [Mixed] source
802
+ #
803
+ # @param [Hash] options
804
+ #
805
+ # @option options [String] :bucket_name The name of the bucket
806
+ # the source object can be found in. Defaults to the current
807
+ # object's bucket.
808
+ #
809
+ # @option options [Bucket] :bucket The bucket the source object
810
+ # can be found in. Defaults to the current object's bucket.
811
+ #
812
+ # @option options [Hash] :metadata A hash of metadata to save
813
+ # with the copied object. Each name, value pair must conform
814
+ # to US-ASCII. When blank, the sources metadata is copied.
815
+ # If you set this value, you must set ALL metadata values for
816
+ # the object as we do not preserve existing values.
817
+ #
818
+ # @option options [String] :content_type The content type of
819
+ # the copied object. Defaults to the source object's content
820
+ # type.
821
+ #
822
+ # @option options [String] :content_disposition The presentational
823
+ # information for the object. Defaults to the source object's
824
+ # content disposition.
825
+ #
826
+ # @option options [Boolean] :reduced_redundancy (false) If true the
827
+ # object is stored with reduced redundancy in S3 for a lower cost.
828
+ #
829
+ # @option options [String] :version_id (nil) Causes the copy to
830
+ # read a specific version of the source object.
831
+ #
832
+ # @option options [Symbol] :acl (private) A canned access
833
+ # control policy. Valid values are:
834
+ #
835
+ # * `:private`
836
+ # * `:public_read`
837
+ # * `:public_read_write`
838
+ # * `:authenticated_read`
839
+ # * `:bucket_owner_read`
840
+ # * `:bucket_owner_full_control`
841
+ #
842
+ # @option options [Symbol] :server_side_encryption (nil) If this
843
+ # option is set, the object will be stored using server side
844
+ # encryption. The only valid value is `:aes256`, which
845
+ # specifies that the object should be stored using the AES
846
+ # encryption algorithm with 256 bit keys. By default, this
847
+ # option uses the value of the `:s3_server_side_encryption`
848
+ # option in the current configuration; for more information,
849
+ # see {AWS.config}.
850
+ #
851
+ # @option options [Boolean] :client_side_encrypted (false) Set to true
852
+ # when the object being copied was client-side encrypted. This
853
+ # is important so the encryption metadata will be copied.
854
+ #
855
+ # @option options [Boolean] :use_multipart_copy (false) Set this to
856
+ # `true` if you need to copy an object that is larger than 5GB.
857
+ #
858
+ # @option options :cache_control [String] Can be used to specify
859
+ # caching behavior. See
860
+ # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9
861
+ #
862
+ # @option options [String] :expires The date and time at which the
863
+ # object is no longer cacheable.
864
+ #
865
+ # @return [nil]
866
+ def copy_from source, options = {}
867
+
868
+ options = options.dup
869
+
870
+ options[:copy_source] =
871
+ case source
872
+ when S3Object
873
+ "#{source.bucket.name}/#{source.key}"
874
+ when ObjectVersion
875
+ options[:version_id] = source.version_id
876
+ "#{source.object.bucket.name}/#{source.object.key}"
877
+ else
878
+ if options[:bucket]
879
+ "#{options.delete(:bucket).name}/#{source}"
880
+ elsif options[:bucket_name]
881
+ "#{options.delete(:bucket_name)}/#{source}"
882
+ else
883
+ "#{self.bucket.name}/#{source}"
884
+ end
885
+ end
886
+
887
+ if [:metadata, :content_disposition, :content_type, :cache_control,
888
+ ].any? {|opt| options.key?(opt) }
889
+ then
890
+ options[:metadata_directive] = 'REPLACE'
891
+ else
892
+ options[:metadata_directive] ||= 'COPY'
893
+ end
894
+
895
+ # copies client-side encryption materials (from the metadata or
896
+ # instruction file)
897
+ if options.delete(:client_side_encrypted)
898
+ copy_cse_materials(source, options)
899
+ end
900
+
901
+ add_sse_options(options)
902
+
903
+ options[:storage_class] = options.delete(:reduced_redundancy) ?
904
+ 'REDUCED_REDUNDANCY' : 'STANDARD'
905
+
906
+ options[:bucket_name] = bucket.name
907
+ options[:key] = key
908
+
909
+ if use_multipart_copy?(options)
910
+ multipart_copy(options)
911
+ else
912
+ resp = client.copy_object(options)
913
+ end
914
+
915
+ nil
916
+
917
+ end
918
+
919
+ # Copies data from the current object to another object in S3.
920
+ #
921
+ # S3 handles the copy so the client does not need to fetch the data
922
+ # and upload it again. You can also change the storage class and
923
+ # metadata of the object when copying.
924
+ #
925
+ # @note This operation does not copy the ACL, storage class
926
+ # (standard vs. reduced redundancy) or server side encryption
927
+ # setting from this object to the new object. If you don't
928
+ # specify any of these options when copying, the new object
929
+ # will have the default values as described below.
930
+ #
931
+ # @param [S3Object,String] target An S3Object, or a string key of
932
+ # and object to copy to.
933
+ #
934
+ # @param [Hash] options
935
+ #
936
+ # @option options [String] :bucket_name The name of the bucket
937
+ # the object should be copied into. Defaults to the current object's
938
+ # bucket.
939
+ #
940
+ # @option options [Bucket] :bucket The bucket the target object
941
+ # should be copied into. Defaults to the current object's bucket.
942
+ #
943
+ # @option options [Hash] :metadata A hash of metadata to save
944
+ # with the copied object. Each name, value pair must conform
945
+ # to US-ASCII. When blank, the sources metadata is copied.
946
+ #
947
+ # @option options [Boolean] :reduced_redundancy (false) If true
948
+ # the object is stored with reduced redundancy in S3 for a
949
+ # lower cost.
950
+ #
951
+ # @option options [Symbol] :acl (private) A canned access
952
+ # control policy. Valid values are:
953
+ #
954
+ # * `:private`
955
+ # * `:public_read`
956
+ # * `:public_read_write`
957
+ # * `:authenticated_read`
958
+ # * `:bucket_owner_read`
959
+ # * `:bucket_owner_full_control`
960
+ #
961
+ # @option options [Symbol] :server_side_encryption (nil) If this
962
+ # option is set, the object will be stored using server side
963
+ # encryption. The only valid value is `:aes256`, which
964
+ # specifies that the object should be stored using the AES
965
+ # encryption algorithm with 256 bit keys. By default, this
966
+ # option uses the value of the `:s3_server_side_encryption`
967
+ # option in the current configuration; for more information,
968
+ # see {AWS.config}.
969
+ #
970
+ # @option options [Boolean] :client_side_encrypted (false) When `true`,
971
+ # the client-side encryption materials will be copied. Without this
972
+ # option, the key and iv are not guaranteed to be transferred to
973
+ # the new object.
974
+ #
975
+ # @option options [String] :expires The date and time at which the
976
+ # object is no longer cacheable.
977
+ #
978
+ # @return [S3Object] Returns the copy (target) object.
979
+ #
980
+ def copy_to target, options = {}
981
+
982
+ unless target.is_a?(S3Object)
983
+
984
+ bucket = case
985
+ when options[:bucket] then options[:bucket]
986
+ when options[:bucket_name]
987
+ Bucket.new(options[:bucket_name], :config => config)
988
+ else self.bucket
989
+ end
990
+
991
+ target = S3Object.new(bucket, target)
992
+ end
993
+
994
+ copy_opts = options.dup
995
+ copy_opts.delete(:bucket)
996
+ copy_opts.delete(:bucket_name)
997
+
998
+ target.copy_from(self, copy_opts)
999
+ target
1000
+
1001
+ end
1002
+
1003
+ # Fetches the object data from S3. If you pass a block to this
1004
+ # method, the data will be yielded to the block in chunks as it
1005
+ # is read off the HTTP response.
1006
+ #
1007
+ # ### Read an object from S3 in chunks
1008
+ #
1009
+ # When downloading large objects it is recommended to pass a block
1010
+ # to #read. Data will be yielded to the block as it is read off
1011
+ # the HTTP response.
1012
+ #
1013
+ # # read an object from S3 to a file
1014
+ # File.open('output.txt', 'wb') do |file|
1015
+ # bucket.objects['key'].read do |chunk|
1016
+ # file.write(chunk)
1017
+ # end
1018
+ # end
1019
+ #
1020
+ # ### Reading an object without a block
1021
+ #
1022
+ # When you omit the block argument to #read, then the entire
1023
+ # HTTP response and read and the object data is loaded into
1024
+ # memory.
1025
+ #
1026
+ # bucket.objects['key'].read
1027
+ # #=> 'object-contents-here'
1028
+ #
1029
+ # @param [Hash] options
1030
+ #
1031
+ # @option options [String] :version_id Reads data from a
1032
+ # specific version of this object.
1033
+ #
1034
+ # @option options [Time] :if_unmodified_since If specified, the
1035
+ # method will raise
1036
+ # `AWS::S3::Errors::PreconditionFailed` unless the
1037
+ # object has not been modified since the given time.
1038
+ #
1039
+ # @option options [Time] :if_modified_since If specified, the
1040
+ # method will raise `AWS::S3::Errors::NotModified` if
1041
+ # the object has not been modified since the given time.
1042
+ #
1043
+ # @option options [String] :if_match If specified, the method
1044
+ # will raise `AWS::S3::Errors::PreconditionFailed`
1045
+ # unless the object ETag matches the provided value.
1046
+ #
1047
+ # @option options [String] :if_none_match If specified, the
1048
+ # method will raise `AWS::S3::Errors::NotModified` if
1049
+ # the object ETag matches the provided value.
1050
+ #
1051
+ # @option options [Range] :range A byte range to read data from
1052
+ #
1053
+ # @option options [OpenSSL::PKey::RSA, String] :encryption_key
1054
+ # (nil) If this option is set, the object will be decrypted using
1055
+ # envelope encryption. The valid values are OpenSSL asymmetric keys
1056
+ # `OpenSSL::Pkey::RSA` or strings representing symmetric keys
1057
+ # of an AES-128/192/256-ECB cipher as a `String`.
1058
+ # This value defaults to the value in `s3_encryption_key`;
1059
+ # for more information, see {AWS.config}.
1060
+ #
1061
+ # Symmetric Keys:
1062
+ #
1063
+ # cipher = OpenSSL::Cipher.new('AES-256-ECB')
1064
+ # key = cipher.random_key
1065
+ #
1066
+ # Asymmetric keys can also be generated as so:
1067
+ # key = OpenSSL::PKey::RSA.new(KEY_SIZE)
1068
+ #
1069
+ # @option options [Symbol] :encryption_materials_location (:metadata)
1070
+ # Set this to `:instruction_file` if the encryption materials
1071
+ # are not stored in the object metadata
1072
+ #
1073
+ # @note `:range` option cannot be used with client-side encryption
1074
+ #
1075
+ # @note All decryption reads incur at least an extra HEAD operation.
1076
+ #
1077
+ def read options = {}, &read_block
1078
+
1079
+ options[:bucket_name] = bucket.name
1080
+ options[:key] = key
1081
+
1082
+ if should_decrypt?(options)
1083
+ get_encrypted_object(options, &read_block)
1084
+ else
1085
+ resp_data = get_object(options, &read_block)
1086
+ block_given? ? resp_data : resp_data[:data]
1087
+ end
1088
+
1089
+ end
1090
+
1091
+ # @api private
1092
+ module ACLProxy
1093
+
1094
+ attr_accessor :object
1095
+
1096
+ def change
1097
+ yield(self)
1098
+ object.acl = self
1099
+ end
1100
+
1101
+ end
1102
+
1103
+ # Returns the object's access control list. This will be an
1104
+ # instance of AccessControlList, plus an additional `change`
1105
+ # method:
1106
+ #
1107
+ # object.acl.change do |acl|
1108
+ # # remove any grants to someone other than the bucket owner
1109
+ # owner_id = object.bucket.owner.id
1110
+ # acl.grants.reject! do |g|
1111
+ # g.grantee.canonical_user_id != owner_id
1112
+ # end
1113
+ # end
1114
+ #
1115
+ # Note that changing the ACL is not an atomic operation; it
1116
+ # fetches the current ACL, yields it to the block, and then
1117
+ # sets it again. Therefore, it's possible that you may
1118
+ # overwrite a concurrent update to the ACL using this
1119
+ # method.
1120
+ #
1121
+ # @return [AccessControlList]
1122
+ #
1123
+ def acl
1124
+
1125
+ resp = client.get_object_acl(:bucket_name => bucket.name, :key => key)
1126
+
1127
+ acl = AccessControlList.new(resp.data)
1128
+ acl.extend ACLProxy
1129
+ acl.object = self
1130
+ acl
1131
+
1132
+ end
1133
+
1134
+ # Sets the objects's ACL (access control list). You can provide an ACL
1135
+ # in a number of different formats.
1136
+ # @param (see ACLOptions#acl_options)
1137
+ # @return [nil]
1138
+ def acl=(acl)
1139
+
1140
+ client_opts = {}
1141
+ client_opts[:bucket_name] = bucket.name
1142
+ client_opts[:key] = key
1143
+
1144
+ client.put_object_acl(acl_options(acl).merge(client_opts))
1145
+ nil
1146
+
1147
+ end
1148
+
1149
+ # @api private
1150
+ REQUEST_PARAMETERS = Core::Signers::S3::QUERY_PARAMS.map do |p|
1151
+ p.tr("-","_").to_sym
1152
+ end
1153
+
1154
+ # Generates a presigned URL for an operation on this object.
1155
+ # This URL can be used by a regular HTTP client to perform the
1156
+ # desired operation without credentials and without changing
1157
+ # the permissions of the object.
1158
+ #
1159
+ # @example Generate a url to read an object
1160
+ #
1161
+ # bucket.objects.myobject.url_for(:read)
1162
+ #
1163
+ # @example Generate a url to delete an object
1164
+ #
1165
+ # bucket.objects.myobject.url_for(:delete)
1166
+ #
1167
+ # @example Override response headers for reading an object
1168
+ #
1169
+ # object = bucket.objects.myobject
1170
+ # url = object.url_for(:read,
1171
+ # :response_content_type => "application/json")
1172
+ #
1173
+ # @example Generate a url that expires in 10 minutes
1174
+ #
1175
+ # bucket.objects.myobject.url_for(:read, :expires => 10*60)
1176
+ #
1177
+ # @param [Symbol, String] method The HTTP verb or object
1178
+ # method for which the returned URL will be valid. Valid
1179
+ # values:
1180
+ #
1181
+ # * `:get` or `:read`
1182
+ # * `:put` or `:write`
1183
+ # * `:delete`
1184
+ # * `:head`
1185
+ #
1186
+ # @param [Hash] options Additional options for generating the URL.
1187
+ #
1188
+ # @option options :expires Sets the expiration time of the
1189
+ # URL; after this time S3 will return an error if the URL is
1190
+ # used. This can be an integer (to specify the number of
1191
+ # seconds after the current time), a string (which is parsed
1192
+ # as a date using Time#parse), a Time, or a DateTime object.
1193
+ # This option defaults to one hour after the current time.
1194
+ #
1195
+ # @option options [Boolean] :secure (true) Whether to generate a
1196
+ # secure (HTTPS) URL or a plain HTTP url.
1197
+ #
1198
+ # @option options [String] :content_type Object content type for
1199
+ # HTTP PUT. When provided, has to be also added to the request
1200
+ # header as a 'content-type' field
1201
+ #
1202
+ # @option options [String] :content_md5 Object MD5 hash for HTTP PUT.
1203
+ # When provided, has to be also added to the request header as a
1204
+ # 'content-md5' field
1205
+ #
1206
+ # @option options [String] :endpoint Sets the hostname of the
1207
+ # endpoint.
1208
+ #
1209
+ # @option options [Integer] :port Sets the port of the
1210
+ # endpoint (overrides config.s3_port).
1211
+ #
1212
+ # @option options [Boolean] :force_path_style (false) Indicates
1213
+ # whether the generated URL should place the bucket name in
1214
+ # the path (true) or as a subdomain (false).
1215
+ #
1216
+ # @option options [String] :response_content_type Sets the
1217
+ # Content-Type header of the response when performing an
1218
+ # HTTP GET on the returned URL.
1219
+ #
1220
+ # @option options [String] :response_content_language Sets the
1221
+ # Content-Language header of the response when performing an
1222
+ # HTTP GET on the returned URL.
1223
+ #
1224
+ # @option options [String] :response_expires Sets the Expires
1225
+ # header of the response when performing an HTTP GET on the
1226
+ # returned URL.
1227
+ #
1228
+ # @option options [String] :response_cache_control Sets the
1229
+ # Cache-Control header of the response when performing an
1230
+ # HTTP GET on the returned URL.
1231
+ #
1232
+ # @option options [String] :response_content_disposition Sets
1233
+ # the Content-Disposition header of the response when
1234
+ # performing an HTTP GET on the returned URL.
1235
+ #
1236
+ # @option options [String] :acl The value to use for the
1237
+ # x-amz-acl.
1238
+ #
1239
+ # @option options [String] :response_content_encoding Sets the
1240
+ # Content-Encoding header of the response when performing an
1241
+ # HTTP GET on the returned URL.
1242
+ #
1243
+ # @option options [:v3, :v4] :signature_version (:v3)
1244
+ #
1245
+ # @return [URI::HTTP, URI::HTTPS]
1246
+ def url_for(method, options = {})
1247
+
1248
+ options = options.dup
1249
+ options[:expires] = expiration_timestamp(options[:expires])
1250
+ options[:secure] = config.use_ssl? unless options.key?(:secure)
1251
+ options[:signature_version] ||= config.s3_signature_version
1252
+
1253
+ case options[:signature_version]
1254
+ when :v3 then presign_v3(method, options)
1255
+ when :v4 then presign_v4(method, options)
1256
+ else
1257
+ msg = "invalid signature version, expected :v3 or :v4, got "
1258
+ msg << options[:signature_version].inspect
1259
+ raise ArgumentError, msg
1260
+ end
1261
+ end
1262
+
1263
+ # Generates a public (not authenticated) URL for the object.
1264
+ #
1265
+ # @param [Hash] options Options for generating the URL.
1266
+ #
1267
+ # @option options [Boolean] :secure Whether to generate a
1268
+ # secure (HTTPS) URL or a plain HTTP url.
1269
+ #
1270
+ # @return [URI::HTTP, URI::HTTPS]
1271
+ #
1272
+ def public_url(options = {})
1273
+ options[:secure] = config.use_ssl? unless options.key?(:secure)
1274
+ build_uri(request_for_signing(options), options)
1275
+ end
1276
+
1277
+ # Generates fields for a presigned POST to this object. This
1278
+ # method adds a constraint that the key must match the key of
1279
+ # this object. All options are sent to the PresignedPost
1280
+ # constructor.
1281
+ #
1282
+ # @see PresignedPost
1283
+ # @return [PresignedPost]
1284
+ def presigned_post(options = {})
1285
+ PresignedPost.new(bucket, options.merge(:key => key))
1286
+ end
1287
+
1288
+ # @note Changing the storage class of an object incurs a COPY
1289
+ # operation.
1290
+ #
1291
+ # Changes the storage class of the object to enable or disable
1292
+ # Reduced Redundancy Storage (RRS).
1293
+ #
1294
+ # @param [true,false] value If this is true, the object will be
1295
+ # copied in place and stored with reduced redundancy at a
1296
+ # lower cost. Otherwise, the object will be copied and stored
1297
+ # with the standard storage class.
1298
+ #
1299
+ # @return [true,false] The `value` parameter.
1300
+ def reduced_redundancy= value
1301
+ copy_from(key, :reduced_redundancy => value)
1302
+ value
1303
+ end
1304
+
1305
+ private
1306
+
1307
+ def presign_v4(method, options)
1308
+ PresignV4.new(self).presign(method, options)
1309
+ end
1310
+
1311
+ def presign_v3(method, options)
1312
+ options[:acl] = options[:acl].to_s.sub('_', '-') if options[:acl]
1313
+
1314
+ req = request_for_signing(options)
1315
+ req.http_method = http_method(method)
1316
+ req.add_param("AWSAccessKeyId", config.credential_provider.access_key_id)
1317
+ req.add_param("versionId", options[:version_id]) if options[:version_id]
1318
+ req.add_param("Signature", signature(req, options))
1319
+ req.add_param("Expires", options[:expires])
1320
+ req.add_param("x-amz-acl", options[:acl]) if options[:acl]
1321
+ if config.credential_provider.session_token
1322
+ req.add_param(
1323
+ "x-amz-security-token",
1324
+ config.credential_provider.session_token
1325
+ )
1326
+ end
1327
+
1328
+ build_uri(req, options)
1329
+ end
1330
+
1331
+ # Used to determine if the data needs to be copied in parts
1332
+ def use_multipart_copy? options
1333
+ options[:use_multipart_copy]
1334
+ end
1335
+
1336
+ def multipart_copy options
1337
+
1338
+ unless options[:content_length]
1339
+ msg = "unknown content length, must set :content_length " +
1340
+ "to use multi-part copy"
1341
+ raise ArgumentError, msg
1342
+ end
1343
+
1344
+ part_size = compute_part_size(options)
1345
+ clean_up_options(options)
1346
+ source_length = options.delete(:content_length)
1347
+
1348
+ multipart_upload(options) do |upload|
1349
+ pos = 0
1350
+ # We copy in part_size chunks until we read the
1351
+ until pos >= source_length
1352
+ last_byte = (pos + part_size >= source_length) ? source_length - 1 : pos + part_size - 1
1353
+ upload.copy_part(options[:copy_source], options.merge({:copy_source_range => "bytes=#{pos}-#{last_byte}"}))
1354
+ pos += part_size
1355
+ end
1356
+ end
1357
+ end
1358
+
1359
+ # @return [Boolean]
1360
+ def should_decrypt? options
1361
+ options[:encryption_key] or config.s3_encryption_key
1362
+ end
1363
+
1364
+ # A small wrapper around client#get_object
1365
+ def get_object options, &read_block
1366
+ client.get_object(options, &read_block).data
1367
+ end
1368
+
1369
+ # A wrapper around get_object that decrypts
1370
+ def get_encrypted_object options, &read_block
1371
+ decryption_cipher(options) do |cipher|
1372
+ if block_given?
1373
+ resp = get_object(options) do |chunk|
1374
+ yield(cipher.update(chunk))
1375
+ end
1376
+ yield(cipher.final)
1377
+ resp
1378
+ else
1379
+ cipher.update(get_object(options)[:data]) + cipher.final
1380
+ end
1381
+ end
1382
+ end
1383
+
1384
+ # @return [Boolean] Returns `true` if the :data option is large or
1385
+ # guessed to be larger than a configured threshold.
1386
+ def use_multipart? options
1387
+ estimated_content_length(options) > multipart_threshold(options) and
1388
+ !options[:single_request]
1389
+ end
1390
+
1391
+ # @return [Integer] Returns the number of bytes where a multipart
1392
+ # upload is used instead of #put_object.
1393
+ def multipart_threshold options
1394
+ threshold = options[:multipart_threshold] ||
1395
+ config.s3_multipart_threshold
1396
+ end
1397
+
1398
+ # @return [Integer] Returns the size of each multipart chunk.
1399
+ def compute_part_size options
1400
+
1401
+ max_parts = options[:multipart_max_parts] ||
1402
+ config.s3_multipart_max_parts
1403
+
1404
+ min_size = options[:multipart_min_part_size] ||
1405
+ config.s3_multipart_min_part_size
1406
+
1407
+ estimated_size = estimated_content_length(options)
1408
+
1409
+ part_size = [(estimated_size.to_f / max_parts).ceil, min_size].max.to_i
1410
+ part_size += 16 - (part_size % 16)
1411
+ part_size
1412
+
1413
+ end
1414
+
1415
+ # @return [Integer] Returns the size of the data or an estimated
1416
+ # size as provided by the user (useful for IO streams).
1417
+ def estimated_content_length options
1418
+ estimate = options[:content_length] ||
1419
+ options[:estimated_content_length]
1420
+ unless estimate
1421
+ msg = "unknown content length, must set :content_length or " +
1422
+ ":estimated_content_length"
1423
+ raise ArgumentError, msg
1424
+ end
1425
+ estimate
1426
+ end
1427
+
1428
+ def build_uri(request, options)
1429
+ uri_class = options[:secure] ? URI::HTTPS : URI::HTTP
1430
+ uri_class.build(:host => request.host,
1431
+ :port => request.port,
1432
+ :path => request.path,
1433
+ :query => request.querystring)
1434
+ end
1435
+
1436
+ def signature request, options
1437
+ parts = []
1438
+ parts << request.http_method
1439
+ parts << options[:content_md5].to_s
1440
+ parts << options[:content_type].to_s
1441
+ parts << options[:expires]
1442
+ parts << "x-amz-acl:#{options[:acl]}" if options[:acl]
1443
+ if token = config.credential_provider.session_token
1444
+ parts << "x-amz-security-token:#{token}"
1445
+ end
1446
+ parts << Core::Signers::S3.canonicalized_resource(request)
1447
+
1448
+ string_to_sign = parts.join("\n")
1449
+
1450
+ secret = config.credential_provider.secret_access_key
1451
+ Core::Signers::Base.sign(secret, string_to_sign, 'sha1')
1452
+ end
1453
+
1454
+ def expiration_timestamp(input)
1455
+ input = input.to_int if input.respond_to?(:to_int)
1456
+ case input
1457
+ when Time then input.to_i
1458
+ when DateTime then Time.parse(input.to_s).to_i
1459
+ when Integer then (Time.now + input).to_i
1460
+ when String then Time.parse(input).to_i
1461
+ else (Time.now + 60*60).to_i
1462
+ end
1463
+ end
1464
+
1465
+ def http_method(input)
1466
+ symbol = case input
1467
+ when :read then :get
1468
+ when :write then :put
1469
+ else
1470
+ input
1471
+ end
1472
+ symbol.to_s.upcase
1473
+ end
1474
+
1475
+ def request_for_signing(options)
1476
+
1477
+ port = [443, 80].include?(config.s3_port) ?
1478
+ (options[:secure] ? 443 : 80) :
1479
+ config.s3_port
1480
+
1481
+ req = Request.new
1482
+
1483
+ req.bucket = bucket.name
1484
+ req.key = key
1485
+ req.host = options.fetch(:endpoint, config.s3_endpoint)
1486
+ req.port = options.fetch(:port, port)
1487
+ req.force_path_style = options.fetch(:force_path_style, config.s3_force_path_style)
1488
+
1489
+ REQUEST_PARAMETERS.each do |param|
1490
+ req.add_param(param.to_s.tr("_","-"),
1491
+ options[param]) if options.key?(param)
1492
+ end
1493
+
1494
+ req
1495
+ end
1496
+
1497
+ def add_sse_options(options)
1498
+ unless options.key?(:server_side_encryption)
1499
+ options[:server_side_encryption] = config.s3_server_side_encryption
1500
+ end
1501
+ options.delete(:server_side_encryption) if
1502
+ options[:server_side_encryption].nil?
1503
+ end
1504
+
1505
+ # Adds client-side encryption metadata headers and encrypts key
1506
+ def add_cse_options(options)
1507
+ encryption_key_for(options) do |encryption_key|
1508
+
1509
+ check_encryption_materials(:encrypt, encryption_key)
1510
+ cipher = get_aes_cipher(:encrypt, :CBC)
1511
+
1512
+ generate_aes_key(cipher) do |envelope_key, envelope_iv|
1513
+ envelope_key, envelope_iv =
1514
+ encode_envelope_key(encryption_key, envelope_key, envelope_iv)
1515
+
1516
+ build_cse_metadata(options,
1517
+ envelope_key,
1518
+ envelope_iv) do |headers, encryption_materials|
1519
+ store_encryption_materials(options, headers, encryption_materials)
1520
+ end
1521
+ end
1522
+
1523
+ # Wrap current stream in encryption
1524
+ options[:data] = CipherIO.new(cipher,
1525
+ options[:data],
1526
+ options[:content_length])
1527
+
1528
+ # Update content_length
1529
+ options[:content_length] =
1530
+ get_encrypted_size(options[:content_length]) if
1531
+ options[:content_length]
1532
+
1533
+ end
1534
+ remove_cse_options(options)
1535
+ end
1536
+
1537
+ # @yield [String, String] Yields an encrypted encoded key and iv pair
1538
+ def encode_envelope_key encryption_key, envelope_key, envelope_iv, &block
1539
+ envelope_key = encrypt(envelope_key, encryption_key)
1540
+ [encode64(envelope_key), encode64(envelope_iv)]
1541
+ end
1542
+
1543
+ # @yield [Hash, Hash] Yields headers and encryption materials that are
1544
+ # to be stored in the metadata and/or instruction file
1545
+ def build_cse_metadata options, enc_envelope_key, enc_envelope_iv, &block
1546
+ # Ensure metadata exists
1547
+ options[:metadata] = {} unless options[:metadata]
1548
+
1549
+ matdesc = options[:encryption_matdesc] || config.s3_encryption_matdesc
1550
+
1551
+ encryption_materials = {'x-amz-key' => enc_envelope_key,
1552
+ 'x-amz-iv' => enc_envelope_iv,
1553
+ 'x-amz-matdesc' => matdesc}
1554
+ orig_headers = {}
1555
+
1556
+ # Save the unencrypted content length
1557
+ if options[:content_length]
1558
+ orig_headers['x-amz-unencrypted-content-length'] =
1559
+ options[:content_length]
1560
+ end
1561
+
1562
+ # Save the unencrypted content MD5
1563
+ if options[:content_md5]
1564
+ orig_headers['x-amz-unencrypted-content-md5'] =
1565
+ options[:content_md5]
1566
+ options.delete(:content_md5)
1567
+ end
1568
+
1569
+ options[:metadata].merge!(orig_headers)
1570
+
1571
+ yield([orig_headers, encryption_materials])
1572
+ end
1573
+
1574
+ # Stores the headers and encryption materials needed to decrypt the data
1575
+ # and to know unencrypted information about the object
1576
+ def store_encryption_materials options, orig_headers, encryption_materials
1577
+ # Get the storage location
1578
+ cse_location = options[:encryption_materials_location] ||
1579
+ config.s3_encryption_materials_location
1580
+
1581
+ # Encryption type specific metadata
1582
+ case cse_location
1583
+ when :metadata
1584
+ options[:metadata].merge!(encryption_materials)
1585
+ when :instruction_file
1586
+ json_string = JSON.generate(encryption_materials)
1587
+ inst_headers = {'x-amz-crypto-instr-file' => ""}.merge(orig_headers)
1588
+ bucket.objects["#{key}.instruction"].write(json_string,
1589
+ :metadata => inst_headers)
1590
+ else
1591
+ msg = "invalid :encryption_materials_location, expected "
1592
+ msg << ":metadata or :instruction_file, got: #{cse_location.inspect}"
1593
+ raise ArgumentError, msg
1594
+ end
1595
+ nil
1596
+ end
1597
+
1598
+ # Removes any extra headers client-side encryption uses.
1599
+ def remove_cse_options options
1600
+ options.delete(:encryption_key)
1601
+ options.delete(:encryption_materials_location)
1602
+ options.delete(:encryption_matdesc)
1603
+ end
1604
+
1605
+ # Yields a decryption cipher for the given client-side encryption key
1606
+ # or raises an error.
1607
+ def decryption_cipher options, &block
1608
+ encryption_key_for(options) do |encryption_key|
1609
+
1610
+ check_encryption_materials(:decrypt, encryption_key)
1611
+
1612
+ location = options[:encryption_materials_location] ||
1613
+ config.s3_encryption_materials_location
1614
+
1615
+ cipher =
1616
+ decryption_materials(location, options) do |envelope_key, envelope_iv|
1617
+ envelope_key, envelope_iv =
1618
+ decode_envelope_key(envelope_key, envelope_iv, encryption_key)
1619
+ get_aes_cipher(:decrypt, :CBC, envelope_key, envelope_iv)
1620
+ end
1621
+
1622
+ remove_cse_options(options)
1623
+
1624
+ yield(cipher)
1625
+
1626
+ end
1627
+ end
1628
+
1629
+ # Decodes the envelope key for decryption
1630
+ def decode_envelope_key envelope_key, envelope_iv, encryption_key
1631
+ decrypted_key =
1632
+ begin
1633
+ decrypt(decode64(envelope_key), encryption_key)
1634
+ rescue RuntimeError
1635
+ msg = "Master key used to decrypt data key is not correct."
1636
+ raise AWS::S3::Errors::IncorrectClientSideEncryptionKey, msg
1637
+ end
1638
+
1639
+ [decrypted_key, decode64(envelope_iv)]
1640
+ end
1641
+
1642
+
1643
+ # @yield [String, String, String] Yields encryption materials for
1644
+ # decryption
1645
+ def decryption_materials location, options = {}, &block
1646
+
1647
+ materials = case location
1648
+ when :metadata then get_metadata_materials(options)
1649
+ when :instruction_file then get_inst_file_materials
1650
+ else
1651
+ msg = "invalid :encryption_materials_location option, expected "
1652
+ msg << ":metadata or :instruction_file, got: #{location.inspect}"
1653
+ raise ArgumentError, msg
1654
+ end
1655
+
1656
+ envelope_key, envelope_iv = materials
1657
+
1658
+ unless envelope_key and envelope_iv
1659
+ raise 'no encryption materials found, unable to decrypt'
1660
+ end
1661
+
1662
+ yield(envelope_key, envelope_iv)
1663
+
1664
+ end
1665
+
1666
+ # @return [String, String, String] Returns the data key, envelope_iv, and the
1667
+ # material description for decryption from the metadata.
1668
+ def get_metadata_materials(options)
1669
+ opts = {}
1670
+ opts[:version_id] = options[:version_id] if options[:version_id]
1671
+ metadata(opts).to_h.values_at(*%w(x-amz-key x-amz-iv))
1672
+ end
1673
+
1674
+ # @return [String, String, String] Returns the data key, envelope_iv, and the
1675
+ # material description for decryption from the instruction file.
1676
+ def get_inst_file_materials
1677
+ obj = bucket.objects["#{key}.instruction"]
1678
+ JSON.parse(obj.read).values_at(*%w(x-amz-key x-amz-iv))
1679
+ end
1680
+
1681
+ # @yield [Hash] Yields the metadata to be saved for client-side encryption
1682
+ def copy_cse_materials source, options
1683
+ cse_materials = {}
1684
+ meta = source.metadata.to_h
1685
+ cse_materials['x-amz-key'] = meta['x-amz-key'] if meta['x-amz-key']
1686
+ cse_materials['x-amz-iv'] = meta['x-amz-iv'] if meta['x-amz-iv']
1687
+ cse_materials['x-amz-matdesc'] = meta['x-amz-matdesc'] if
1688
+ meta['x-amz-matdesc']
1689
+ cse_materials['x-amz-unencrypted-content-length'] =
1690
+ meta['x-amz-unencrypted-content-length'] if
1691
+ meta['x-amz-unencrypted-content-length']
1692
+ cse_materials['x-amz-unencrypted-content-md5'] =
1693
+ meta['x-amz-unencrypted-content-md5'] if
1694
+ meta['x-amz-unencrypted-content-md5']
1695
+
1696
+ if
1697
+ cse_materials['x-amz-key'] and
1698
+ cse_materials['x-amz-iv'] and
1699
+ cse_materials['x-amz-matdesc']
1700
+ then
1701
+ options[:metadata] = (options[:metadata] || {}).merge(cse_materials)
1702
+ else
1703
+ # Handling instruction file
1704
+ source_inst = "#{source.key}.instruction"
1705
+ dest_inst = "#{key}.instruction"
1706
+ self.bucket.objects[dest_inst].copy_from(
1707
+ source.bucket.objects[source_inst])
1708
+ end
1709
+ end
1710
+
1711
+ # Removes unwanted options that should not be passed to the client.
1712
+ def clean_up_options(options)
1713
+ options.delete(:estimated_content_length)
1714
+ options.delete(:single_request)
1715
+ options.delete(:multipart_threshold)
1716
+ end
1717
+
1718
+ # Performs a write using a multipart upload
1719
+ def write_with_multipart options
1720
+ part_size = compute_part_size(options)
1721
+ clean_up_options(options)
1722
+ options.delete(:content_length)
1723
+
1724
+ multipart_upload(options) do |upload|
1725
+ upload.add_part(options[:data].read(part_size)) until
1726
+ options[:data].eof?
1727
+ end
1728
+ end
1729
+
1730
+ # Performs a write using a single request
1731
+ def write_with_put_object options
1732
+
1733
+ # its possible we don't know the content length of the data
1734
+ # option, but the :estimated_content_length was sufficiently
1735
+ # small that we will read the entire stream into memory
1736
+ # so we can tell s3 the content length (this is required).
1737
+ unless options[:content_length]
1738
+ data = StringIO.new
1739
+
1740
+ while (chunk = options[:data].read(4 * 1024))
1741
+ data << chunk
1742
+ end
1743
+
1744
+ options[:content_length] = data.size
1745
+ data.rewind
1746
+ options[:data] = data
1747
+ end
1748
+
1749
+ clean_up_options(options)
1750
+
1751
+ options[:bucket_name] = bucket.name
1752
+ options[:key] = key
1753
+
1754
+ resp = client.put_object(options)
1755
+
1756
+ resp.data[:version_id] ?
1757
+ ObjectVersion.new(self, resp.data[:version_id]) : self
1758
+ end
1759
+
1760
+ def encryption_key_for options, &block
1761
+ if key = options[:encryption_key] || config.s3_encryption_key
1762
+ yield(key)
1763
+ end
1764
+ end
1765
+
1766
+ def add_storage_class_option options
1767
+ if options[:reduced_redundancy] == true
1768
+ options[:storage_class] = 'REDUCED_REDUNDANCY'
1769
+ end
1770
+ end
1771
+
1772
+ # @return [String] Encodes a `String` in base 64 regardless of version of
1773
+ # Ruby for http headers (removes newlines).
1774
+ def encode64 input
1775
+ Base64.encode64(input).split("\n") * ""
1776
+ end
1777
+
1778
+ # @return [String] Decodes a `String` in base 64.
1779
+ def decode64 input
1780
+ Base64.decode64(input)
1781
+ end
1782
+ end
1783
+ end
1784
+ end