aboisvert_aws 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. data/History.txt +329 -0
  2. data/Manifest.txt +61 -0
  3. data/README.txt +163 -0
  4. data/Rakefile +130 -0
  5. data/lib/acf/right_acf_interface.rb +549 -0
  6. data/lib/acf/right_acf_invalidations.rb +144 -0
  7. data/lib/acf/right_acf_origin_access_identities.rb +230 -0
  8. data/lib/acf/right_acf_streaming_interface.rb +229 -0
  9. data/lib/acw/right_acw_interface.rb +248 -0
  10. data/lib/as/right_as_interface.rb +698 -0
  11. data/lib/awsbase/benchmark_fix.rb +39 -0
  12. data/lib/awsbase/right_awsbase.rb +1343 -0
  13. data/lib/awsbase/support.rb +35 -0
  14. data/lib/awsbase/version.rb +9 -0
  15. data/lib/ec2/right_ec2.rb +541 -0
  16. data/lib/ec2/right_ec2_ebs.rb +481 -0
  17. data/lib/ec2/right_ec2_images.rb +444 -0
  18. data/lib/ec2/right_ec2_instances.rb +788 -0
  19. data/lib/ec2/right_ec2_monitoring.rb +70 -0
  20. data/lib/ec2/right_ec2_placement_groups.rb +108 -0
  21. data/lib/ec2/right_ec2_reserved_instances.rb +184 -0
  22. data/lib/ec2/right_ec2_security_groups.rb +491 -0
  23. data/lib/ec2/right_ec2_spot_instances.rb +422 -0
  24. data/lib/ec2/right_ec2_tags.rb +139 -0
  25. data/lib/ec2/right_ec2_vpc.rb +590 -0
  26. data/lib/ec2/right_ec2_vpc2.rb +381 -0
  27. data/lib/ec2/right_ec2_windows_mobility.rb +84 -0
  28. data/lib/elb/right_elb_interface.rb +573 -0
  29. data/lib/emr/right_emr_interface.rb +727 -0
  30. data/lib/iam/right_iam_access_keys.rb +71 -0
  31. data/lib/iam/right_iam_groups.rb +195 -0
  32. data/lib/iam/right_iam_interface.rb +341 -0
  33. data/lib/iam/right_iam_mfa_devices.rb +67 -0
  34. data/lib/iam/right_iam_users.rb +251 -0
  35. data/lib/rds/right_rds_interface.rb +1384 -0
  36. data/lib/right_aws.rb +86 -0
  37. data/lib/route_53/right_route_53_interface.rb +640 -0
  38. data/lib/s3/right_s3.rb +1138 -0
  39. data/lib/s3/right_s3_interface.rb +1278 -0
  40. data/lib/sdb/active_sdb.rb +1107 -0
  41. data/lib/sdb/right_sdb_interface.rb +762 -0
  42. data/lib/sns/right_sns_interface.rb +286 -0
  43. data/lib/sqs/right_sqs.rb +387 -0
  44. data/lib/sqs/right_sqs_gen2.rb +342 -0
  45. data/lib/sqs/right_sqs_gen2_interface.rb +523 -0
  46. data/lib/sqs/right_sqs_interface.rb +593 -0
  47. data/right_aws.gemspec +90 -0
  48. data/test/README.mdown +39 -0
  49. data/test/acf/test_helper.rb +2 -0
  50. data/test/acf/test_right_acf.rb +138 -0
  51. data/test/awsbase/test_helper.rb +2 -0
  52. data/test/awsbase/test_right_awsbase.rb +11 -0
  53. data/test/ec2/test_helper.rb +2 -0
  54. data/test/ec2/test_right_ec2.rb +107 -0
  55. data/test/elb/test_helper.rb +2 -0
  56. data/test/elb/test_right_elb.rb +43 -0
  57. data/test/http_connection.rb +87 -0
  58. data/test/rds/test_helper.rb +2 -0
  59. data/test/rds/test_right_rds.rb +120 -0
  60. data/test/route_53/fixtures/a_record.xml +18 -0
  61. data/test/route_53/fixtures/alias_record.xml +18 -0
  62. data/test/route_53/test_helper.rb +2 -0
  63. data/test/route_53/test_right_route_53.rb +141 -0
  64. data/test/s3/test_helper.rb +2 -0
  65. data/test/s3/test_right_s3.rb +528 -0
  66. data/test/s3/test_right_s3_stubbed.rb +97 -0
  67. data/test/sdb/test_active_sdb.rb +357 -0
  68. data/test/sdb/test_batch_put_attributes.rb +54 -0
  69. data/test/sdb/test_helper.rb +3 -0
  70. data/test/sdb/test_right_sdb.rb +253 -0
  71. data/test/sns/test_helper.rb +2 -0
  72. data/test/sns/test_right_sns.rb +153 -0
  73. data/test/sqs/test_helper.rb +2 -0
  74. data/test/sqs/test_right_sqs.rb +285 -0
  75. data/test/sqs/test_right_sqs_gen2.rb +264 -0
  76. data/test/test_credentials.rb +37 -0
  77. data/test/ts_right_aws.rb +15 -0
  78. metadata +257 -0
