vagrant-box-s3 0.1.2 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
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: