diff options
| -rw-r--r-- | app/controllers/controller_extension/token_authentication.rb | 2 | ||||
| -rw-r--r-- | app/models/api_token.rb | 27 | ||||
| -rw-r--r-- | config/routes.rb | 3 | ||||
| -rw-r--r-- | test/functional/v1/identities_controller_test.rb | 20 | ||||
| -rw-r--r-- | test/functional/v1/users_controller_test.rb | 52 | ||||
| -rw-r--r-- | test/support/auth_test_helper.rb | 15 | 
6 files changed, 109 insertions, 10 deletions
diff --git a/app/controllers/controller_extension/token_authentication.rb b/app/controllers/controller_extension/token_authentication.rb index 15ddef7..c41d61b 100644 --- a/app/controllers/controller_extension/token_authentication.rb +++ b/app/controllers/controller_extension/token_authentication.rb @@ -5,7 +5,7 @@ module ControllerExtension::TokenAuthentication    def token      @token ||= authenticate_with_http_token do |token, options| -      Token.find_by_token(token) || ApiToken.find_by_token(token) +      Token.find_by_token(token) || ApiToken.find_by_token(token, request.headers['REMOTE_ADDR'])      end    end diff --git a/app/models/api_token.rb b/app/models/api_token.rb index 49b1870..5c7923d 100644 --- a/app/models/api_token.rb +++ b/app/models/api_token.rb @@ -14,10 +14,12 @@ class ApiToken    # Searches static config to see if there is a matching api token string.    # Return an ApiToken if successful, or nil otherwise.    # -  def self.find_by_token(token) +  def self.find_by_token(token, ip_address=nil)      if APP_CONFIG["api_tokens"].nil? || APP_CONFIG["api_tokens"].empty?        # no api auth tokens are configured        return nil +    elsif ip_address && !ip_allowed?(ip_address) +      return nil      elsif !token.is_a?(String) || token.size < 24        # don't allow obviously invalid token strings        return nil @@ -25,8 +27,8 @@ class ApiToken        token_digest = Digest::SHA512.hexdigest(token)        username = self.static_auth_tokens[token_digest]        if username -        if username == "test" -          return ApiTestToken.new +        if username == "monitor" +          return ApiMonitorToken.new          elsif username == "admin"            # not yet supported            return nil @@ -51,14 +53,25 @@ class ApiToken    #    def self.static_auth_tokens      @static_auth_tokens ||= APP_CONFIG["api_tokens"].inject({}) {|hsh, entry| -      hsh[Digest::SHA512.hexdigest(entry[1])] = entry[0] +      if ["monitor", "admin"].include?(entry[0]) +        hsh[Digest::SHA512.hexdigest(entry[1])] = entry[0] +      end        hsh      }.freeze    end +  def self.ip_allowed?(ip) +    ip == "0.0.0.0" || +    ip == "127.0.0.1" || ( +      APP_CONFIG["api_tokens"] && +      APP_CONFIG["api_tokens"]["allowed_ips"].is_a?(Array) && +      APP_CONFIG["api_tokens"]["allowed_ips"].include?(ip) +    ) +  end +  end -class ApiAdminToken < Token +class ApiAdminToken < ApiToken    # not yet supported    #def authenticate    #  AdminUser.new @@ -69,8 +82,8 @@ end  # These tokens used by the platform to run regular monitor tests  # of a production infrastructure.  # -class ApiTestToken < Token +class ApiMonitorToken < ApiToken    def authenticate -    ApiTestUser.new +    ApiMonitorUser.new    end  end diff --git a/config/routes.rb b/config/routes.rb index da6edce..c455dd7 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -30,12 +30,13 @@ LeapWeb::Application.routes.draw do      resources :sessions, :only => [:new, :create, :update],        :constraints => { :id => /[^\/]+(?=\.json\z)|[^\/]+/ }      delete "logout" => "sessions#destroy", :as => "logout" -    resources :users, :only => [:create, :update, :destroy, :index] +    resources :users, :only => [:create, :update, :destroy, :index, :show]      resources :messages, :only => [:index, :update]      resource :cert, :only => [:show, :create]      resource :smtp_cert, :only => [:create]      resource :service, :only => [:show]      resources :configs, :only => [:index, :show] +    resources :identities, :only => [:show]    end    scope "(:locale)", :locale => CommonLanguages.match_available do diff --git a/test/functional/v1/identities_controller_test.rb b/test/functional/v1/identities_controller_test.rb new file mode 100644 index 0000000..3e88402 --- /dev/null +++ b/test/functional/v1/identities_controller_test.rb @@ -0,0 +1,20 @@ +require_relative '../../test_helper' + +class V1::IdentitiesControllerTest < ActionController::TestCase + +  test "api monitor can fetch identity" do +    monitor_auth do +      identity = FactoryGirl.create :identity +      get :show, :id => identity.address, :format => 'json' +      assert_response :success +      assert_equal identity, assigns(:identity) +    end +  end + +  test "anonymous cannot fetch identity" do +    identity = FactoryGirl.create :identity +    get :show, :id => identity.address, :format => 'json' +    assert_response :forbidden +  end + +end diff --git a/test/functional/v1/users_controller_test.rb b/test/functional/v1/users_controller_test.rb index ffe2484..7afbb02 100644 --- a/test/functional/v1/users_controller_test.rb +++ b/test/functional/v1/users_controller_test.rb @@ -1,4 +1,4 @@ -require 'test_helper' +require_relative '../../test_helper'  class V1::UsersControllerTest < ActionController::TestCase @@ -81,4 +81,54 @@ class V1::UsersControllerTest < ActionController::TestCase      end    end +  test "admin can show user" do +    user = FactoryGirl.create :user +    login :is_admin? => true +    get :show, :id => 0, :login => user.login, :format => :json +    assert_response :success +    assert_json_response user +    get :show, :id => user.id, :format => :json +    assert_response :success +    assert_json_response user +    get :show, :id => "0", :format => :json +    assert_response :not_found +  end + +  test "normal users cannot show user" do +    user = find_record :user +    login +    get :show, :id => 0, :login => user.login, :format => :json +    assert_access_denied +  end + +  test "api monitor auth can create and destroy test users" do +    with_config(allow_registration: false) do +      monitor_auth do +        user_attribs = record_attributes_for :test_user +        post :create, :user => user_attribs, :format => :json +        assert_response :success +        delete :destroy, :id => assigns(:user).id, :format => :json +        assert_response :success +      end +    end +  end + +  test "api monitor auth cannot create normal users" do +    monitor_auth do +      user_attribs = record_attributes_for :user +      post :create, :user => user_attribs, :format => :json +      assert_response :forbidden +    end +  end + +  test "api monitor auth cannot delete normal users" do +    post :create, :user => record_attributes_for(:user), :format => :json +    assert_response :success +    normal_user_id = assigns(:user).id +    monitor_auth do +      delete :destroy, :id => normal_user_id, :format => :json +      assert_response :forbidden +    end +  end +  end diff --git a/test/support/auth_test_helper.rb b/test/support/auth_test_helper.rb index 7af3341..acc6076 100644 --- a/test/support/auth_test_helper.rb +++ b/test/support/auth_test_helper.rb @@ -29,6 +29,21 @@ module AuthTestHelper      @token.expects(:destroy) if @token    end +  # authenticate as the api monitor +  def monitor_auth(&block) +    token_auth(APP_CONFIG['api_tokens']['monitor'], &block) +  end + +  # authenticate with a token +  def token_auth(token_str) +    original = request.env['HTTP_AUTHORIZATION'] +    request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Token.encode_credentials(token_str) +    if block_given? +      yield +      request.env['HTTP_AUTHORIZATION'] = original +    end +  end +    protected    def header_for_token_auth  | 
