Skip to content

Commit

Permalink
Merge pull request #170 from fastly/connie/remove-session-auth-part1
Browse files Browse the repository at this point in the history
Removes session authentication
  • Loading branch information
conniechu929 committed Feb 3, 2021
2 parents 159ae26 + 72b0811 commit 2c9d507
Show file tree
Hide file tree
Showing 11 changed files with 38 additions and 83 deletions.
4 changes: 2 additions & 2 deletions lib/fastly.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ class Fastly
#
# Some methods require full username and password rather than just auth token.
def initialize(opts)
if opts[:api_key].nil? && (opts[:password].nil? || opts[:user].nil?)
raise ArgumentError, "Required options missing. Please pass either ':api_key' or both ':user' and ':password'."
if opts[:api_key].nil?
raise ArgumentError, "Required option missing. Please pass ':api_key'."
end

client(opts)
Expand Down
20 changes: 4 additions & 16 deletions lib/fastly/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class Client #:nodoc: all

DEFAULT_URL = 'https://api.fastly.com'.freeze

attr_accessor :api_key, :base_url, :debug, :user, :password, :cookie, :customer
attr_accessor :api_key, :base_url, :debug, :user, :password, :customer

def initialize(opts)
@api_key = opts.fetch(:api_key, nil)
Expand All @@ -25,22 +25,12 @@ def initialize(opts)
Concurrent::ThreadLocalVar.new { build_http_client }
end

return self unless fully_authed?

