vagrant-box-s3 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +17 -16
- data/lib/vagrant-box-s3/downloader.rb +11 -34
- data/lib/vagrant-box-s3/urls.rb +70 -0
- data/lib/vagrant-box-s3/utils.rb +20 -61
- data/lib/vagrant-box-s3/version.rb +1 -1
- data/lib/vagrant-box-s3.rb +5 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9a2bc5d3cadb3cdcb261f206f5ca46fe0b210ef3514bcc9072176d85222f9e24
|
4
|
+
data.tar.gz: 9044ae220e16806ba95a48c94bf147bf5df4b418cd8181bf1a9cab7ac04219ef
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 24cf532f08f551c08dec67c11b94672bf660d73b985d2d4b35ab35e6413c6d9b6ff709b15088192e7fd006cbd0c76e11dbb0bea8f5f9dafd914e411eeaa9f9e3
|
7
|
+
data.tar.gz: a15234a433f1aa2d3f2968ad98c2fc9fb29e11d269361cbd6fc2fbeb10c4fdaaa4dd47d7e4a395fc6fcec5bbb24a4dec184493bc43e4781594a8a8b4e4ca71cf
|
data/README.md
CHANGED
@@ -11,8 +11,9 @@ Use Vagrant boxes stored in Amazon S3 private buckets.
|
|
11
11
|
|
12
12
|
## Features
|
13
13
|
|
14
|
-
This plugin works
|
15
|
-
|
14
|
+
This plugin works using the `authenticate_box_url` hook to replace S3 URLs with presigned URLs and monkey
|
15
|
+
patching `Vagrant::Util::Downloader`, extending the core Downloader class in Vagrant to override the `head` method
|
16
|
+
used when fetching box metadata URLs from S3.
|
16
17
|
|
17
18
|
## Installation
|
18
19
|
|
@@ -55,22 +56,22 @@ You can also use your credentials file to create a profile. Select the appropria
|
|
55
56
|
|
56
57
|
You can use any valid HTTP(S) URL for your box URL:
|
57
58
|
|
58
|
-
####
|
59
|
-
|
60
|
-
Specify the bucket name in the path of the URL. AWS has deprecated path-style URLs, but they might still be seen or used in legacy systems.
|
59
|
+
#### Virtual-Hosted-Style URLs
|
61
60
|
|
62
|
-
-
|
63
|
-
- Example: https://s3.eu-west-1.amazonaws.com/mybucket/mybox.box
|
61
|
+
Virtual-hosted-style URLs use the bucket name as a subdomain. This is the recommended and most commonly used format.
|
64
62
|
|
63
|
+
| Format | Example |
|
64
|
+
|----------------------------------------------|------------------------------------------------------------|
|
65
|
+
| `https://BUCKET.s3.REGION.amazonaws.com/KEY` | `https://mybucket.s3.eu-west-1.amazonaws.com/mybox.box` |
|
65
66
|
|
66
|
-
-
|
67
|
-
- Example: https://s3-eu-west-1.amazonaws.com/bucket-name/mybox.box
|
67
|
+
#### Path-Style URLs
|
68
68
|
|
69
|
-
|
70
|
-
Virtual-hosted-style URLs use the bucket name as a subdomain. This is the recommended and most commonly used format.
|
69
|
+
Specify the bucket name in the path of the URL. AWS has deprecated path-style URLs, but they might still be seen or used in legacy systems.
|
71
70
|
|
72
|
-
|
73
|
-
|
71
|
+
| Format | Example |
|
72
|
+
|----------------------------------------------|------------------------------------------------------------|
|
73
|
+
| `https://s3.REGION.amazonaws.com/BUCKET/KEY` | `https://s3.eu-west-1.amazonaws.com/mybucket/mybox.box` |
|
74
|
+
| `https://s3-REGION.amazonaws.com/BUCKET/KEY` | `https://s3-eu-west-1.amazonaws.com/bucket-name/mybox.box` |
|
74
75
|
|
75
76
|
### IAM configuration
|
76
77
|
|
@@ -123,15 +124,15 @@ Update the current version in `lib/vagrant-box-s3/version.rb`.
|
|
123
124
|
|
124
125
|
### Dev build and test
|
125
126
|
|
126
|
-
To build the plugin, use `rake build`, this will create a file with the current version number, e.g. `pkg/vagrant-box-s3-
|
127
|
+
To build the plugin, use `rake build`, this will create a file with the current version number, e.g. `pkg/vagrant-box-s3-{VERSION}.gem`.
|
127
128
|
|
128
129
|
Remove the old version:
|
129
130
|
|
130
|
-
vagrant plugin uninstall vagrant-box-s3
|
131
|
+
vagrant plugin uninstall vagrant-box-s3 --local
|
131
132
|
|
132
133
|
Testing the plugin requires installing into vagrant from the build:
|
133
134
|
|
134
|
-
vagrant plugin install ../vagrant-box-s3/pkg/vagrant-box-s3-
|
135
|
+
vagrant plugin install ../vagrant-box-s3/pkg/vagrant-box-s3-{VERSION}.gem
|
135
136
|
|
136
137
|
Then running a command that will trigger box URL related actions, such as `vagrant up`, `vagrant box update` etc. with the `--debug` flag.
|
137
138
|
|
@@ -4,47 +4,24 @@ module Vagrant
|
|
4
4
|
module Util
|
5
5
|
class Downloader
|
6
6
|
|
7
|
-
|
8
|
-
# Get URL from options, which is the last option in the list.
|
9
|
-
url = options.last
|
7
|
+
alias_method :original_head, :head
|
10
8
|
|
11
|
-
|
12
|
-
|
9
|
+
def head
|
10
|
+
if ::VagrantPlugins::BoxS3::Utils.is_s3_manifest(@source)
|
11
|
+
options, subprocess_options = self.options
|
12
|
+
options.unshift("-i")
|
13
|
+
options << @source
|
13
14
|
|
14
|
-
|
15
|
-
|
15
|
+
@logger.info("HEAD (Override): #{@source}")
|
16
|
+
result = execute_curl(options, subprocess_options)
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
# Call original execute_curl (aliased).
|
21
|
-
execute_curl_without_aws_auth(options, subprocess_options, &data_proc)
|
22
|
-
|
23
|
-
rescue Aws::Errors::MissingCredentialsError, Aws::Sigv4::Errors::MissingCredentialsError => e
|
24
|
-
message = "Missing AWS credentials: #{e.message}"
|
25
|
-
@logger.error(message) if defined?(@logger)
|
26
|
-
raise Errors::DownloaderError, message: message
|
27
|
-
rescue Aws::S3::Errors::Forbidden => e
|
28
|
-
message = "403 Forbidden: #{e.message}"
|
29
|
-
raise Errors::DownloaderError, message: message
|
30
|
-
rescue => e
|
31
|
-
raise Errors::DownloaderError, message: e
|
32
|
-
end
|
33
|
-
|
34
|
-
def execute_curl_with_aws_auth(options, subprocess_options, &data_proc)
|
35
|
-
options = options.dup
|
36
|
-
url = options.find { |o| o =~ /^http/ }
|
37
|
-
|
38
|
-
if url && url.include?('amazonaws.com')
|
39
|
-
aws_auth_download(options, subprocess_options, &data_proc)
|
18
|
+
headers, _body = result.stdout.split("\r\n\r\n", 2)
|
19
|
+
headers
|
40
20
|
else
|
41
|
-
|
21
|
+
original_head
|
42
22
|
end
|
43
23
|
end
|
44
24
|
|
45
|
-
alias execute_curl_without_aws_auth execute_curl
|
46
|
-
alias execute_curl execute_curl_with_aws_auth
|
47
|
-
|
48
25
|
end
|
49
26
|
end
|
50
27
|
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'log4r'
|
2
|
+
require 'vagrant-box-s3/utils'
|
3
|
+
|
4
|
+
module VagrantPlugins
|
5
|
+
module BoxS3
|
6
|
+
class Urls
|
7
|
+
def initialize(app, env)
|
8
|
+
@app = app
|
9
|
+
@logger = Log4r::Logger.new('vagrant::plugins::box_s3')
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(env)
|
13
|
+
# Assume 'env[:box_urls]' contains the original URLs that need authentication
|
14
|
+
original_urls = env[:box_urls]
|
15
|
+
|
16
|
+
# Your logic to authenticate the URLs goes here
|
17
|
+
# This is just an example, replace it with your actual authentication mechanism
|
18
|
+
authenticated_urls = original_urls.map do |url|
|
19
|
+
presign_url(url)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Ensure the authenticated URLs are set back in the environment
|
23
|
+
env[:box_urls] = authenticated_urls
|
24
|
+
|
25
|
+
# Continue the middleware chain
|
26
|
+
@app.call(env)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
# Pre-sign an s3 URL, with given method.
|
32
|
+
def presign_url(url)
|
33
|
+
|
34
|
+
# Check if the URL is an S3 URL.
|
35
|
+
if !Utils.is_s3_url(url)
|
36
|
+
@logger.info("Skipping presigner for #{url}")
|
37
|
+
return url
|
38
|
+
end
|
39
|
+
|
40
|
+
@logger.info("Discovered S3 URL: #{url}")
|
41
|
+
|
42
|
+
region, bucket, key = Utils.parse_s3_url(url)
|
43
|
+
|
44
|
+
profile = ENV['AWS_PROFILE']
|
45
|
+
|
46
|
+
@logger.debug("Region: #{region}")
|
47
|
+
@logger.debug("Bucket: #{bucket}")
|
48
|
+
@logger.debug("Key: #{key}")
|
49
|
+
@logger.debug("Profile: #{profile}")
|
50
|
+
|
51
|
+
client = Aws::S3::Client.new(
|
52
|
+
profile: profile,
|
53
|
+
region: region
|
54
|
+
)
|
55
|
+
presigner = Aws::S3::Presigner.new(client: client)
|
56
|
+
|
57
|
+
presigned_url = presigner.presigned_url(
|
58
|
+
:get_object,
|
59
|
+
bucket: bucket,
|
60
|
+
key: key,
|
61
|
+
expires_in: 3600
|
62
|
+
).to_s
|
63
|
+
|
64
|
+
@logger.debug("Pre-signed URL: #{presigned_url}")
|
65
|
+
|
66
|
+
return presigned_url
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/lib/vagrant-box-s3/utils.rb
CHANGED
@@ -7,13 +7,32 @@ module VagrantPlugins
|
|
7
7
|
|
8
8
|
# Match host style URLs, e.g.
|
9
9
|
# https://bucket-name.s3.Region.amazonaws.com/key-name
|
10
|
-
|
10
|
+
# https://bucket-name.s3-Region.amazonaws.com/key-name
|
11
|
+
S3_URL_HOST_REGEX = %r{^https?://([\w\-\.]+)\.s3[-\.]([\w\-]+)\.amazonaws\.com/([^?]+)}
|
11
12
|
|
12
13
|
# Match path style URLs e.g.
|
13
14
|
# https://s3.Region.amazonaws.com/bucket-name/key-name
|
14
15
|
# https://s3-Region.amazonaws.com/bucket-name/keyname
|
15
16
|
S3_URL_PATH_REGEX = %r{^https?://s3[-\.]([\w\-]+)\.amazonaws\.com/([^/]+)/([^?]+)}
|
16
17
|
|
18
|
+
# Check if URL matches S3 URLs.
|
19
|
+
def self.is_s3_url(url)
|
20
|
+
# Check if the URL matches either the host style or path style S3 URL
|
21
|
+
matches_host_style = !!(url =~ S3_URL_HOST_REGEX)
|
22
|
+
matches_path_style = !!(url =~ S3_URL_PATH_REGEX)
|
23
|
+
|
24
|
+
# Return true if either match is found, false otherwise
|
25
|
+
matches_host_style || matches_path_style
|
26
|
+
end
|
27
|
+
|
28
|
+
# Check if the URL is an S3 URL and the filename is 'manifest.json'
|
29
|
+
def self.is_s3_manifest(url)
|
30
|
+
uri = URI.parse(url)
|
31
|
+
filename = File.basename(uri.path)
|
32
|
+
|
33
|
+
return is_s3_url(url) && filename == 'manifest.json'
|
34
|
+
end
|
35
|
+
|
17
36
|
# Parse an s3 URL.
|
18
37
|
def self.parse_s3_url(url)
|
19
38
|
region = bucket = key = nil
|
@@ -32,66 +51,6 @@ module VagrantPlugins
|
|
32
51
|
return region, bucket, key
|
33
52
|
end
|
34
53
|
|
35
|
-
# Remove presigned URL params from box URL.
|
36
|
-
# We do this as URLs can be cached and do not want to want
|
37
|
-
# to include previously presigned URL parameters.
|
38
|
-
def self.remove_presigned_params(url)
|
39
|
-
# Parse the URL
|
40
|
-
uri = URI.parse(url)
|
41
|
-
|
42
|
-
# Split the query string into parameters
|
43
|
-
query_params = URI.decode_www_form(uri.query || '').to_h
|
44
|
-
|
45
|
-
# Remove any parameters that start with 'X-Amz-'
|
46
|
-
query_params.reject! { |k, _| k.start_with?('X-Amz-') }
|
47
|
-
|
48
|
-
# Check if there are any query parameters left
|
49
|
-
if query_params.empty?
|
50
|
-
# If no query parameters left, set uri.query to nil to remove the '?'
|
51
|
-
uri.query = nil
|
52
|
-
else
|
53
|
-
# Reconstruct the query string without AWS presigned parameters
|
54
|
-
uri.query = URI.encode_www_form(query_params)
|
55
|
-
end
|
56
|
-
|
57
|
-
return uri.to_s
|
58
|
-
end
|
59
|
-
|
60
|
-
# Pre-sign an s3 URL, with given method.
|
61
|
-
def self.presign_url(method, url, logger)
|
62
|
-
|
63
|
-
url = remove_presigned_params(url)
|
64
|
-
|
65
|
-
logger.info("BoxS3: Generating signed URL for #{method.upcase}")
|
66
|
-
logger.info("BoxS3: Discovered S3 URL: #{url}")
|
67
|
-
|
68
|
-
region, bucket, key = parse_s3_url(url)
|
69
|
-
|
70
|
-
profile = ENV['AWS_PROFILE']
|
71
|
-
|
72
|
-
logger.debug("BoxS3: Region: #{region}")
|
73
|
-
logger.debug("BoxS3: Bucket: #{bucket}")
|
74
|
-
logger.debug("BoxS3: Key: #{key}")
|
75
|
-
logger.debug("BoxS3: Profile: #{profile}")
|
76
|
-
|
77
|
-
client = Aws::S3::Client.new(
|
78
|
-
profile: profile,
|
79
|
-
region: region
|
80
|
-
)
|
81
|
-
presigner = Aws::S3::Presigner.new(client: client)
|
82
|
-
|
83
|
-
presigned_url = presigner.presigned_url(
|
84
|
-
method,
|
85
|
-
bucket: bucket,
|
86
|
-
key: key,
|
87
|
-
expires_in: 3600
|
88
|
-
).to_s
|
89
|
-
|
90
|
-
logger.debug("BoxS3: Pre-signed URL: #{presigned_url}")
|
91
|
-
|
92
|
-
return presigned_url
|
93
|
-
end
|
94
|
-
|
95
54
|
end
|
96
55
|
end
|
97
56
|
end
|
data/lib/vagrant-box-s3.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'vagrant'
|
2
|
+
require 'vagrant-box-s3/urls'
|
2
3
|
|
3
4
|
module VagrantPlugins
|
4
5
|
module BoxS3
|
@@ -9,6 +10,10 @@ module VagrantPlugins
|
|
9
10
|
require_relative 'vagrant-box-s3/downloader'
|
10
11
|
end
|
11
12
|
|
13
|
+
action_hook(:vagrant_box_s3_url, :authenticate_box_url) do |hook|
|
14
|
+
hook.prepend(Urls)
|
15
|
+
end
|
16
|
+
|
12
17
|
end
|
13
18
|
end
|
14
19
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vagrant-box-s3
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Steve Whiteley
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-10-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-sdk-s3
|
@@ -63,6 +63,7 @@ files:
|
|
63
63
|
- README.md
|
64
64
|
- lib/vagrant-box-s3.rb
|
65
65
|
- lib/vagrant-box-s3/downloader.rb
|
66
|
+
- lib/vagrant-box-s3/urls.rb
|
66
67
|
- lib/vagrant-box-s3/utils.rb
|
67
68
|
- lib/vagrant-box-s3/version.rb
|
68
69
|
homepage: https://github.com/memiah/vagrant-box-s3
|