Skip to content

Commit

Permalink
Merge pull request #22 from imnetworku/PIPE-6553
Browse files Browse the repository at this point in the history
PIPE-6553: Upgrade http-hmac-ruby to Ruby 3.3
  • Loading branch information
stephenthedev authored Dec 20, 2024
2 parents b4b16a9 + 01b407e commit 3769c52
Show file tree
Hide file tree
Showing 20 changed files with 335 additions and 273 deletions.
47 changes: 47 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
AllCops:
DisplayCopNames: true
NewCops: disable
TargetRubyVersion: 3.3.6

Style/FrozenStringLiteralComment:
Exclude:
- 'lib/acquia-http-hmac/rack_authenticate.rb'

Metrics/ParameterLists:
Max: 7

Style/ClassVars:
Exclude:
- 'example/app.rb'
- 'lib/acquia-http-hmac/rack_authenticate.rb'

Metrics/AbcSize:
Max: 50
Exclude:
- 'test/acquia_spec_test.rb'

Naming/AccessorMethodName:
Exclude:
- 'test/rack_simple_app_test.rb'
- 'test/rack_sqlite3_app_test.rb'

Metrics/BlockLength:
Max: 150

Metrics/ClassLength:
Max: 1000

Metrics/CyclomaticComplexity:
Max: 12

Layout/LineLength:
Max: 200

Metrics/MethodLength:
Max: 50

Metrics/ModuleLength:
Max: 250

Metrics/PerceivedComplexity:
Max: 10
11 changes: 0 additions & 11 deletions .travis.yml

This file was deleted.

4 changes: 3 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
source "https://rubygems.org"
# frozen_string_literal: true

source 'https://rubygems.org'

gemspec
15 changes: 12 additions & 3 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
# frozen_string_literal: true

require 'bundler/setup'

begin
require 'rake/testtask'
Rake::TestTask.new do |t|
t.libs.push "lib"
t.libs.push 'lib'
t.test_files = FileList['test/*_test.rb']
t.verbose = true
end
task(default: [:test])
rescue LoadError

desc 'Run RuboCop'
task :rubocop do
sh 'rubocop'
end

task default: %i[test rubocop]
rescue LoadError => e
warn "Could not load rake/testtask: #{e}"
end
33 changes: 19 additions & 14 deletions acquia-http-hmac.gemspec
Original file line number Diff line number Diff line change
@@ -1,24 +1,29 @@
# frozen_string_literal: true

Gem::Specification.new do |s|
s.name = 'acquia-http-hmac'
s.version = '2.0.2'
s.version = '2.0.3'
s.required_ruby_version = '>= 3.3.0'
s.licenses = ['MIT']
s.summary = "HMAC signing library and rack middleware"
s.summary = 'HMAC signing library and rack middleware'
s.description = "HMAC signing library and rack middleware conforming to Acquia's HMAC 2.0 specifications"
s.date = Time.now.strftime("%Y-%m-%d")
s.authors = ["Peter Wolanin", "Marc Seeger"]
s.date = Time.now.strftime('%Y-%m-%d')
s.authors = ['Peter Wolanin', 'Marc Seeger']
s.email = '[email protected]'
s.homepage = 'https://www.acquia.com/'
s.files = Dir["[A-Z]*", "{bin,etc,lib,test}/**/*"]
s.homepage = 'https://www.acquia.com/'
s.files = Dir['[A-Z]*', '{bin,etc,lib,test}/**/*']
s.bindir = 'bin'
s.require_paths = ["lib"]
s.require_paths = ['lib']
s.executables << 'acq-http-request'

s.add_dependency 'addressable', '~> 2.4'
s.add_dependency 'addressable', '~> 2.8'