warn("DEPRECATION WARNING: Username/password authentication is deprecated
and will not be available starting September 2020;
please migrate to API tokens as soon as possible.")

# If full auth creds (user/pass) then log in and set a cookie
resp = http.post(
'/login',
make_params(user: user, password: password),
{'Content-Type' => 'application/x-www-form-urlencoded'}
)
if resp.kind_of?(Net::HTTPSuccess)
@cookie = resp['Set-Cookie']
else
fail Unauthorized, "Invalid auth credentials. Check username/password."

if api_key.nil?
fail Unauthorized, "Invalid auth credentials. Check api_key."
end

self
Expand Down Expand Up @@ -150,9 +140,7 @@ def post_and_put(method, path, params = {})

def headers(extras={}, include_auth=true)
headers = {}
# Some endpoints (POST /tokens) break if any auth headers including cookies are sent
if include_auth
headers['Cookie'] = cookie if fully_authed?
headers['Fastly-Key'] = api_key if api_key
end
headers.merge('Content-Accept' => 'application/json', 'User-Agent' => "fastly-ruby-v#{Fastly::VERSION}").merge(extras.keep_if {|k,v| !v.nil? })
Expand Down
2 changes: 1 addition & 1 deletion lib/fastly/gem_version.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# The current version of the library
class Fastly
VERSION = "2.5.3"
VERSION = "3.0.0"
end
16 changes: 10 additions & 6 deletions lib/fastly/token.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,16 @@ def self.delete_path(opts)
end

def new_token(opts)
opts[:username] = client.user
opts[:password] = client.password
opts[:include_auth] = false

token = create(Token, opts)
token.nil? ? nil : token
if client.fully_authed?
opts[:username] = client.user
opts[:password] = client.password
opts[:include_auth] = false

token = create(Token, opts)
token.nil? ? nil : token
else
raise ArgumentError, "Required options missing. Please pass :api_key, :user and :password."
end
end

def customer_tokens(opts)
Expand Down
22 changes: 1 addition & 21 deletions test/api_key_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class Fastly
end
end

describe 'with cookie and api key' do
describe 'with username/password and api key' do
before do
@opts = login_opts(:both)
@client = Fastly::Client.new(@opts)
Expand All @@ -75,26 +75,6 @@ class Fastly
assert_equal 'ok', response['status']
end
end

describe 'with cookie only' do
before do
@opts = login_opts(:full)
@client = Fastly::Client.new(@opts)
@fastly = Fastly.new(@opts)
service_name = "fastly-test-service-#{random_string}"
@service = @fastly.create_service(:name => service_name)
end

after do
@fastly.delete_service(@service)
end

it 'does not allow purging' do
assert_raises Fastly::KeyAuthRequired do
@service.purge_by_key('somekey')
end
end
end
end
end
end
Expand Down
31 changes: 9 additions & 22 deletions test/fastly/client_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,17 @@
assert_equal nil, client.password
end

it 'raises Unauthorized if api_key is not passed in the options' do
assert_raises(Fastly::Unauthorized) { Fastly::Client.new(user: user, password: password)}
end

it 'raises Unauthorized if user/pass provided but are invalid' do
stub_request(:any, /api.fastly.com/).to_return(status: 400)

e = assert_raises(Fastly::Unauthorized) {
Fastly::Client.new(user: user, password: pass)
Fastly::Client.new(user: user, password: password)
}
assert_equal "Invalid auth credentials. Check username/password.", e.message
end

it 'surfaces a deprecation message when a username or password is provided' do
stub_request(:any, /api.fastly.com/).
to_return(body: JSON.generate(i: "dont care"), status: 200)

assert_output('', /DEPRECATION WARNING:/) { Fastly::Client.new(user: user, password: pass) }
assert_equal "Invalid auth credentials. Check api_key.", e.message
end

it 'initializes an http client' do
Expand All @@ -45,23 +42,13 @@
assert client.http.use_ssl?
end

it 'sets a cookie when auth with valid user/pass' do
stub_request(:any, /api.fastly.com/).
to_return(body: JSON.generate(i: "dont care"), status: 200, headers: { 'Set-Cookie' => 'tasty!' })

client = Fastly::Client.new(user: user, password: pass)
assert_equal "tasty!", client.cookie
end

it 'raises an Error if username is used in place of user as an option' do
stub_request(:any, /api.fastly.com/).
to_return(body: JSON.generate(i: "dont care"), status: 200, headers: { 'Set-Cookie' => 'tasty!' })
to_return(body: JSON.generate(i: "dont care"), status: 200)

assert_raises(ArgumentError) { Fastly.new(username: user, password: pass) }
assert_raises(ArgumentError) { Fastly.new(username: user, password: password) }

Fastly.new(user: user, password: pass)
Fastly.new(api_key: api_key)
Fastly.new(api_key: api_key, user: user, password: pass)
Fastly.new(api_key: api_key, user: user, password: password)
end
end

Expand Down
2 changes: 1 addition & 1 deletion test/fastly/customer_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
let(:owner_id) { SecureRandom.hex(6) }

let(:customer) do
stub_request(:post, "#{Fastly::Client::DEFAULT_URL}/login").to_return(body: '{}', status: 200, headers: { 'Set-Cookie' => 'tasty!' })
stub_request(:post, "#{Fastly::Client::DEFAULT_URL}/login").to_return(body: '{}', status: 200)

customer_body = JSON.dump(
'id' => customer_id,
Expand Down
4 changes: 2 additions & 2 deletions test/fastly/dictionary_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

describe Fastly::Dictionary do

let(:client) { Fastly.new(user: 'test@example.com', password: 'password') }
let(:client) { Fastly.new(api_key: 'notasecrettestkey') }
let(:service_id) { SecureRandom.hex(6) }
let(:version) { 1 }
let(:dictionary) { Fastly::Dictionary.new({id: SecureRandom.hex(6), service_id: service_id, version: 1}, client) }

before {
stub_request(:post, "#{Fastly::Client::DEFAULT_URL}/login").to_return(body: '{}', status: 200, headers: { 'Set-Cookie' => 'tasty!' })
stub_request(:post, "#{Fastly::Client::DEFAULT_URL}/login").to_return(body: '{}', status: 200)
}

describe '#item' do
Expand Down
4 changes: 2 additions & 2 deletions test/fastly/syslog_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

describe Fastly::Syslog do

let(:client) { Fastly.new(user: 'test@example.com', password: 'password') }
let(:client) { Fastly.new(api_key: 'notasecrettestkey', user: 'test@example.com', password: 'password') }
let(:service_id) { SecureRandom.hex(6) }
let(:version) { 1 }
let(:syslog) { Fastly::Syslog.new({ name: 'test_syslog', service_id: service_id, version: 1 }, client) }

before {
stub_request(:post, "#{Fastly::Client::DEFAULT_URL}/login").to_return(body: '{}', status: 200, headers: { 'Set-Cookie' => 'tasty!' })
stub_request(:post, "#{Fastly::Client::DEFAULT_URL}/login").to_return(body: '{}', status: 200)
}

describe '#item' do
Expand Down
14 changes: 5 additions & 9 deletions test/fastly/token_test.rb
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
require_relative '../test_helper'

describe Fastly::Token do

let(:elevated_fastly) { Fastly.new(user: 'test@example.com', password: 'password') }
let(:fastly) { Fastly.new(api_key:'my_api_key') }
let(:fastly) { Fastly.new(api_key:'my_api_key', user: 'test@example.com', password: 'password') }

before {
stub_request(:post, "#{Fastly::Client::DEFAULT_URL}/login").to_return(body: '{}', status: 200, headers: { 'Set-Cookie' => 'tasty!' })
stub_request(:post, "#{Fastly::Client::DEFAULT_URL}/login").to_return(body: '{}', status: 200)
}

describe '#fastly' do

it 'cannot create itself because POST /tokens must have no auth headers)' do
it 'cannot create itself because POST /tokens must have no auth headers' do
stub_request(:post, "https://api.fastly.com/tokens").
with(
body: {"name"=>"name_of_token", "scope"=>"token_scope such_as purge_all purge_select", "services"=>"service_id_that_token_can_access"},
Expand All @@ -20,13 +17,12 @@
'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
'Content-Accept'=>'application/json',
'Content-Type'=>'application/x-www-form-urlencoded',
'Cookie'=>'tasty!',
'User-Agent'=> /fastly-ruby/
}).
to_return(status: 403, body: '{"msg":"You must POST /sudo to access this endpoint"}', headers: {})

assert_raises(Fastly::Error,'{"msg":"You must POST /sudo to access this endpoint"}') do
elevated_fastly.create_token(
fastly.create_token(
name: 'name_of_token',
services: 'service_id_that_token_can_access',
scope: 'token_scope such_as purge_all purge_select'
Expand Down Expand Up @@ -63,7 +59,7 @@
}).
to_return(status: 200, body: response_body, headers: {})

token = elevated_fastly.new_token(
token = fastly.new_token(
name: 'name_of_token',
services: 'service_id_that_token_can_access',
scope: 'optional token_scope such_as purge_all purge_select'
Expand Down
2 changes: 1 addition & 1 deletion test/full_login_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# Test username/password login access to user and customer objects
class Fastly
describe 'FullLoginTest' do
let(:opts) { login_opts(:full) }
let(:opts) { login_opts(:both) }
let(:client) { Client.new(opts) }
let(:fastly) { Fastly.new(opts) }
let(:current_user) { fastly.current_user }
Expand Down

0 comments on commit 2c9d507

Please sign in to comment.