vagrant-box-s3 0.1.2 → 0.1.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1643e17f9a726431fd44b34c7a87fe44e73070328d4c7bb261c2f12935c74834
4
- data.tar.gz: 2f1e60867c1016ab3e349873b293b69d30142db898301b912e16bfdf8cbd95ed
3
+ metadata.gz: 633fa8c2b30bc3482894cf4f2beb0a1b7d39a8b1cf74ec93d45fb24e93de8a13
4
+ data.tar.gz: 0aed7b6dc1a38fcf0d4542ef8e38fe42c797b688071340f9e898f59267c5450b
5
5
  SHA512:
6
- metadata.gz: 8d2c9963853012e0091c2c8fe8678c77d171c56d5662e28d670d728ee9d97e0123a25056bcb6d5cf9398983e0ad3541d3486cf635a00e4fb8af8ebeecfb9fe2c
7
- data.tar.gz: dff68c70631396e84fd058e488583fce8c56e70fbc735981575f018ad91e0b710222e7cf7de721ad0c69f16a1e56da94444429c1d13e5764adb2f53e6fd85a36
6
+ metadata.gz: 2e064c15560beb870b711bb46dce0b5af18c7c2922cf445ea5e78441e77b15befc20168e7330749f2caf5db32b2ccb527bc26446780ff8a07b3df2c5545208a5
7
+ data.tar.gz: cafd52ddd7b9b82fd0393acebaacb94d19c42cadf9fbcf8fec8e7f57c8510ac2a133e8fe775d7255d792818c78200aa869535cafac0abf96ac68912f96606849
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 by monkey patching `Vagrant::Util::Downloader`, extending the core Downloader class in Vagrant to
15
- override the `execute_curl` method to replace S3 box URLs with pre-signed S3 URLs.
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
 
@@ -40,14 +41,14 @@ You can also use your credentials file to create a profile. Select the appropria
40
41
 
41
42
  #### ~/.aws/credentials
42
43
 
43
- [vagrant-s3auth]
44
+ [vagrant-box-s3]
44
45
  aws_access_key_id = AKIA...
45
46
  aws_secret_access_key = ...
46
47
 
47
48
  #### Vagrantfile
48
49
 
49
50
  ENV.delete_if { |name| name.start_with?('AWS_') } # Filter out rogue env vars.
50
- ENV['AWS_PROFILE'] = 'vagrant-s3auth'
51
+ ENV['AWS_PROFILE'] = 'vagrant-box-s3'
51
52
 
52
53
  Vagrant.configure("2") { |config| ... }
53
54
 
@@ -60,10 +61,11 @@ You can use any valid HTTP(S) URL for your box URL:
60
61
  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.
61
62
 
62
63
  - Format: https://s3.Region.amazonaws.com/bucket-name/key-name
63
- Example: https://s3.eu-west-1.amazonaws.com/mybucket/mybox.box
64
+ - Example: https://s3.eu-west-1.amazonaws.com/mybucket/mybox.box
65
+
64
66
 
65
67
  - Format: https://s3-Region.amazonaws.com/bucket-name/keyname
66
- Example: https://s3-eu-west-1.amazonaws.com/bucket-name/mybox.box
68
+ - Example: https://s3-eu-west-1.amazonaws.com/bucket-name/mybox.box
67
69
 
68
70
  #### Virtual-Hosted-Style URLs
69
71
  Virtual-hosted-style URLs use the bucket name as a subdomain. This is the recommended and most commonly used format.
@@ -122,11 +124,15 @@ Update the current version in `lib/vagrant-box-s3/version.rb`.
122
124
 
123
125
  ### Dev build and test
124
126
 