s.add_development_dependency('rake')
s.add_development_dependency('grape')
s.add_development_dependency('rack-test')
s.add_development_dependency('multi_json')
s.add_development_dependency('sqlite3')
s.add_development_dependency('webrick')
s.add_development_dependency('grape', '~> 2.2')
s.add_development_dependency('multi_json', '~> 1.15')
s.add_development_dependency 'rack', '~> 2.2.10'
s.add_development_dependency('rack-test', '~> 2.1')
s.add_development_dependency('rake', '~> 13.2')
s.add_development_dependency 'rubocop', '~> 1.69'
s.add_development_dependency('sqlite3', '~> 2.4')
s.add_development_dependency('webrick', '~> 1.9')
end
60 changes: 26 additions & 34 deletions bin/acq-http-request
Original file line number Diff line number Diff line change
@@ -1,79 +1,71 @@
#!/usr/bin/env ruby
# frozen_string_literal: true

require 'acquia-http-hmac'
require 'optparse'
require 'ostruct'

if ARGV[0]
url = ARGV[0]
end
url = ARGV[0] if ARGV[0]

# Argument processing
options = OpenStruct.new
options.realm = 'Test'
options.http_method = 'GET'
o = OptionParser.new do |opts|
opts.banner = "Usage: #{$0} URL -u ID:PASSWORD"
opts.on("-r", "--realm [REALM]", "Server auth realm. Default 'Test'.") { |v| options.realm = v }
opts.on("-u", "--user [ID:PASSWORD]", "HMAC creds") { |v| options.user = v }
opts.on("-d", "--data [DATA]", "Data to POST.") { |v| options.data = v }
opts.on("-X", "--request [METHOD]", "HTTP method. Defaults to GET, or POST if --data is specified.") { |v| options.http_method = v.upcase }
opts.banner = "Usage: #{$PROGRAM_NAME} URL -u ID:PASSWORD"
opts.on('-r', '--realm [REALM]', "Server auth realm. Default 'Test'.") { |v| options.realm = v }
opts.on('-u', '--user [ID:PASSWORD]', 'HMAC creds') { |v| options.user = v }
opts.on('-d', '--data [DATA]', 'Data to POST.') { |v| options.data = v }
opts.on('-X', '--request [METHOD]', 'HTTP method. Defaults to GET, or POST if --data is specified.') { |v| options.http_method = v.upcase }
end
begin
o.parse!
rescue Exception => e
rescue StandardError => e
puts e.message
puts o.help
exit 1
end

if ARGV.empty? or !options.user
if ARGV.empty? || !options.user
puts o.help
exit
end

uri = URI(Addressable::URI.escape.encode(url))

if uri.path == ''
uri.path = '/'
end
uri.path = '/' if uri.path == ''

host = uri.host
if uri.port && uri.port != '443'
host << ':' + uri.port
end
host << ":#{uri.port}" if uri.port && uri.port != '443'

id, password = options.user.split(':', 2)

mac = Acquia::HTTPHmac::Auth.new(options.realm, password)



args = {
http_method: options.http_method,
host: host,
id: id,
path_info: uri.path,
path_info: uri.path
}

case
when options.http_method == 'GET'
req = Net::HTTP::GET.new(uri)
when options.http_method == 'HEAD'
req = Net::HTTP::HEAD.new(uri)
when options.http_method == 'POST'
req = Net::HTTP::POST.new(uri)
when options.http_method == 'PUT'
req = Net::HTTP::PUT.new(uri)
when options.http_method == 'DELETE'
req = Net::HTTP::DELETE.new(uri)
case options.http_method
when 'GET'
Net::HTTP::GET.new(uri)
when 'HEAD'
Net::HTTP::HEAD.new(uri)
when 'POST'
Net::HTTP::POST.new(uri)
when 'PUT'
Net::HTTP::PUT.new(uri)
when 'DELETE'
Net::HTTP::DELETE.new(uri)
else
fail("Unsupported HTTP verb #{options.http_method}")
raise("Unsupported HTTP verb #{options.http_method}")
end
mac.prepare_request_headers(args).each do |name, value|
#header(name, value)
# header(name, value)
end

net = Net::HTTP.new(uri.host, uri.port)
net.use_ssl= uri.host != 'localhost'

