configure-s3-website 1.1.2 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +35 -0
- data/changelog.md +4 -0
- data/features/cassettes/cucumber_tags/redirects.yml +203 -0
- data/features/configure_bucket.feature +15 -0
- data/features/support/sample_config_files/redirects.yml +10 -0
- data/features/support/vcr.rb +1 -0
- data/lib/configure-s3-website/config_source/config_source.rb +3 -0
- data/lib/configure-s3-website/config_source/file_config_source.rb +4 -0
- data/lib/configure-s3-website/s3_client.rb +52 -0
- data/lib/configure-s3-website/version.rb +1 -1
- metadata +7 -3
data/README.md
CHANGED
@@ -44,6 +44,29 @@ configuration file a row like this:
|
|
44
44
|
The valid *s3_endpoint* values consist of the [S3 location constraint
|
45
45
|
values](http://docs.amazonwebservices.com/general/latest/gr/rande.html#s3_region).
|
46
46
|
|
47
|
+
### Configuring redirects
|
48
|
+
|
49
|
+
You can configure redirects on your S3 website by adding `routing_rules` into
|
50
|
+
the config file.
|
51
|
+
|
52
|
+
Here is an example:
|
53
|
+
|
54
|
+
````yaml
|
55
|
+
routing_rules:
|
56
|
+
- condition:
|
57
|
+
key_prefix_equals: blog/some_path
|
58
|
+
redirect:
|
59
|
+
host_name: blog.example.com
|
60
|
+
replace_key_prefix_with: some_new_path/
|
61
|
+
http_redirect_code: 301
|
62
|
+
````
|
63
|
+
|
64
|
+
You can use any routing rule property that the [REST
|
65
|
+
API](http://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketPUTwebsite.html)
|
66
|
+
supports. All you have to do is to replace the uppercase letter in AWS XML with
|
67
|
+
an underscore and an undercase version of the same letter. For example,
|
68
|
+
`KeyPrefixEquals` becomes `key_prefix_equals` in the config file.
|
69
|
+
|
47
70
|
## How does `configure-s3-website` work?
|
48
71
|
|
49
72
|
It calls the [PUT Bucket
|
@@ -79,10 +102,22 @@ API with the following JSON:
|
|
79
102
|
}
|
80
103
|
```
|
81
104
|
|
105
|
+
If you define `routing_rules` in the config file, `configure-s3-website` will
|
106
|
+
make an additional call to the AWS API.
|
107
|
+
|
82
108
|
## Development
|
83
109
|
|
84
110
|
* This project uses [Semantic Versioning](http://semver.org)
|
85
111
|
|
112
|
+
## Credit
|
113
|
+
|
114
|
+
Created by Lauri Lehmijoki.
|
115
|
+
|
116
|
+
Big thanks to the following contributors (in alphabetical order):
|
117
|
+
|
118
|
+
* SlawD
|
119
|
+
* Steve Schwartz
|
120
|
+
|
86
121
|
## License
|
87
122
|
|
88
123
|
See the file LICENSE.
|
data/changelog.md
CHANGED
@@ -0,0 +1,203 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: put
|
5
|
+
uri: https://s3.amazonaws.com/website-with-redirects/?website
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ! "\n <WebsiteConfiguration xmlns='http://s3.amazonaws.com/doc/2006-03-01/'>\n
|
9
|
+
\ <IndexDocument>\n <Suffix>index.html</Suffix>\n </IndexDocument>\n
|
10
|
+
\ <ErrorDocument>\n <Key>error.html</Key>\n </ErrorDocument>\n
|
11
|
+
\ </WebsiteConfiguration>\n "
|
12
|
+
headers:
|
13
|
+
Date:
|
14
|
+
- Sun, 05 May 2013 17:15:13 EEST
|
15
|
+
Content-Type:
|
16
|
+
- ''
|
17
|
+
Content-Length:
|
18
|
+
- '298'
|
19
|
+
Authorization:
|
20
|
+
- AWS
|
21
|
+
response:
|
22
|
+
status:
|
23
|
+
code: 404
|
24
|
+
message: Not Found
|
25
|
+
headers:
|
26
|
+
X-Amz-Request-Id:
|
27
|
+
- 2DFD9AF9459D6EBA
|
28
|
+
X-Amz-Id-2:
|
29
|
+
- xuu
|
30
|
+
Content-Type:
|
31
|
+
- application/xml
|
32
|
+
Transfer-Encoding:
|
33
|
+
- chunked
|
34
|
+
Date:
|
35
|
+
- Sun, 05 May 2013 14:15:16 GMT
|
36
|
+
Connection:
|
37
|
+
- close
|
38
|
+
Server:
|
39
|
+
- AmazonS3
|
40
|
+
body:
|
41
|
+
encoding: US-ASCII
|
42
|
+
string: ! '<?xml version="1.0" encoding="UTF-8"?>
|
43
|
+
|
44
|
+
<Error><Code>NoSuchBucket</Code><Message>The specified bucket does not exist</Message><BucketName>website-with-redirects</BucketName><RequestId>2DFD9AF9459D6EBA</RequestId><HostId>+mKBZUngt5PWBeABkXaUZFengM23XP683j5NXVkvIlDnfkfsYdU6jJuoRMJaQZF/</HostId></Error>'
|
45
|
+
http_version:
|
46
|
+
recorded_at: Sun, 05 May 2013 14:15:14 GMT
|
47
|
+
- request:
|
48
|
+
method: put
|
49
|
+
uri: https://s3.amazonaws.com/website-with-redirects
|
50
|
+
body:
|
51
|
+
encoding: US-ASCII
|
52
|
+
string: ''
|
53
|
+
headers:
|
54
|
+
Date:
|
55
|
+
- Sun, 05 May 2013 17:15:14 EEST
|
56
|
+
Content-Type:
|
57
|
+
- ''
|
58
|
+
Content-Length:
|
59
|
+
- '0'
|
60
|
+
Authorization:
|
61
|
+
- AWS
|
62
|
+
response:
|
63
|
+
status:
|
64
|
+
code: 200
|
65
|
+
message: OK
|
66
|
+
headers:
|
67
|
+
X-Amz-Id-2:
|
68
|
+
- Hn9luS/t3JpOkwnXRnyVOJ+HlYVS1PNZ//XVrAiZjP95xY4Aot5X0X8S+rQ8eDwp
|
69
|
+
X-Amz-Request-Id:
|
70
|
+
- 60B4854F860963D6
|
71
|
+
Date:
|
72
|
+
- Sun, 05 May 2013 14:15:18 GMT
|
73
|
+
Location:
|
74
|
+
- /website-with-redirects
|
75
|
+
Content-Length:
|
76
|
+
- '0'
|
77
|
+
Server:
|
78
|
+
- AmazonS3
|
79
|
+
body:
|
80
|
+
encoding: US-ASCII
|
81
|
+
string: ''
|
82
|
+
http_version:
|
83
|
+
recorded_at: Sun, 05 May 2013 14:15:15 GMT
|
84
|
+
- request:
|
85
|
+
method: put
|
86
|
+
uri: https://s3.amazonaws.com/website-with-redirects/?website
|
87
|
+
body:
|
88
|
+
encoding: US-ASCII
|
89
|
+
string: ! "\n <WebsiteConfiguration xmlns='http://s3.amazonaws.com/doc/2006-03-01/'>\n
|
90
|
+
\ <IndexDocument>\n <Suffix>index.html</Suffix>\n </IndexDocument>\n
|
91
|
+
\ <ErrorDocument>\n <Key>error.html</Key>\n </ErrorDocument>\n
|
92
|
+
\ </WebsiteConfiguration>\n "
|
93
|
+
headers:
|
94
|
+
Date:
|
95
|
+
- Sun, 05 May 2013 17:15:15 EEST
|
96
|
+
Content-Type:
|
97
|
+
- ''
|
98
|
+
Content-Length:
|
99
|
+
- '298'
|
100
|
+
Authorization:
|
101
|
+
- AWS
|
102
|
+
response:
|
103
|
+
status:
|
104
|
+
code: 200
|
105
|
+
message: OK
|
106
|
+
headers:
|
107
|
+
X-Amz-Id-2:
|
108
|
+
- bBCMImUYwikvIu5M1aFYsEyouPNM3xQoLsNpKeXjSVbe3ZJJZLUdR0OMF+3zFX+y
|
109
|
+
X-Amz-Request-Id:
|
110
|
+
- 2E4F04F9CB9F14F9
|
111
|
+
Date:
|
112
|
+
- Sun, 05 May 2013 14:15:19 GMT
|
113
|
+
Content-Length:
|
114
|
+
- '0'
|
115
|
+
Server:
|
116
|
+
- AmazonS3
|
117
|
+
body:
|
118
|
+
encoding: US-ASCII
|
119
|
+
string: ''
|
120
|
+
http_version:
|
121
|
+
recorded_at: Sun, 05 May 2013 14:15:16 GMT
|
122
|
+
- request:
|
123
|
+
method: put
|
124
|
+
uri: https://s3.amazonaws.com/website-with-redirects/?policy
|
125
|
+
body:
|
126
|
+
encoding: US-ASCII
|
127
|
+
string: ! "{\n \"Version\":\"2008-10-17\",\n \"Statement\":[{\n
|
128
|
+
\ \"Sid\":\"PublicReadForGetBucketObjects\",\n \"Effect\":\"Allow\",\n
|
129
|
+
\ \"Principal\": { \"AWS\": \"*\" },\n \"Action\":[\"s3:GetObject\"],\n
|
130
|
+
\ \"Resource\":[\"arn:aws:s3:::website-with-redirects/*\"]\n }]\n
|
131
|
+
\ }"
|
132
|
+
headers:
|
133
|
+
Date:
|
134
|
+
- Sun, 05 May 2013 17:15:16 EEST
|
135
|
+
Content-Type:
|
136
|
+
- ''
|
137
|
+
Content-Length:
|
138
|
+
- '291'
|
139
|
+
Authorization:
|
140
|
+
- AWS
|
141
|
+
response:
|
142
|
+
status:
|
143
|
+
code: 204
|
144
|
+
message: No Content
|
145
|
+
headers:
|
146
|
+
X-Amz-Id-2:
|
147
|
+
- ijsq/+jpLhfwLnUJF2xKj5x+1x9YhapYBVk38FDb7BYQ2vRsiFUydmrYD8PIfr0b
|
148
|
+
X-Amz-Request-Id:
|
149
|
+
- EA0FDFDE47845326
|
150
|
+
Date:
|
151
|
+
- Sun, 05 May 2013 14:15:19 GMT
|
152
|
+
Server:
|
153
|
+
- AmazonS3
|
154
|
+
body:
|
155
|
+
encoding: US-ASCII
|
156
|
+
string: ''
|
157
|
+
http_version:
|
158
|
+
recorded_at: Sun, 05 May 2013 14:15:17 GMT
|
159
|
+
- request:
|
160
|
+
method: put
|
161
|
+
uri: https://s3.amazonaws.com/website-with-redirects/?website
|
162
|
+
body:
|
163
|
+
encoding: US-ASCII
|
164
|
+
string: ! "\n <WebsiteConfiguration xmlns='http://s3.amazonaws.com/doc/2006-03-01/'>\n
|
165
|
+
\ <IndexDocument>\n <Suffix>index.html</Suffix>\n </IndexDocument>\n
|
166
|
+
\ <ErrorDocument>\n <Key>error.html</Key>\n </ErrorDocument>\n
|
167
|
+
\ <RoutingRules>\n \n <RoutingRule>\n \n
|
168
|
+
\ <Condition>\n <KeyPrefixEquals>blog/some_path</KeyPrefixEquals></Condition>\n
|
169
|
+
\ <Redirect>\n <HostName>blog.example.com</HostName>\n
|
170
|
+
\ <ReplaceKeyPrefixWith>some_new_path/</ReplaceKeyPrefixWith>\n
|
171
|
+
\ <HttpRedirectCode>301</HttpRedirectCode></Redirect>\n </RoutingRule>\n
|
172
|
+
\ \n </RoutingRules>\n </WebsiteConfiguration>\n
|
173
|
+
\ "
|
174
|
+
headers:
|
175
|
+
Date:
|
176
|
+
- Sun, 05 May 2013 17:15:17 EEST
|
177
|
+
Content-Type:
|
178
|
+
- ''
|
179
|
+
Content-Length:
|
180
|
+
- '786'
|
181
|
+
Authorization:
|
182
|
+
- AWS
|
183
|
+
response:
|
184
|
+
status:
|
185
|
+
code: 200
|
186
|
+
message: OK
|
187
|
+
headers:
|
188
|
+
X-Amz-Id-2:
|
189
|
+
- aAt1wLoQJwkJHLmF8wHSX8fbfyVVacGEv3PO/Cx6y4kDkEqzp2v33l99ZWBH4dVt
|
190
|
+
X-Amz-Request-Id:
|
191
|
+
- 1C1A5EB5ABB7198A
|
192
|
+
Date:
|
193
|
+
- Sun, 05 May 2013 14:15:20 GMT
|
194
|
+
Content-Length:
|
195
|
+
- '0'
|
196
|
+
Server:
|
197
|
+
- AmazonS3
|
198
|
+
body:
|
199
|
+
encoding: US-ASCII
|
200
|
+
string: ''
|
201
|
+
http_version:
|
202
|
+
recorded_at: Sun, 05 May 2013 14:15:18 GMT
|
203
|
+
recorded_with: VCR 2.3.0
|
@@ -9,6 +9,7 @@ Feature: configure an S3 bucket to function as a website
|
|
9
9
|
Created bucket name-of-a-new-bucket in the US Standard Region
|
10
10
|
Bucket name-of-a-new-bucket now functions as a website
|
11
11
|
Bucket name-of-a-new-bucket is now readable to the whole world
|
12
|
+
No redirects to configure for name-of-a-new-bucket bucket
|
12
13
|
|
13
14
|
"""
|
14
15
|
|
@@ -38,5 +39,19 @@ Feature: configure an S3 bucket to function as a website
|
|
38
39
|
"""
|
39
40
|
Bucket name-of-an-existing-bucket now functions as a website
|
40
41
|
Bucket name-of-an-existing-bucket is now readable to the whole world
|
42
|
+
No redirects to configure for name-of-an-existing-bucket bucket
|
43
|
+
|
44
|
+
"""
|
45
|
+
|
46
|
+
@redirects
|
47
|
+
Scenario: The user wants to configure redirects for the S3 website
|
48
|
+
Given my config file is in "features/support/sample_config_files/redirects.yml"
|
49
|
+
When I run the configure-s3-website command
|
50
|
+
Then the output should be
|
51
|
+
"""
|
52
|
+
Created bucket website-with-redirects in the US Standard Region
|
53
|
+
Bucket website-with-redirects now functions as a website
|
54
|
+
Bucket website-with-redirects is now readable to the whole world
|
55
|
+
1 redirects configured for website-with-redirects bucket
|
41
56
|
|
42
57
|
"""
|
data/features/support/vcr.rb
CHANGED
@@ -10,6 +10,7 @@ module ConfigureS3Website
|
|
10
10
|
begin
|
11
11
|
enable_website_configuration(config_source)
|
12
12
|
make_bucket_readable_to_everyone(config_source)
|
13
|
+
configure_bucket_redirects(config_source)
|
13
14
|
rescue NoSuchBucketError
|
14
15
|
create_bucket(config_source)
|
15
16
|
retry
|
@@ -58,6 +59,45 @@ module ConfigureS3Website
|
|
58
59
|
puts "Bucket #{config_source.s3_bucket_name} is now readable to the whole world"
|
59
60
|
end
|
60
61
|
|
62
|
+
def self.configure_bucket_redirects(config_source)
|
63
|
+
routing_rules = config_source.routing_rules
|
64
|
+
if routing_rules.is_a?(Array) && routing_rules.any?
|
65
|
+
body = %|
|
66
|
+
<WebsiteConfiguration xmlns='http://s3.amazonaws.com/doc/2006-03-01/'>
|
67
|
+
<IndexDocument>
|
68
|
+
<Suffix>index.html</Suffix>
|
69
|
+
</IndexDocument>
|
70
|
+
<ErrorDocument>
|
71
|
+
<Key>error.html</Key>
|
72
|
+
</ErrorDocument>
|
73
|
+
<RoutingRules>
|
74
|
+
|
|
75
|
+
routing_rules.each do |routing_rule|
|
76
|
+
body << %|
|
77
|
+
<RoutingRule>
|
78
|
+
|
|
79
|
+
body << self.hash_to_api_xml(routing_rule, 7)
|
80
|
+
body << %|
|
81
|
+
</RoutingRule>
|
82
|
+
|
|
83
|
+
end
|
84
|
+
body << %|
|
85
|
+
</RoutingRules>
|
86
|
+
</WebsiteConfiguration>
|
87
|
+
|
|
88
|
+
|
89
|
+
call_s3_api(
|
90
|
+
path = "/#{config_source.s3_bucket_name}/?website",
|
91
|
+
method = Net::HTTP::Put,
|
92
|
+
body = body,
|
93
|
+
config_source = config_source
|
94
|
+
)
|
95
|
+
puts "#{routing_rules.size} redirects configured for #{config_source.s3_bucket_name} bucket"
|
96
|
+
else
|
97
|
+
puts "No redirects to configure for #{config_source.s3_bucket_name} bucket"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
61
101
|
def self.create_bucket(config_source)
|
62
102
|
endpoint = Endpoint.new(config_source.s3_endpoint || '')
|
63
103
|
body = if endpoint.region == 'US Standard'
|
@@ -115,6 +155,18 @@ module ConfigureS3Website
|
|
115
155
|
hmac = OpenSSL::HMAC.digest(digest, config_source.s3_secret_access_key, can_string)
|
116
156
|
signature = Base64.encode64(hmac).strip
|
117
157
|
end
|
158
|
+
|
159
|
+
def self.hash_to_api_xml(hash={}, indent=0)
|
160
|
+
"".tap do |body|
|
161
|
+
hash.each do |key, value|
|
162
|
+
key_name = key.sub(/^[a-z\d]*/) { $&.capitalize }.gsub(/(?:_|(\/))([a-z\d]*)/) { $2.capitalize }
|
163
|
+
value = value.is_a?(Hash) ? self.hash_to_api_xml(value, indent+1) : value
|
164
|
+
body << "\n"
|
165
|
+
body << " " * indent * 2 # 2-space indentation formatting for xml
|
166
|
+
body << "<#{key_name}>#{value}</#{key_name}>"
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
118
170
|
end
|
119
171
|
end
|
120
172
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: configure-s3-website
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -142,11 +142,13 @@ files:
|
|
142
142
|
- features/cassettes/cucumber_tags/bucket-does-not-exist-in-tokyo.yml
|
143
143
|
- features/cassettes/cucumber_tags/bucket-does-not-exist.yml
|
144
144
|
- features/cassettes/cucumber_tags/bucket-exists.yml
|
145
|
+
- features/cassettes/cucumber_tags/redirects.yml
|
145
146
|
- features/config_file.feature
|
146
147
|
- features/configure_bucket.feature
|
147
148
|
- features/step_definitions/steps.rb
|
148
149
|
- features/support/env.rb
|
149
150
|
- features/support/sample_config_files/endpoint_tokyo.yml
|
151
|
+
- features/support/sample_config_files/redirects.yml
|
150
152
|
- features/support/sample_config_files/s3_config_with_existing_bucket.yml
|
151
153
|
- features/support/sample_config_files/s3_config_with_non-existing_bucket.yml
|
152
154
|
- features/support/vcr.rb
|
@@ -174,7 +176,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
174
176
|
version: '0'
|
175
177
|
segments:
|
176
178
|
- 0
|
177
|
-
hash:
|
179
|
+
hash: -1020516680573187683
|
178
180
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
179
181
|
none: false
|
180
182
|
requirements:
|
@@ -183,7 +185,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
183
185
|
version: '0'
|
184
186
|
segments:
|
185
187
|
- 0
|
186
|
-
hash:
|
188
|
+
hash: -1020516680573187683
|
187
189
|
requirements: []
|
188
190
|
rubyforge_project:
|
189
191
|
rubygems_version: 1.8.25
|
@@ -194,11 +196,13 @@ test_files:
|
|
194
196
|
- features/cassettes/cucumber_tags/bucket-does-not-exist-in-tokyo.yml
|
195
197
|
- features/cassettes/cucumber_tags/bucket-does-not-exist.yml
|
196
198
|
- features/cassettes/cucumber_tags/bucket-exists.yml
|
199
|
+
- features/cassettes/cucumber_tags/redirects.yml
|
197
200
|
- features/config_file.feature
|
198
201
|
- features/configure_bucket.feature
|
199
202
|
- features/step_definitions/steps.rb
|
200
203
|
- features/support/env.rb
|
201
204
|
- features/support/sample_config_files/endpoint_tokyo.yml
|
205
|
+
- features/support/sample_config_files/redirects.yml
|
202
206
|
- features/support/sample_config_files/s3_config_with_existing_bucket.yml
|
203
207
|
- features/support/sample_config_files/s3_config_with_non-existing_bucket.yml
|
204
208
|
- features/support/vcr.rb
|