@@ -0,0 +1,70 @@
1
+ #
2
+ # Copyright (c) 2009 RightScale Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #
23
+
24
+ module RightAws
25
+
26
+ class Ec2
27
+
28
+ # Enables monitoring for a running instances. For more information, refer to the Amazon CloudWatch Developer Guide.
29
+ #
30
+ # ec2.monitor_instances('i-8437ddec') #=>
31
+ # {:instance_id=>"i-8437ddec", :monitoring_state=>"pending"}
32
+ #
33
+ def monitor_instances(*list)
34
+ link = generate_request("MonitorInstances", amazonize_list('InstanceId', list.flatten) )
35
+ request_info(link, QEc2MonitorInstancesParser.new(:logger => @logger)).first
36
+ rescue Exception
37
+ on_exception
38
+ end
39
+
40
+ # Disables monitoring for a running instances. For more information, refer to the Amazon CloudWatch Developer Guide.
41
+ #
42
+ # ec2.unmonitor_instances('i-8437ddec') #=>
43
+ # {:instance_id=>"i-8437ddec", :monitoring_state=>"disabling"}
44
+ #
45
+ def unmonitor_instances(*list)
46
+ link = generate_request("UnmonitorInstances", amazonize_list('InstanceId', list.flatten) )
47
+ request_info(link, QEc2MonitorInstancesParser.new(:logger => @logger)).first
48
+ rescue Exception
49
+ on_exception
50
+ end
51
+
52
+ class QEc2MonitorInstancesParser < RightAWSParser #:nodoc:
53
+ def tagstart(name, attributes)
54
+ @item = {} if name == 'item'
55
+ end
56
+ def tagend(name)
57
+ case name
58
+ when 'instanceId' then @item[:instance_id] = @text
59
+ when 'state' then @item[:monitoring_state] = @text
60
+ when 'item' then @result << @item
61
+ end
62
+ end
63
+ def reset
64
+ @result = []
65
+ end
66
+ end
67
+
68
+ end
69
+
70
+ end
@@ -0,0 +1,108 @@
1
+ #
2
+ # Copyright (c) 2010 RightScale Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #
23
+
24
+ module RightAws
25
+
26
+ class Ec2
27
+
28
+ #-----------------------------------------------------------------
29
+ # Placement Groups
30
+ #-----------------------------------------------------------------
31
+
32
+ # Describe placement groups.
33
+ #
34
+ # Accepts a list of placement groups and/or a set of filters as the last parameter.
35
+ #
36
+ # Filters: group-name, state, strategy
37
+ #
38
+ # If you don’t specify a particular placement group, the response includes
39
+ # information about all of them. The information includes the group name, the strategy,
40
+ # and the group state (e.g., pending, available, etc.).
41
+ #
42
+ # ec2.describe_placement_groups #=>
43
+ # [{:state=>"available", :strategy=>"cluster", :group_name=>"kd_first"},
44
+ # {:state=>"available", :strategy=>"cluster", :group_name=>"kd_second"}]
45
+ #
46
+ # ec2.describe_placement_groups('kd_second') #=>
47
+ # [{:strategy=>"cluster", :group_name=>"kd_second", :state=>"available"}]
48
+ #
49
+ # P.S. filters: http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference_query_DescribePlacementGroups.html
50
+ #
51
+ def describe_placement_groups(*list_and_options)
52
+ describe_resources_with_list_and_options('DescribePlacementGroups', 'GroupName', QEc2DescribePlacementGroupsParser, list_and_options)
53
+ end
54
+
55
+ # Create placement group creates a placement group (i.e. logical cluster group)
56
+ # into which you can then launch instances. You must provide a name for the group
57
+ # that is unique within the scope of your account. You must also provide a strategy
58
+ # value. Currently the only value accepted is cluster.
59
+ #
60
+ # ec2.create_placement_group('kd_second') #=> true
61
+ #
62
+ def create_placement_group(placement_group_name, strategy = 'cluster')
63
+ link = generate_request('CreatePlacementGroup',
64
+ 'GroupName' => placement_group_name.to_s,
65
+ 'Strategy' => strategy.to_s)
66
+ request_info(link, RightBoolResponseParser.new(:logger => @logger))
67
+ rescue Exception
68
+ on_exception
69
+ end
70
+
71
+ # Delete placement group deletes a placement group that you own. The group must not
72
+ # contain any instances.
73
+ #
74
+ # ec2.delete_placement_group('kd_second') #=> true
75
+ #
76
+ def delete_placement_group(placement_group_name)
77
+ link = generate_request('DeletePlacementGroup',
78
+ 'GroupName' => placement_group_name.to_s)
79
+ request_info(link, RightBoolResponseParser.new(:logger => @logger))
80
+ rescue Exception
81
+ on_exception
82
+ end
83
+
84
+ #-----------------------------------------------------------------
85
+ # PARSERS: Placement Groups
86
+ #-----------------------------------------------------------------
87
+
88
+ class QEc2DescribePlacementGroupsParser < RightAWSParser #:nodoc:
89
+ def tagstart(name, attributes)
90
+ case name
91
+ when 'item' then @item = {}
92
+ end
93
+ end
94
+ def tagend(name)
95
+ case name
96
+ when 'groupName' then @item[:group_name] = @text
97
+ when 'strategy' then @item[:strategy] = @text
98
+ when 'state' then @item[:state] = @text
99
+ when 'item' then @result << @item
100
+ end
101
+ end
102
+ def reset
103
+ @result = []
104
+ end
105
+ end
106
+
107
+ end
108
+ end
@@ -0,0 +1,184 @@
1
+ #
2
+ # Copyright (c) 2009 RightScale Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #
23
+
24
+ module RightAws
25
+
26
+ class Ec2
27
+
28
+ #-----------------------------------------------------------------
29
+ # Reserved instances
30
+ #-----------------------------------------------------------------
31
+
32
+ # Retrieve reserved instances list.
33
+ #
34
+ # Accepts a list of reserved instances and/or a set of filters as the last parameter.
35
+ #
36
+ # Filters: availability-zone, duration, fixed-price, instance-type, product-description,
37
+ # reserved-instances-id, start, state, tag-key, tag-value, tag:key, usage-price
38
+ #
39
+ # ec2.describe_reserved_instances #=>
40
+ # [{:currency_code=>"USD",
41
+ # :aws_fixed_price=>350.0,
42
+ # :aws_availability_zone=>"us-east-1c",
43
+ # :aws_instance_count=>1,
44
+ # :tags=>{},
45
+ # :aws_id=>"4357912c-ad94-4f57-8625-15ca71a8e66d",
46
+ # :aws_product_description=>"Linux/UNIX",
47
+ # :aws_state=>"active",
48
+ # :aws_start=>"2010-03-18T20:39:39.569Z",
49
+ # :aws_duration=>94608000,
50
+ # :aws_instance_type=>"m1.small",
51
+ # :instance_tenancy=>"default",
52
+ # :aws_usage_price=>0.03}]
53
+ #
54
+ # ec2.describe_reserved_instances(:filters => {'availability-zone' => 'us-east-1a'})
55
+ #
56
+ # P.S. filters: http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/index.html?ApiReference-query-DescribeReservedInstances.html
57
+ #
58
+ def describe_reserved_instances(*list_and_options)
59
+ describe_resources_with_list_and_options('DescribeReservedInstances', 'ReservedInstancesId', QEc2DescribeReservedInstancesParser, list_and_options)
60
+ end
61
+
62
+ # Retrieve reserved instances offerings.
63
+ #
64
+ # Accepts a list of reserved instances offerings and/or a set of filters as the last parameter.
65
+ #
66
+ # Filters: availability-zone, duration, fixed-price, instance-type, product-description, reserved-instances-offering-id, usage-price
67
+ #
68
+ # ec2.describe_reserved_instances_offerings #=>
69
+ # [{:currency_code=>"USD",
70
+ # :aws_fixed_price=>700.0,
71
+ # :aws_id=>"248e7b75-933c-451b-b126-be25865e02a5",
72
+ # :aws_product_description=>"Linux/UNIX",
73
+ # :aws_instance_type=>"c1.medium",
74
+ # :aws_duration=>94608000,
75
+ # :instance_tenancy=>"default",
76
+ # :aws_usage_price=>0.06,
77
+ # :aws_availability_zone=>"us-east-1a"},
78
+ # {:currency_code=>"USD",
79
+ # :aws_fixed_price=>700.0,
80
+ # :aws_id=>"c48ab04c-7e03-46b2-891a-2df1116e51a3",
81
+ # :aws_product_description=>"Linux/UNIX (Amazon VPC)",
82
+ # :aws_instance_type=>"c1.medium",
83
+ # :aws_duration=>94608000,
84
+ # :instance_tenancy=>"default",
85
+ # :aws_usage_price=>0.06,
86
+ # :aws_availability_zone=>"us-east-1a"}, ... ]
87
+ #
88
+ # ec2.describe_reserved_instances_offerings(:filters => {'availability-zone' => 'us-east-1c'})
89
+ #
90
+ # P.S. filters: http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/index.html?ApiReference-query-DescribeReservedInstancesOfferings.html
91
+ #
92
+ def describe_reserved_instances_offerings(*list_and_options)
93
+ describe_resources_with_list_and_options('DescribeReservedInstancesOfferings', 'ReservedInstancesOfferingId', QEc2DescribeReservedInstancesOfferingsParser, list_and_options)
94
+ end
95
+
96
+ # Purchase a Reserved Instance.
97
+ # Returns ReservedInstancesId value.
98
+ #
99
+ # ec2.purchase_reserved_instances_offering('e5a2ff3b-f6eb-4b4e-83f8-b879d7060257', 3) # => '4b2293b4-5813-4cc8-9ce3-1957fc1dcfc8'
100
+ #
101
+ def purchase_reserved_instances_offering(reserved_instances_offering_id, instance_count=1)
102
+ link = generate_request("PurchaseReservedInstancesOffering", { 'ReservedInstancesOfferingId' => reserved_instances_offering_id,
103
+ 'InstanceCount' => instance_count })
104
+ request_info(link, QEc2PurchaseReservedInstancesOfferingParser.new)
105
+ rescue Exception
106
+ on_exception
107
+ end
108
+
109
+ #-----------------------------------------------------------------
110
+ # PARSERS: ReservedInstances
111
+ #-----------------------------------------------------------------
112
+
113
+ class QEc2DescribeReservedInstancesParser < RightAWSParser #:nodoc:
114
+ def tagstart(name, attributes)
115
+ case full_tag_name
116
+ when %r{/reservedInstancesSet/item$} then @item = { :tags => {} }
117
+ when %r{/tagSet/item$} then @aws_tag = {}
118
+ end
119
+ end
120
+ def tagend(name)
121
+ case name
122
+ when 'reservedInstancesId' then @item[:aws_id] = @text
123
+ when 'instanceType' then @item[:aws_instance_type] = @text
124
+ when 'availabilityZone' then @item[:aws_availability_zone] = @text
125
+ when 'duration' then @item[:aws_duration] = @text.to_i
126
+ when 'usagePrice' then @item[:aws_usage_price] = @text.to_f
127
+ when 'fixedPrice' then @item[:aws_fixed_price] = @text.to_f
128
+ when 'instanceCount' then @item[:aws_instance_count] = @text.to_i
129
+ when 'productDescription' then @item[:aws_product_description] = @text
130
+ when 'state' then @item[:aws_state] = @text
131
+ when 'start' then @item[:aws_start] = @text
132
+ when 'instanceTenancy' then @item[:instance_tenancy] = @text
133
+ when 'currencyCode' then @item[:currency_code] = @text
134
+ else
135
+ case full_tag_name
136
+ when %r{/tagSet/item/key$} then @aws_tag[:key] = @text
137
+ when %r{/tagSet/item/value$} then @aws_tag[:value] = @text
138
+ when %r{/tagSet/item$} then @item[:tags][@aws_tag[:key]] = @aws_tag[:value]
139
+ when %r{/reservedInstancesSet/item$} then @result << @item
140
+ end
141
+ end
142
+ end
143
+ def reset
144
+ @result = []
145
+ end
146
+ end
147
+
148
+ class QEc2DescribeReservedInstancesOfferingsParser < RightAWSParser #:nodoc:
149
+ def tagstart(name, attributes)
150
+ @item = {} if name == 'item'
151
+ end
152
+ def tagend(name)
153
+ case name
154
+ when 'reservedInstancesOfferingId' then @item[:aws_id] = @text
155
+ when 'instanceType' then @item[:aws_instance_type] = @text
156
+ when 'availabilityZone' then @item[:aws_availability_zone] = @text
157
+ when 'duration' then @item[:aws_duration] = @text.to_i
158
+ when 'usagePrice' then @item[:aws_usage_price] = @text.to_f
159
+ when 'fixedPrice' then @item[:aws_fixed_price] = @text.to_f
160
+ when 'instanceTenancy' then @item[:instance_tenancy] = @text
161
+ when 'currencyCode' then @item[:currency_code] = @text
162
+ when 'productDescription' then @item[:aws_product_description] = @text
163
+ when 'item' then @result << @item
164
+ end
165
+ end
166
+ def reset
167
+ @result = []
168
+ end
169
+ end
170
+
171
+ class QEc2PurchaseReservedInstancesOfferingParser < RightAWSParser #:nodoc:
172
+ def tagend(name)
173
+ if name == 'reservedInstancesId'
174
+ @result = @text
175
+ end
176
+ end
177
+ def reset
178
+ @result = ''
179
+ end
180
+ end
181
+
182
+ end
183
+
184
+ end
@@ -0,0 +1,491 @@
1
+ #
2
+ # Copyright (c) 2010 RightScale Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #
23
+
24
+ module RightAws
25
+
26
+ class Ec2
27
+
28
+ #-----------------------------------------------------------------
29
+ # Security groups
30
+ #-----------------------------------------------------------------
31
+
32
+ # Retrieve Security Groups information.
33
+ # Options: By default this methods expects security group ids but if you wanna pass their names then :describe_by => :group_name option must be set.
34
+ #
35
+ # Accepts a list of security groups and/or a set of filters as the last parameter.
36
+ #
37
+ # Filters: description, group-name, ip-permission.cidr, ip-permission.from-port, ip-permission.group-name,
38
+ # ip-permission.protocol, ip-permission.to-port, ip-permission.user-id, owner-id
39
+ #
40
+ # # Amazon cloud:
41
+ # ec2 = Rightscale::Ec2.new(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)
42
+ # ec2.describe_security_groups #=>
43
+ # [{:aws_perms=>
44
+ # [{:protocol=>"-1", :cidr_ips=>"0.0.0.0/0", :direction=>:egress},
45
+ # {:protocol=>"tcp",
46
+ # :cidr_ips=>"127.0.0.2/32",
47
+ # :direction=>:egress,
48
+ # :from_port=>"1111",
49
+ # :to_port=>"1111"},
50
+ # {:protocol=>"tcp",
51
+ # :cidr_ips=>"127.0.0.1/32",
52
+ # :direction=>:egress,
53
+ # :from_port=>"1111",
54
+ # :to_port=>"1111"}],
55
+ # :aws_group_name=>"kd-vpc-egress-test-1",
56
+ # :vpc_id=>"vpc-e16cf988",
57
+ # :aws_description=>"vpc test",
58
+ # :aws_owner=>"826693181925",
59
+ # :group_id=>"sg-b72032db"}]
60
+ #
61
+ # # Describe by group ids
62
+ # ec2.describe_security_groups("sg-a0b85dc9", "sg-00b05d39", "sg-a1b86dc8")
63
+ #
64
+ # # Describe by group names
65
+ # ec2.describe_security_groups("default", "default1", "kd", :describe_by => :group_name)
66
+ #
67
+ # # Eucalyptus cloud:
68
+ # ec2 = Rightscale::Ec2.new(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, :eucalyptus => true)
69
+ # ec2.describe_security_groups #=>
70
+ # [{:aws_perms=>
71
+ # [{:to_port=>"65535",
72
+ # :group_name=>"default",
73
+ # :protocol=>"tcp",
74
+ # :owner=>"048291609141",
75
+ # :from_port=>"1"},
76
+ # {:to_port=>"65535",
77
+ # :group_name=>"default",
78
+ # :protocol=>"udp",
79
+ # :owner=>"048291609141",
80
+ # :from_port=>"1"},
81
+ # {:to_port=>"-1",
82
+ # :group_name=>"default",
83
+ # :protocol=>"icmp",
84
+ # :owner=>"048291609141",
85
+ # :from_port=>"-1"},
86
+ # {:to_port=>"22",
87
+ # :protocol=>"tcp",
88
+ # :from_port=>"22",
89
+ # :cidr_ip=>"0.0.0.0/0"},
90
+ # {:to_port=>"9997",
91
+ # :protocol=>"tcp",
92
+ # :from_port=>"9997",
93
+ # :cidr_ip=>"0.0.0.0/0"}],
94
+ # :aws_group_name=>"photo_us",
95
+ # :aws_description=>"default group",
96
+ # :aws_owner=>"826693181925"}]
97
+ #
98
+ # ec2.describe_security_groups(:filters => {'ip-permission.from-port' => '22'})
99
+ #
100
+ # P.S. filters: http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeSecurityGroups.html
101
+ #
102
+ def describe_security_groups(*list_and_options)
103
+ list, options = AwsUtils::split_items_and_params(list_and_options)
104
+ describe_by = options.delete(:describe_by) == :group_name ? 'GroupName' : 'GroupId'
105
+ describe_resources_with_list_and_options('DescribeSecurityGroups', describe_by, QEc2DescribeSecurityGroupsParser, list_and_options) do |parser|
106
+ result = []
107
+ parser.result.each do |item|
108
+ result_item = { :aws_owner => item[:owner_id],
109
+ :aws_group_name => item[:group_name],
110
+ :aws_description => item[:group_description] }
111
+ result_item[:group_id] = item[:group_id] unless item[:group_id].right_blank?
112
+ result_item[:vpc_id] = item[:vpc_id] unless item[:vpc_id].right_blank?
113
+ aws_perms = []
114
+ item[:ip_permissions].each do |permission|
115
+ result_perm = {}
116
+ result_perm[:from_port] = permission[:from_port] unless permission[:from_port].right_blank?
117
+ result_perm[:to_port] = permission[:to_port] unless permission[:to_port].right_blank?
118
+ result_perm[:protocol] = permission[:ip_protocol]
119
+ result_perm[:direction] = permission[:direction]
120
+ # IP permissions
121
+ Array(permission[:ip_ranges]).each do |ip_range|
122
+ perm = result_perm.dup
123
+ # Mhhh... For Eucalyptus we somehow get used to use ":cidr_ip" instead of ":cidr_ips"...
124
+ if @params[:eucalyptus] then perm[:cidr_ip] = ip_range
125
+ else perm[:cidr_ips] = ip_range
126
+ end
127
+ aws_perms << perm
128
+ end
129
+ # Group permissions
130
+ Array(permission[:groups]).each do |group|
131
+ perm = result_perm.dup
132
+ perm[:group_name] = group[:group_name] unless group[:group_name].right_blank?
133
+ perm[:group_id] = group[:group_id] unless group[:group_id].right_blank?
134
+ perm[:owner] = group[:user_id] unless group[:user_id].right_blank?
135
+ aws_perms << perm
136
+ end
137
+ end
138
+ result_item[:aws_perms] = aws_perms.uniq
139
+ result << result_item
140
+ end
141
+ result
142
+ end
143
+ end
144
+
145
+ def describe_security_groups_by_name(*list)
146
+ describe_security_groups(list, :describe_by => :group_name)
147
+ end
148
+
149
+ # Create new Security Group. Returns +true+ or an exception.
150
+ # Options: :vpc_id
151
+ #
152
+ # ec2.create_security_group('default-1',"Default allowing SSH, HTTP, and HTTPS ingress") #=>
153
+ # { :group_id=>"sg-f0227599", :return=>true }
154
+ #
155
+ # ec2.create_security_group('default-2',"my VPC group", :vpc_id => 'vpc-e16c0000') #=>
156
+ # { :group_id=>"sg-76d1c31a", :return=>true }
157
+ #
158
+ def create_security_group(name, description = nil, options = {})
159
+ options = options.dup
160
+ options[:group_name] = name
161
+ options[:group_description] = description.right_blank? ? '-' : description # EC2 rejects an empty description...
162
+ link = generate_request("CreateSecurityGroup", map_api_keys_and_values(options, :group_name, :group_description, :vpc_id))
163
+ request_info(link, QEc2CreateSecurityGroupsParser.new(:logger => @logger))
164
+ rescue Exception
165
+ on_exception
166
+ end
167
+
168
+ # Remove Security Group. Returns +true+ or an exception.
169
+ # Options: :group_name, :group_id
170
+ #
171
+ # # Delete security group by group_id:
172
+ # ec2.delete_security_group('sg-90054ef9') #=> true
173
+ # ec2.delete_security_group(:group_id => 'sg-90054ef9') #=> true
174
+ #
175
+ # # Delete security group by name (EC2 only):
176
+ # ec2.delete_security_group(:group_name => 'my-group']) #=> true
177
+ #
178
+ def delete_security_group(group_id_or_options={})
179
+ options = group_id_or_options.is_a?(Hash) ? group_id_or_options : { :group_id => group_id_or_options }
180
+ link = generate_request("DeleteSecurityGroup", map_api_keys_and_values(options, :group_name, :group_id))
181
+ request_info(link, RightBoolResponseParser.new(:logger => @logger))
182
+ rescue Exception
183
+ on_exception
184
+ end
185
+
186
+ def grant_security_group_ingress(group_id, permissions)
187
+ modify_security_group(:grant, :ingress, group_id, permissions)
188
+ end
189
+
190
+ def revoke_security_group_ingress(group_id, permissions)
191
+ modify_security_group(:revoke, :ingress, group_id, permissions)
192
+ end
193
+
194
+ def grant_security_group_egress(group_id, permissions)
195
+ modify_security_group(:grant, :egress, group_id, permissions)
196
+ end
197
+
198
+ def revoke_security_group_egress(group_id, permissions)
199
+ modify_security_group(:revoke, :egress, group_id, permissions)
200
+ end
201
+
202
+ # Modify AWS security group permissions.
203
+ #
204
+ # Options:
205
+ # action - :authorize (or :grant) | :revoke (or :remove)
206
+ # direction - :ingress | :egress
207
+ # group_name - security group name
208
+ # permissions - a combination of options below:
209
+ # # Ports:
210
+ # :from_port => from port
211
+ # :to_port => to port
212
+ # :port => set both :from_port and to_port with the same value
213
+ # # Protocol
214
+ # :protocol => :tcp | :udp | :icmp | -1
215
+ # # or (ingress)
216
+ # :groups => { UserId1 => GroupId1, UserName2 => GroupId2 }
217
+ # :groups => [ [ UserId1, GroupId1 ], [ UserName2 => GroupId2 ] ]
218
+ # # or (egress)
219
+ # :groups => [ GroupId1, GroupId2 ]
220
+ # # CidrIp(s)
221
+ # :cidr_ip => '0.0.0.0/0'
222
+ # :cidr_ips => ['1.1.1.1/1', '2.2.2.2/2']
223
+ #
224
+ # # CidrIP based permissions:
225
+ #
226
+ # ec2.modify_security_group(:authorize, :ingress, 'sg-75d1c319',
227
+ # :cidr_ip => "127.0.0.0/31",
228
+ # :port => 811,
229
+ # :protocol => 'tcp' ) #=> true
230
+ #
231
+ # ec2.modify_security_group(:revoke, :ingress, 'sg-75d1c319',
232
+ # :cidr_ips => ["127.0.0.1/32", "127.0.0.2/32"],
233
+ # :port => 812,
234
+ # :protocol => 'tcp' ) #=> true
235
+ #
236
+ # # Group based permissions:
237
+ #
238
+ # ec2.modify_security_group(:authorize, :ingress, 'sg-75d1c319',
239
+ # :groups => { "586789340000" => "sg-75d1c300",
240
+ # "635201710000" => "sg-75d1c301" },
241
+ # :port => 801,
242
+ # :protocol => 'tcp' ) #=> true
243
+ #
244
+ # ec2.modify_security_group(:revoke, :ingress, 'sg-75d1c319',
245
+ # :groups => [[ "586789340000", "sg-75d1c300" ],
246
+ # [ "586789340000", "sg-75d1c302" ]],
247
+ # :port => 809,
248
+ # :protocol => 'tcp' ) #=> true
249
+ #
250
+ # # +Permissions+ can be an array of permission hashes:
251
+ #
252
+ # ec2.modify_security_group(:authorize, :ingress, 'sg-75d1c319',
253
+ # [{ :groups => { "586789340000" => "sg-75d1c300",
254
+ # "635201710000" => "sg-75d1c301" },
255
+ # :port => 803,
256
+ # :protocol => 'tcp'},
257
+ # { :cidr_ips => ["127.0.0.1/32", "127.0.0.2/32"],
258
+ # :port => 812,
259
+ # :protocol => 'tcp' }]) #=> true
260
+ #
261
+ def modify_security_group(action, direction, group_id, permissions)
262
+ hash = {}
263
+ raise "Unknown action #{action.inspect}!" unless [:authorize, :grant, :revoke, :remove].include?(action)
264
+ raise "Unknown direction #{direction.inspect}!" unless [:ingress, :egress].include?(direction)
265
+ # Remote action
266
+ remote_action = case action
267
+ when :authorize, :grant then direction == :ingress ? "AuthorizeSecurityGroupIngress" : "AuthorizeSecurityGroupEgress"
268
+ when :revoke, :remove then direction == :ingress ? "RevokeSecurityGroupIngress" : "RevokeSecurityGroupEgress"
269
+ end
270
+ # Group Name
271
+ hash["GroupId"] = group_id
272
+ # Permissions
273
+ permissions = [permissions] unless permissions.is_a?(Array)
274
+ permissions.each_with_index do |permission, idx|
275
+ pid = idx+1
276
+ # Protocol
277
+ hash["IpPermissions.#{pid}.IpProtocol"] = permission[:protocol]
278
+ # Port
279
+ unless permission[:port].right_blank?
280
+ hash["IpPermissions.#{pid}.FromPort"] = permission[:port]
281
+ hash["IpPermissions.#{pid}.ToPort"] = permission[:port]
282
+ else
283
+ hash["IpPermissions.#{pid}.FromPort"] = permission[:from_port]
284
+ hash["IpPermissions.#{pid}.ToPort"] = permission[:to_port]
285
+ end
286
+ # Groups
287
+ case direction
288
+ when :ingress
289
+ # :groups => {UserId1 => GroupId1, ... UserIdN => GroupIdN}
290
+ # or (this allows using same UserId multiple times )
291
+ # :groups => [[UserId1, GroupId1], ... [UserIdN, GroupIdN]]
292
+ # or even (unset user is == current account user)
293
+ # :groups => [GroupId1, GroupId2, ... GroupIdN]
294
+ # :groups => [[UserId1, GroupId1], GroupId2, ... GroupIdN, ... [UserIdM, GroupIdM]]
295
+ #
296
+ index = 1
297
+ unless permission[:group_names].right_blank?
298
+ owner_and_groups = []
299
+ groups_only = []
300
+ Array(permission[:group_names]).each do |item|
301
+ if item.is_a?(Array) && item.size == 2
302
+ owner_and_groups << item
303
+ else
304
+ groups_only << item
305
+ end
306
+ end
307
+ hash.merge!(amazonize_list( ["IpPermissions.#{pid}.Groups.?.UserId", "IpPermissions.#{pid}.Groups.?.GroupName"], owner_and_groups, :index => index ))
308
+ index += owner_and_groups.size
309
+ groups_only = groups_only.flatten
310
+ hash.merge!(amazonize_list( "IpPermissions.#{pid}.Groups.?.GroupName", groups_only, :index => index ))
311
+ index += groups_only.size
312
+ end
313
+ unless permission[:groups].right_blank?
314
+ owner_and_groups = []
315
+ groups_only = []
316
+ Array(permission[:groups]).each do |item|
317
+ if item.is_a?(Array) && item.size == 2
318
+ owner_and_groups << item
319
+ else
320
+ groups_only << item
321
+ end
322
+ end
323
+ hash.merge!(amazonize_list( ["IpPermissions.#{pid}.Groups.?.UserId", "IpPermissions.#{pid}.Groups.?.GroupId"], owner_and_groups, :index => index ))
324
+ index += owner_and_groups.size
325
+ groups_only = groups_only.flatten
326
+ hash.merge!(amazonize_list( "IpPermissions.#{pid}.Groups.?.GroupId", groups_only, :index => index ))
327
+ end
328
+ when :egress
329
+ # :groups => [GroupId1, ... GroupIdN]
330
+ hash.merge!(amazonize_list( "IpPermissions.#{pid}.Groups.?.GroupId", permission[:groups] ))
331
+ end
332
+ # CidrIp(s)
333
+ cidr_ips = permission[:cidr_ips] unless permission[:cidr_ips].right_blank?
334
+ cidr_ips ||= permission[:cidr_ip] unless permission[:cidr_ip].right_blank?
335
+ hash.merge!(amazonize_list("IpPermissions.1.IpRanges.?.CidrIp", cidr_ips))
336
+ end
337
+ #
338
+ link = generate_request(remote_action, hash)
339
+ request_info(link, RightBoolResponseParser.new(:logger => @logger))
340
+ rescue Exception
341
+ on_exception
342
+ end
343
+
344
+ #-----------------------------------------------------------------
345
+ # Eucalyptus
346
+ #-----------------------------------------------------------------
347
+
348
+ # Edit AWS/Eucaliptus security group permissions.
349
+ #
350
+ # Options:
351
+ # action - :authorize (or :grant) | :revoke (or :remove)
352
+ # group_name - security group name
353
+ # permissions - a combination of options below:
354
+ # :source_group_owner => UserId
355
+ # :source_group => GroupName
356
+ # :from_port => from port
357
+ # :to_port => to port
358
+ # :port => set both :from_port and to_port with the same value
359
+ # :protocol => :tcp | :udp | :icmp
360
+ # :cidr_ip => '0.0.0.0/0'
361
+ #
362
+ # ec2.edit_security_group( :grant,
363
+ # 'kd-sg-test',
364
+ # :source_group => "sketchy",
365
+ # :source_group_owner => "600000000006",
366
+ # :protocol => 'tcp',
367
+ # :port => '80',
368
+ # :cidr_ip => '127.0.0.1/32') #=> true
369
+ #
370
+ # P.S. This method is deprecated for AWS and but still good for Eucaliptus clouds.
371
+ # Use +modify_security_group_ingress+ method for AWS clouds.
372
+ #
373
+ def edit_security_group(action, group_name, params)
374
+ hash = {}
375
+ case action
376
+ when :authorize, :grant then action = "AuthorizeSecurityGroupIngress"
377
+ when :revoke, :remove then action = "RevokeSecurityGroupIngress"
378
+ else raise "Unknown action #{action.inspect}!"
379
+ end
380
+ hash['GroupName'] = group_name
381
+ hash['SourceSecurityGroupName'] = params[:source_group] unless params[:source_group].right_blank?
382
+ hash['SourceSecurityGroupOwnerId'] = params[:source_group_owner].to_s.gsub(/-/,'') unless params[:source_group_owner].right_blank?
383
+ hash['IpProtocol'] = params[:protocol] unless params[:protocol].right_blank?
384
+ unless params[:port].right_blank?
385
+ hash['FromPort'] = params[:port]
386
+ hash['ToPort'] = params[:port]
387
+ end
388
+ hash['FromPort'] = params[:from_port] unless params[:from_port].right_blank?
389
+ hash['ToPort'] = params[:to_port] unless params[:to_port].right_blank?
390
+ hash['CidrIp'] = params[:cidr_ip] unless params[:cidr_ip].right_blank?
391
+ #
392
+ link = generate_request(action, hash)
393
+ request_info(link, RightBoolResponseParser.new(:logger => @logger))
394
+ rescue Exception
395
+ on_exception
396
+ end
397
+
398
+ # Authorize named ingress for security group. Allows instances that are member of someone
399
+ # else's security group to open connections to instances in my group.
400
+ #
401
+ # ec2.authorize_security_group_named_ingress('my_awesome_group', '7011-0219-8268', 'their_group_name') #=> true
402
+ #
403
+ def authorize_security_group_named_ingress(name, owner, group)
404
+ edit_security_group( :authorize, name, :source_group_owner => owner, :source_group => group)
405
+ end
406
+
407
+ # Revoke named ingress for security group.
408
+ #
409
+ # ec2.revoke_security_group_named_ingress('my_awesome_group', aws_user_id, 'another_group_name') #=> true
410
+ #
411
+ def revoke_security_group_named_ingress(name, owner, group)
412
+ edit_security_group( :revoke, name, :source_group_owner => owner, :source_group => group)
413
+ end
414
+
415
+ # Add permission to a security group. Returns +true+ or an exception. +protocol+ is one of :'tcp'|'udp'|'icmp'.
416
+ #
417
+ # ec2.authorize_security_group_IP_ingress('my_awesome_group', 80, 82, 'udp', '192.168.1.0/8') #=> true
418
+ # ec2.authorize_security_group_IP_ingress('my_awesome_group', -1, -1, 'icmp') #=> true
419
+ #
420
+ def authorize_security_group_IP_ingress(name, from_port, to_port, protocol='tcp', cidr_ip='0.0.0.0/0')
421
+ edit_security_group( :authorize, name, :from_port => from_port, :to_port => to_port, :protocol => protocol, :cidr_ip => cidr_ip )
422
+ end
423
+
424
+ # Remove permission from a security group. Returns +true+ or an exception. +protocol+ is one of :'tcp'|'udp'|'icmp' ('tcp' is default).
425
+ #
426
+ # ec2.revoke_security_group_IP_ingress('my_awesome_group', 80, 82, 'udp', '192.168.1.0/8') #=> true
427
+ #
428
+ def revoke_security_group_IP_ingress(name, from_port, to_port, protocol='tcp', cidr_ip='0.0.0.0/0')
429
+ edit_security_group( :revoke, name, :from_port => from_port, :to_port => to_port, :protocol => protocol, :cidr_ip => cidr_ip )
430
+ end
431
+
432
+ #-----------------------------------------------------------------
433
+ # PARSERS: Security Groups
434
+ #-----------------------------------------------------------------
435
+
436
+ class QEc2CreateSecurityGroupsParser < RightAWSParser #:nodoc:
437
+ def tagend(name)
438
+ case name
439
+ when 'groupId' then @result[:group_id] = @text
440
+ when 'return' then @result[:return] = @text == 'true'
441
+ end
442
+ end
443
+ def reset
444
+ @result = {}
445
+ end
446
+ end
447
+
448
+ class QEc2DescribeSecurityGroupsParser < RightAWSParser #:nodoc:
449
+ def tagstart(name, attributes)
450
+ if name == 'item'
451
+ case full_tag_name
452
+ when %r{securityGroupInfo/item$} then @item = { :ip_permissions => [] }
453
+ when %r{ipPermissions/item$} then @ip_perm = { :groups => [], :ip_ranges => [], :direction => :ingress }
454
+ when %r{ipPermissionsEgress/item$} then @ip_perm = { :groups => [], :ip_ranges => [], :direction => :egress }
455
+ when %r{ipPermissions(Egress)?/item/groups/item$} then @group = {}
456
+ end
457
+ end
458
+ end
459
+ def tagend(name)
460
+ case name
461
+ when 'ownerId' then @item[:owner_id] = @text
462
+ when 'groupDescription' then @item[:group_description] = @text
463
+ when 'vpcId' then @item[:vpc_id] = @text
464
+ else
465
+ case full_tag_name
466
+ when %r{securityGroupInfo/item/groupName$} then @item[:group_name] = @text
467
+ when %r{securityGroupInfo/item/groupId$} then @item[:group_id] = @text
468
+ # ipPermission[Egress]
469
+ when %r{ipPermissions(Egress)?/item/ipProtocol$} then @ip_perm[:ip_protocol] = @text
470
+ when %r{ipPermissions(Egress)?/item/fromPort$} then @ip_perm[:from_port] = @text
471
+ when %r{ipPermissions(Egress)?/item/toPort$} then @ip_perm[:to_port] = @text
472
+ when %r{ipPermissions(Egress)?/item/ipRanges/item/cidrIp$} then @ip_perm[:ip_ranges] << @text
473
+ # ipPermissions[Egress]/Groups
474
+ when %r{ipPermissions(Egress)?/item/groups/item/groupName$} then @group[:group_name] = @text
475
+ when %r{ipPermissions(Egress)?/item/groups/item/groupId$} then @group[:group_id] = @text
476
+ when %r{ipPermissions(Egress)?/item/groups/item/userId$} then @group[:user_id] = @text
477
+ # Sets
478
+ when %r{ipPermissions(Egress)?/item/groups/item$} then @ip_perm[:groups] << @group
479
+ when %r{ipPermissions/item$} then @item[:ip_permissions] << @ip_perm
480
+ when %r{ipPermissionsEgress/item$} then @item[:ip_permissions] << @ip_perm
481
+ when %r{securityGroupInfo/item$} then @result << @item
482
+ end
483
+ end
484
+ end
485
+ def reset
486
+ @result = []
487
+ end
488
+ end
489
+
490
+ end
491
+ end