gitlab-fog-azure-rm 2.2.0 → 2.3.0
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/CHANGELOG.md +4 -0
- data/lib/azure/storage/blob/blob_service.rb +3 -0
- data/lib/azure/storage/blob/default.rb +1 -1
- data/lib/azure/storage/common/core/auth/shared_access_signature_generator.rb +13 -2
- data/lib/azure/storage/common/default.rb +1 -1
- data/lib/fog/azurerm/storage.rb +3 -1
- data/lib/fog/azurerm/version.rb +1 -1
- data/test/requests/storage/test_get_blob_https_url.rb +1 -1
- data/test/unit/test_shared_access_signature_generator.rb +198 -0
- metadata +4 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fa5ac286afc5ba0f3066194079050eb837ec86bb0e23a0e879ae34b6ccd18242
|
4
|
+
data.tar.gz: cc8affe1faf1d79f910c7d7e232386b592472981738a3122922ad370d4406294
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 90faba724967de441a00eef32538b14dfbfbbce8a225d7052c965bd69110ab434316484da41b6b6de6e8ad3c7bf3cb5009cd25d634419f402a5fa31616f4764b
|
7
|
+
data.tar.gz: 7e9a772cdd278514751f4e3cd167ebe54c4c63b451c95ea701f48b475b5810638a8b847c6724e3ccf707152dbd4e509d45d2fe5ce897a2173ea88b9d5ea80c93
|
data/CHANGELOG.md
CHANGED
@@ -27,6 +27,7 @@ require "azure/storage/blob/page"
|
|
27
27
|
require "azure/storage/blob/block"
|
28
28
|
require "azure/storage/blob/append"
|
29
29
|
require "azure/storage/blob/blob"
|
30
|
+
require 'azure/storage/blob/default'
|
30
31
|
|
31
32
|
module Azure::Storage
|
32
33
|
include Azure::Storage::Common::Service
|
@@ -126,6 +127,8 @@ module Azure::Storage
|
|
126
127
|
#
|
127
128
|
# Accepted key/value pairs in options parameter are:
|
128
129
|
#
|
130
|
+
|
131
|
+
# * +:api_version+ - String. Override the default Blob service API version.
|
129
132
|
# * +:use_development_storage+ - TrueClass|FalseClass. Whether to use storage emulator.
|
130
133
|
# * +:development_storage_proxy_uri+ - String. Used with +:use_development_storage+ if emulator is hosted other than localhost.
|
131
134
|
# * +:storage_connection_string+ - String. The storage connection string.
|
@@ -29,7 +29,7 @@ require "rbconfig"
|
|
29
29
|
module Azure::Storage::Blob
|
30
30
|
module Default
|
31
31
|
# Default REST service (STG) version number
|
32
|
-
STG_VERSION = "
|
32
|
+
STG_VERSION = "2025-07-05"
|
33
33
|
|
34
34
|
# The number of default concurrent requests for parallel operation.
|
35
35
|
DEFAULT_PARALLEL_OPERATION_THREAD_COUNT = 1
|
@@ -215,6 +215,7 @@ module Azure::Storage::Common::Core
|
|
215
215
|
end
|
216
216
|
|
217
217
|
# Construct the plaintext to the spec required for signatures
|
218
|
+
# See https://learn.microsoft.com/en-us/rest/api/storageservices/create-user-delegation-sas
|
218
219
|
# @return [String]
|
219
220
|
def signable_string_for_service(service_type, path, options)
|
220
221
|
# Order is significant
|
@@ -236,8 +237,17 @@ module Azure::Storage::Common::Core
|
|
236
237
|
@user_delegation_key.signed_start,
|
237
238
|
@user_delegation_key.signed_expiry,
|
238
239
|
@user_delegation_key.signed_service,
|
239
|
-
@user_delegation_key.signed_version
|
240
|
+
@user_delegation_key.signed_version,
|
241
|
+
# User delegation fields (supported since 2020-02-10)
|
242
|
+
options[:signed_authorized_user_object_id] || "", # saoid
|
243
|
+
options[:signed_unauthorized_user_object_id] || "", # suoid
|
244
|
+
options[:signed_correlation_id] || "", # scid
|
245
|
+
# For 2025-07-05 USER DELEGATION SAS ONLY, add two empty lines after correlation ID
|
246
|
+
# This is the critical difference that was causing the signature mismatch with 2018-11-09.
|
247
|
+
"",
|
248
|
+
""
|
240
249
|
]
|
250
|
+
|
241
251
|
end
|
242
252
|
|
243
253
|
signable_fields.concat [
|
@@ -248,7 +258,8 @@ module Azure::Storage::Common::Core
|
|
248
258
|
|
249
259
|
signable_fields.concat [
|
250
260
|
options[:resource],
|
251
|
-
options[:timestamp]
|
261
|
+
options[:timestamp] || "",
|
262
|
+
options[:signed_encryption_scope] || ""
|
252
263
|
] if service_type == Azure::Storage::Common::ServiceType::BLOB
|
253
264
|
|
254
265
|
signable_fields.concat [
|
@@ -30,7 +30,7 @@ require "azure/storage/common/version"
|
|
30
30
|
module Azure::Storage::Common
|
31
31
|
module Default
|
32
32
|
# Default REST service (STG) version number. This is used only for SAS generator.
|
33
|
-
STG_VERSION = "
|
33
|
+
STG_VERSION = "2025-07-05"
|
34
34
|
|
35
35
|
# The number of default concurrent requests for parallel operation.
|
36
36
|
DEFAULT_PARALLEL_OPERATION_THREAD_COUNT = 1
|
data/lib/fog/azurerm/storage.rb
CHANGED
@@ -13,6 +13,7 @@ module Fog
|
|
13
13
|
recognizes :azure_storage_endpoint
|
14
14
|
recognizes :azure_storage_domain
|
15
15
|
recognizes :environment
|
16
|
+
recognizes :api_version
|
16
17
|
|
17
18
|
recognizes :debug
|
18
19
|
|
@@ -105,6 +106,7 @@ module Fog
|
|
105
106
|
|
106
107
|
@azure_storage_account_name = options[:azure_storage_account_name]
|
107
108
|
@azure_storage_access_key = options[:azure_storage_access_key]
|
109
|
+
@api_version = options[:api_version]
|
108
110
|
|
109
111
|
load_credentials
|
110
112
|
|
@@ -126,7 +128,7 @@ module Fog
|
|
126
128
|
signer: @azure_storage_token_signer
|
127
129
|
}.compact)
|
128
130
|
azure_client.storage_blob_host = storage_blob_host
|
129
|
-
@blob_client = Azure::Storage::Blob::BlobService.new(client: azure_client)
|
131
|
+
@blob_client = Azure::Storage::Blob::BlobService.new(client: azure_client, api_version: @api_version)
|
130
132
|
@blob_client.with_filter(Fog::AzureRM::IdentityEncodingFilter.new)
|
131
133
|
@blob_client.with_filter(Azure::Storage::Common::Core::Filter::ExponentialRetryPolicyFilter.new)
|
132
134
|
@blob_client.with_filter(Azure::Core::Http::DebugFilter.new) if @debug
|
data/lib/fog/azurerm/version.rb
CHANGED
@@ -145,7 +145,7 @@ class TestGetBlobHttpsUrl < Minitest::Test
|
|
145
145
|
params = parsed.query.split('&').to_h { |x| x.split('=') }
|
146
146
|
|
147
147
|
assert_equal 'r', params['sp']
|
148
|
-
assert_equal '
|
148
|
+
assert_equal '2025-07-05', params['sv']
|
149
149
|
assert_equal 'b', params['sr']
|
150
150
|
assert_equal 'https', params['spr']
|
151
151
|
assert_equal '2024-09-19T00%3A00%3A00Z', params['skt']
|
@@ -0,0 +1,198 @@
|
|
1
|
+
require File.expand_path '../test_helper', __dir__
|
2
|
+
require 'azure/storage/common'
|
3
|
+
require 'base64'
|
4
|
+
require 'uri'
|
5
|
+
|
6
|
+
class TestSharedAccessSignatureGeneration < Minitest::Test
|
7
|
+
def setup
|
8
|
+
@access_account_name = 'testaccount'
|
9
|
+
@access_key_base64 = Base64.strict_encode64('test-access-key')
|
10
|
+
@path = '/container/blob.txt'
|
11
|
+
@service_type = Azure::Storage::Common::ServiceType::BLOB
|
12
|
+
|
13
|
+
@service_options = {
|
14
|
+
service: 'b',
|
15
|
+
permissions: 'c',
|
16
|
+
start: '2025-09-10T17:00:00Z',
|
17
|
+
expiry: '2025-09-10T18:00:00Z',
|
18
|
+
resource: 'b',
|
19
|
+
protocol: 'https',
|
20
|
+
ip_range: '192.168.1.1-192.168.1.10'
|
21
|
+
}
|
22
|
+
|
23
|
+
@user_delegation_key = Azure::Storage::Common::Service::UserDelegationKey.new do |key|
|
24
|
+
key.signed_oid = 'user-object-id-123'
|
25
|
+
key.signed_tid = 'tenant-id-456'
|
26
|
+
key.signed_start = '2025-09-10T17:00:00Z'
|
27
|
+
key.signed_expiry = '2025-09-10T19:00:00Z'
|
28
|
+
key.signed_service = 'b'
|
29
|
+
key.signed_version = '2020-08-04'
|
30
|
+
key.value = Base64.strict_encode64('user-delegation-key-value')
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_service_sas_signature_string_format
|
35
|
+
# Test regular service SAS (no user delegation key)
|
36
|
+
sas = Azure::Storage::Common::Core::Auth::SharedAccessSignature.new(@access_account_name, @access_key_base64)
|
37
|
+
|
38
|
+
result = sas.signable_string_for_service(@service_type, @path, @service_options)
|
39
|
+
lines = result.split("\n", -1) # Preserve training newlines
|
40
|
+
|
41
|
+
# Verify service SAS structure
|
42
|
+
assert_equal 'c', lines[0] # permissions
|
43
|
+
assert_equal '2025-09-10T17:00:00Z', lines[1] # start
|
44
|
+
assert_equal '2025-09-10T18:00:00Z', lines[2] # expiry
|
45
|
+
assert_equal '/blob/testaccount/container/blob.txt', lines[3] # canonicalized resource
|
46
|
+
assert_equal '', lines[4] # identifier (empty for service SAS)
|
47
|
+
assert_equal '192.168.1.1-192.168.1.10', lines[5] # ip_range
|
48
|
+
assert_equal 'https', lines[6] # protocol
|
49
|
+
assert_equal Azure::Storage::Common::Default::STG_VERSION, lines[7] # version
|
50
|
+
assert_equal 'b', lines[8] # resource
|
51
|
+
assert_equal '', lines[9] # timestamp (empty)
|
52
|
+
assert_equal '', lines[10] # encryption scope (empty)
|
53
|
+
# Response headers (all empty)
|
54
|
+
assert_equal '', lines[11] # cache_control
|
55
|
+
assert_equal '', lines[12] # content_disposition
|
56
|
+
assert_equal '', lines[13] # content_encoding
|
57
|
+
assert_equal '', lines[14] # content_language
|
58
|
+
assert_equal '', lines[15] # content_type
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_user_delegation_sas_signature_string_format
|
62
|
+
# Test user delegation SAS - always includes new 2025-07-05 format
|
63
|
+
sas = Azure::Storage::Common::Core::Auth::SharedAccessSignature.new(@access_account_name, @access_key_base64, @user_delegation_key)
|
64
|
+
|
65
|
+
result = sas.signable_string_for_service(@service_type, @path, @service_options)
|
66
|
+
lines = result.split("\n", -1) # Preserve training newlines
|
67
|
+
|
68
|
+
# Verify user delegation SAS structure
|
69
|
+
assert_equal 'c', lines[0] # permissions
|
70
|
+
assert_equal '2025-09-10T17:00:00Z', lines[1] # start
|
71
|
+
assert_equal '2025-09-10T18:00:00Z', lines[2] # expiry
|
72
|
+
assert_equal '/blob/testaccount/container/blob.txt', lines[3] # canonicalized resource
|
73
|
+
|
74
|
+
# User delegation key fields
|
75
|
+
assert_equal 'user-object-id-123', lines[4] # signed_oid
|
76
|
+
assert_equal 'tenant-id-456', lines[5] # signed_tid
|
77
|
+
assert_equal '2025-09-10T17:00:00Z', lines[6] # signed_start
|
78
|
+
assert_equal '2025-09-10T19:00:00Z', lines[7] # signed_expiry
|
79
|
+
assert_equal 'b', lines[8] # signed_service
|
80
|
+
assert_equal '2020-08-04', lines[9] # signed_version
|
81
|
+
|
82
|
+
# New fields for user delegation SAS (empty by default)
|
83
|
+
assert_equal '', lines[10] # saoid
|
84
|
+
assert_equal '', lines[11] # suoid
|
85
|
+
assert_equal '', lines[12] # scid
|
86
|
+
|
87
|
+
# Critical: Two empty lines - this was causing the signature mismatch!
|
88
|
+
assert_equal '', lines[13] # First empty line
|
89
|
+
assert_equal '', lines[14] # Second empty line
|
90
|
+
|
91
|
+
# Continue with remaining fields
|
92
|
+
assert_equal '192.168.1.1-192.168.1.10', lines[15] # ip_range
|
93
|
+
assert_equal 'https', lines[16] # protocol
|
94
|
+
assert_equal Azure::Storage::Common::Default::STG_VERSION, lines[17] # version
|
95
|
+
assert_equal 'b', lines[18] # resource
|
96
|
+
assert_equal '', lines[19] # timestamp
|
97
|
+
assert_equal '', lines[20] # encryption scope
|
98
|
+
# Response headers (all empty)
|
99
|
+
assert_equal '', lines[21] # cache_control
|
100
|
+
assert_equal '', lines[22] # content_disposition
|
101
|
+
assert_equal '', lines[23] # content_encoding
|
102
|
+
assert_equal '', lines[24] # content_language
|
103
|
+
assert_equal '', lines[25] # content_type
|
104
|
+
end
|
105
|
+
|
106
|
+
def test_user_delegation_sas_with_optional_fields
|
107
|
+
# Test user delegation SAS with optional fields set
|
108
|
+
sas = Azure::Storage::Common::Core::Auth::SharedAccessSignature.new(@access_account_name, @access_key_base64, @user_delegation_key)
|
109
|
+
|
110
|
+
options_with_extras = @service_options.merge({
|
111
|
+
signed_authorized_user_object_id: 'authorized-user-789',
|
112
|
+
signed_unauthorized_user_object_id: 'unauthorized-user-000',
|
113
|
+
signed_correlation_id: 'correlation-abc-123',
|
114
|
+
signed_encryption_scope: 'test-encryption-scope',
|
115
|
+
timestamp: '2025-09-10T17:30:00Z',
|
116
|
+
cache_control: 'no-cache',
|
117
|
+
content_type: 'application/json'
|
118
|
+
})
|
119
|
+
|
120
|
+
result = sas.signable_string_for_service(@service_type, @path, options_with_extras)
|
121
|
+
lines = result.split("\n", -1) # Preserve training newlines
|
122
|
+
|
123
|
+
# Verify the optional fields are included
|
124
|
+
assert_equal 'authorized-user-789', lines[10] # saoid
|
125
|
+
assert_equal 'unauthorized-user-000', lines[11] # suoid
|
126
|
+
assert_equal 'correlation-abc-123', lines[12] # scid
|
127
|
+
assert_equal '2025-09-10T17:30:00Z', lines[19] # timestamp
|
128
|
+
assert_equal 'test-encryption-scope', lines[20] # encryption scope
|
129
|
+
assert_equal 'no-cache', lines[21] # cache_control
|
130
|
+
assert_equal 'application/json', lines[25] # content_type
|
131
|
+
end
|
132
|
+
|
133
|
+
def test_table_service_signature_format
|
134
|
+
# Test table service (no blob-specific fields)
|
135
|
+
sas = Azure::Storage::Common::Core::Auth::SharedAccessSignature.new(@access_account_name, @access_key_base64)
|
136
|
+
|
137
|
+
table_options = {
|
138
|
+
service: 't',
|
139
|
+
permissions: 'rau',
|
140
|
+
expiry: '2025-09-10T18:00:00Z',
|
141
|
+
startpk: 'partition1',
|
142
|
+
startrk: 'row1',
|
143
|
+
endpk: 'partition2',
|
144
|
+
endrk: 'row2'
|
145
|
+
}
|
146
|
+
|
147
|
+
result = sas.signable_string_for_service(Azure::Storage::Common::ServiceType::TABLE, 'mytable', table_options)
|
148
|
+
lines = result.split("\n", -1) # Preserve training newlines
|
149
|
+
|
150
|
+
# Table service should not have blob-specific fields
|
151
|
+
assert_equal 'rau', lines[0] # permissions
|
152
|
+
assert_equal '/table/testaccount/mytable', lines[3] # canonicalized resource
|
153
|
+
|
154
|
+
# Should end with table-specific fields (no response headers for table)
|
155
|
+
expected_line_count = 12 # Basic fields + table fields, no blob fields
|
156
|
+
assert_equal expected_line_count, lines.length
|
157
|
+
assert_equal 'partition1', lines[8] # startpk
|
158
|
+
assert_equal 'row1', lines[9] # startrk
|
159
|
+
assert_equal 'partition2', lines[10] # endpk
|
160
|
+
assert_equal 'row2', lines[11] # endrk
|
161
|
+
end
|
162
|
+
|
163
|
+
def test_canonicalized_resource_format
|
164
|
+
sas = Azure::Storage::Common::Core::Auth::SharedAccessSignature.new(@access_account_name, @access_key_base64)
|
165
|
+
|
166
|
+
# Test with leading slash
|
167
|
+
result = sas.canonicalized_resource('blob', '/container/blob.txt')
|
168
|
+
assert_equal '/blob/testaccount/container/blob.txt', result
|
169
|
+
|
170
|
+
# Test without leading slash
|
171
|
+
result = sas.canonicalized_resource('blob', 'container/blob.txt')
|
172
|
+
assert_equal '/blob/testaccount/container/blob.txt', result
|
173
|
+
|
174
|
+
# Test table resource
|
175
|
+
result = sas.canonicalized_resource('table', 'mytable')
|
176
|
+
assert_equal '/table/testaccount/mytable', result
|
177
|
+
end
|
178
|
+
|
179
|
+
def test_sas_token_generation_creates_valid_query_string
|
180
|
+
# Test that generate_service_sas_token creates a valid query string
|
181
|
+
sas = Azure::Storage::Common::Core::Auth::SharedAccessSignature.new(@access_account_name, @access_key_base64)
|
182
|
+
|
183
|
+
token = sas.generate_service_sas_token(@path, @service_options)
|
184
|
+
|
185
|
+
# Parse the query string
|
186
|
+
params = URI.decode_www_form(token).to_h
|
187
|
+
|
188
|
+
# Verify expected parameters are present
|
189
|
+
assert_equal 'c', params['sp'] # permissions
|
190
|
+
assert_equal '2025-09-10T17:00:00Z', params['st'] # start
|
191
|
+
assert_equal '2025-09-10T18:00:00Z', params['se'] # expiry
|
192
|
+
assert_equal 'b', params['sr'] # resource
|
193
|
+
assert_equal 'https', params['spr'] # protocol
|
194
|
+
assert_equal '192.168.1.1-192.168.1.10', params['sip'] # ip_range
|
195
|
+
assert params.key?('sig') # signature should be present
|
196
|
+
refute_empty params['sig'] # signature should not be empty
|
197
|
+
end
|
198
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gitlab-fog-azure-rm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shaffan Chaudhry
|
@@ -15,10 +15,9 @@ authors:
|
|
15
15
|
- Azeem Sajid
|
16
16
|
- Maham Nazir
|
17
17
|
- Abbas Sheikh
|
18
|
-
autorequire:
|
19
18
|
bindir: bin
|
20
19
|
cert_chain: []
|
21
|
-
date:
|
20
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
22
21
|
dependencies:
|
23
22
|
- !ruby/object:Gem::Dependency
|
24
23
|
name: codeclimate-test-reporter
|
@@ -238,7 +237,6 @@ dependencies:
|
|
238
237
|
version: 1.10.8
|
239
238
|
description: This is a stripped-down fork of fog-azure-rm that enables Azure Blob
|
240
239
|
Storage to be used with CarrierWave and Fog.
|
241
|
-
email:
|
242
240
|
executables: []
|
243
241
|
extensions: []
|
244
242
|
extra_rdoc_files:
|
@@ -452,6 +450,7 @@ files:
|
|
452
450
|
- test/test_helper.rb
|
453
451
|
- test/unit/test_default_credentials.rb
|
454
452
|
- test/unit/test_managed_identity_client.rb
|
453
|
+
- test/unit/test_shared_access_signature_generator.rb
|
455
454
|
- test/unit/test_workflow_identity_client.rb
|
456
455
|
homepage: https://gitlab.com/gitlab-org/gitlab-fog-azure-rm
|
457
456
|
licenses:
|
@@ -473,8 +472,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
473
472
|
- !ruby/object:Gem::Version
|
474
473
|
version: '0'
|
475
474
|
requirements: []
|
476
|
-
rubygems_version: 3.
|
477
|
-
signing_key:
|
475
|
+
rubygems_version: 3.7.2
|
478
476
|
specification_version: 4
|
479
477
|
summary: Module for the 'fog' gem to support Azure Blob Storage with CarrierWave and
|
480
478
|
Fog.
|