net.use_ssl = uri.host != 'localhost'
31 changes: 16 additions & 15 deletions example-sqlite3/setup.rb
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
# frozen_string_literal: true

require 'sqlite3'
require 'base64'
require 'openssl'
require 'yaml'


# Class: ExampleSQLite3Setup
class ExampleSQLite3Setup

def initialize(dbfile, passwords_file)
@dbfile = dbfile
File.unlink(@dbfile) if File.exist?(@dbfile)
@passwords_file = passwords_file
end

def create_t1
return <<-SQL
<<-SQL
CREATE TABLE passwords (
id VARCHAR(50),
request_date CHAR(10),
Expand All @@ -24,7 +25,7 @@ def create_t1
end

def create_t2
return <<-SQL
<<-SQL
CREATE TABLE password_data (
id VARCHAR(50),
request_method VARCHAR(10),
Expand All @@ -46,51 +47,51 @@ def write_database

dates = [
today.strftime('%F'),
tomorrow.strftime('%F'),
tomorrow.strftime('%F')
]
realm = 'Test'

creds = YAML.safe_load(File.read(@passwords_file))
passwords = {}
creds.each do |id,data|
creds.each do |id, data|
passwords[id] = data['password']
end

data = {
'testadmin' => [
['GET', '/'],
['POST', '/'],
['POST', '/']
],
'testuser' => [],
'curltest' => [
['GET', '/'],
],
['GET', '/']
]
}

sha256 = OpenSSL::Digest::SHA256.new
sha256 = OpenSSL::Digest.new('SHA256')

passwords.each do |id,pass|
passwords.each do |id, pass|
# Run a 2-step HMAC KDF using date and realm
binary_pass = Base64.decode64(pass)
dates.each do |date|
derived_pass1 = OpenSSL::HMAC.digest(sha256, binary_pass, date)
derived_pass2 = OpenSSL::HMAC.digest(sha256, derived_pass1, realm)
db.execute("INSERT INTO passwords (id, request_date, base64_password) VALUES ( ?, ?, ? )", [id, date, Base64.strict_encode64(derived_pass2)])
db.execute('INSERT INTO passwords (id, request_date, base64_password) VALUES ( ?, ?, ? )', [id, date, Base64.strict_encode64(derived_pass2)])
end
end

data.each do |id, values|
values.each do |row|
row.unshift(id)
db.execute("INSERT INTO password_data VALUES ( ?, ?, ? )", row)
row.unshift(id)
db.execute('INSERT INTO password_data VALUES ( ?, ?, ? )', row)
end
end

db.close
end
end

if $0 == __FILE__
if $PROGRAM_NAME == __FILE__

mypath = File.dirname(__FILE__)
dbfile = File.join(mypath, 'passwords.sqlite3')
Expand Down
15 changes: 9 additions & 6 deletions example/app.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
# frozen_string_literal: true

require 'bundler/setup'
require 'securerandom'
require 'grape'
require 'json'

module Example
# Class: App
class App < Grape::API
version 'v1', using: :header, vendor: 'acquia'

Expand All @@ -14,28 +17,28 @@ class App < Grape::API
helpers do
def hellos
# Store data in memory for simple testing.
@@hellos ||= {SecureRandom.uuid => "world"}
@@hellos ||= { SecureRandom.uuid => 'world' }
@@hellos
end
end

resource :hello do
get do
{hello: hellos}
{ hello: hellos }
end

desc "Return a single hello."
desc 'Return a single hello.'
get ':id' do
{hello: hellos[params[:id]]}
{ hello: hellos[params[:id]] }
end

params do
requires :hello, type: String, desc: "A hello."
requires :hello, type: String, desc: 'A hello.'
end
post do
id = SecureRandom.uuid
hellos[id] = params[:hello]
{id => params[:hello]}
{ id => params[:hello] }
end
end

Expand Down
Loading

0 comments on commit 3769c52

Please sign in to comment.