125
- To build the plugin, use `rake build`, this will create a file with the current version number, e.g. `pkg/vagrant-box-s3-0.1.2.gem`.
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`.
128
+
129
+ Remove the old version:
130
+
131
+ vagrant plugin uninstall vagrant-box-s3 --local
126
132
 
127
133
  Testing the plugin requires installing into vagrant from the build:
128
134
 
129
- vagrant plugin install ../vagrant-box-s3/pkg/vagrant-box-s3-0.1.2.gem
135
+ vagrant plugin install ../vagrant-box-s3/pkg/vagrant-box-s3-{VERSION}.gem
130
136
 
131
137
  Then running a command that will trigger box URL related actions, such as `vagrant up`, `vagrant box update` etc. with the `--debug` flag.
132
138
 
@@ -4,43 +4,24 @@ module Vagrant
4
4
  module Util
5
5
  class Downloader
6
6
 
7
- def aws_auth_download(options, subprocess_options, &data_proc)
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
- # Determine method from curl command -I flag existence.
12
- method = options.any? { |o| o == '-I' } ? :head_object : :get_object
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
- # Generate pre-signed URL from S3 URL.
15
- presigned_url = VagrantPlugins::BoxS3::Utils.presign_url(method, url, @logger)
15
+ @logger.info("HEAD (Override): #{@source}")
16
+ result = execute_curl(options, subprocess_options)
16
17
 
17
- # Update URL in options.
18
- url.replace(presigned_url.to_s)
19
-
20
- # Call original execute_curl (aliased).
21
- execute_curl_without_aws_auth(options, subprocess_options, &data_proc)
22
-
23
- rescue Aws::S3::Errors::Forbidden => e
24
- message = "403 Forbidden: #{e.message}"
25
- raise Errors::DownloaderError, message: message
26
- rescue Seahorse::Client::NetworkingError => e
27
- raise Errors::DownloaderError, message: e
28
- end
29
-
30
- def execute_curl_with_aws_auth(options, subprocess_options, &data_proc)
31
- options = options.dup
32
- url = options.find { |o| o =~ /^http/ }
33
-
34
- if url && url.include?('amazonaws.com')
35
- aws_auth_download(options, subprocess_options, &data_proc)
18
+ headers, _body = result.stdout.split("\r\n\r\n", 2)
19
+ headers
36
20
  else
37
- execute_curl_without_aws_auth(options, subprocess_options, &data_proc)
21
+ original_head
38
22
  end
39
23
  end
40
24
 
41
- alias execute_curl_without_aws_auth execute_curl
42
- alias execute_curl execute_curl_with_aws_auth
43
-
44
25
  end
45
26
  end
46
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
@@ -7,23 +7,42 @@ module VagrantPlugins
7
7
 
8
8
  # Match host style URLs, e.g.
9
9
  # https://bucket-name.s3.Region.amazonaws.com/key-name
10
- S3_URL_HOST_REGEX = %r{^https?://([\w\-\.]+)\.s3\.([\w\-]+)\.amazonaws\.com/([^?]+)}
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
- def self.parse_s3_url(s3_url)
37
+ def self.parse_s3_url(url)
19
38
  region = bucket = key = nil
20
- if s3_url =~ S3_URL_HOST_REGEX
21
- match = S3_URL_HOST_REGEX.match(s3_url)
39
+ if url =~ S3_URL_HOST_REGEX
40
+ match = S3_URL_HOST_REGEX.match(url)
22
41
  region = match[2]
23
42
  bucket = match[1]
24
43
  key = match[3]
25
- elsif s3_url =~ S3_URL_PATH_REGEX
26
- match = S3_URL_PATH_REGEX.match(s3_url)
44
+ elsif url =~ S3_URL_PATH_REGEX
45
+ match = S3_URL_PATH_REGEX.match(url)
27
46
  region = match[1]
28
47
  bucket = match[2]
29
48
  key = match[3]
@@ -32,35 +51,6 @@ module VagrantPlugins
32
51
  return region, bucket, key
33
52
  end
34
53
 
35
- # Pre-sign an s3 URL, with given method.
36
- def self.presign_url(method, url, logger)
37
- logger.info("BoxS3: Generating signed URL for #{method.upcase}")
38
- logger.info("BoxS3: Discovered S3 URL: #{url}")
39
-
40
- region, bucket, key = parse_s3_url(url)
41
-
42
- logger.debug("BoxS3: Region: #{region}")
43
- logger.debug("BoxS3: Bucket: #{bucket}")
44
- logger.debug("BoxS3: Key: #{key}")
45
-
46
- client = Aws::S3::Client.new(
47
- profile: ENV['AWS_PROFILE'],
48
- region: region
49
- )
50
- presigner = Aws::S3::Presigner.new(client: client)
51
-
52
- presigned_url = presigner.presigned_url(
53
- method,
54
- bucket: bucket,
55
- key: key,
56
- expires_in: 3600
57
- ).to_s
58
-
59
- logger.debug("BoxS3: Pre-signed URL: #{presigned_url}")
60
-
61
- return presigned_url
62
- end
63
-
64
54
  end
65
55
  end
66
56
  end
@@ -1,5 +1,5 @@
1
1
  module VagrantPlugins
2
2
  module BoxS3
3
- VERSION = '0.1.2'
3
+ VERSION = '0.1.4'
4
4
  end
5
5
  end
@@ -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.2
4
+ version: 0.1.4
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-02-13 00:00:00.000000000 Z
11
+ date: 2024-02-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk-s3
@@ -63,12 +63,15 @@ 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
69
70
  licenses:
70
71
  - MIT
71
- metadata: {}
72
+ metadata:
73
+ source_code_uri: https://github.com/memiah/vagrant-box-s3
74
+ bug_tracker_uri: https://github.com/memiah/vagrant-box-s3/issues
72
75
  post_install_message:
73
76
  rdoc_options: []
74
77
  require_paths: