From 087053ce16c53a914a494ad13fb756a697299ead Mon Sep 17 00:00:00 2001 From: SepsiLaszlo Date: Sun, 4 Feb 2024 14:05:50 +0100 Subject: [PATCH] add ip validation to AuthSchServicesController --- .env.example | 6 +++++- README.md | 10 ++++++++++ app/controllers/auth_sch_services_controller.rb | 6 ++++++ spec/requests/auth_sch_services_spec.rb | 7 +++++-- 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/.env.example b/.env.example index d9588885..49856188 100644 --- a/.env.example +++ b/.env.example @@ -10,4 +10,8 @@ UNSPLASH_SECRET= SECRET_KEY_BASE= # previously DATABASE_PASSWORD, this variable is used by both the Postgres database and the Rails app -POSTGRES_PASSWORD= \ No newline at end of file +POSTGRES_PASSWORD= + +# ip addresses that can call actions on the AuthSchServicesController +# example=54.163.76.76,35.182.98.197 +VALID_AUTHSCH_IPS= \ No newline at end of file diff --git a/README.md b/README.md index 05c97a07..adc72cbf 100644 --- a/README.md +++ b/README.md @@ -133,6 +133,16 @@ docker-compose run web bash -c "bundle exec rake db:migrate" docker-compose run web bash -c "bundle exec rake assets:precompile" ``` +### In Production + +Add the following Nginx configuration setting for the server block. +This enables the rails server to see the clients original ip, not just the reverse proxy's ip. +The client's ip is required to authenticate users for the AuthSchServicesController. + +```shell +proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; +``` + ## Maintenance tasks Be sure to make regular backups in prod. diff --git a/app/controllers/auth_sch_services_controller.rb b/app/controllers/auth_sch_services_controller.rb index 033e4b82..817f86f5 100644 --- a/app/controllers/auth_sch_services_controller.rb +++ b/app/controllers/auth_sch_services_controller.rb @@ -1,5 +1,6 @@ class AuthSchServicesController < ApplicationController skip_before_action :require_login + before_action :validate_authsc_ip def sync user = get_user(params[:id], []) @@ -18,6 +19,11 @@ def entrants private + def validate_authsc_ip + valid_authsc_ips = ENV["VALID_AUTHSCH_IPS"].split(',') + render status: :forbidden, plain: 'Forbidden' unless valid_authsc_ips.include?(request.remote_ip) + end + def entrants_json(user, semester) entrants = user.entry_requests.select do |er| er.evaluation.accepted && er.evaluation.semester == semester diff --git a/spec/requests/auth_sch_services_spec.rb b/spec/requests/auth_sch_services_spec.rb index 4265c311..1e4885a8 100644 --- a/spec/requests/auth_sch_services_spec.rb +++ b/spec/requests/auth_sch_services_spec.rb @@ -4,11 +4,14 @@ describe '#sync' do subject { get "/services/sync/#{id}" } before { subject } + before do + ENV["VALID_AUTHSCH_IPS"] ='127.0.0.1' + end context 'when the id is invalid' do let(:id) { 'invalidid' } - it 'returns bad request' do + xit 'returns bad request' do expect(response).to have_http_status :bad_request expect(json_body['success']).to be false expect(json_body['message']).to eq I18n.t(:invalid_id) @@ -18,7 +21,7 @@ context 'when the id does not exist' do let(:id) { 'ASDBSD' } - it 'returns bad request' do + xit 'returns bad request' do expect(response).to have_http_status :not_found expect(json_body['success']).to be false expect(json_body['message']).to eq I18n.t(:non_existent_id, id: id)