From b0db7f3eb9e5cc028a9ec73c8f3c1ef44cc7a9ef Mon Sep 17 00:00:00 2001 From: Moncef Belyamani Date: Fri, 16 Mar 2018 21:00:07 -0400 Subject: [PATCH 01/27] Enable parallel builds in Circle CI **Why**: For faster test runs References: - https://circleci.com/docs/2.0/language-ruby/#sample-configuration - https://circleci.com/docs/2.0/parallelism-faster-jobs/ - https://github.com/ArturT/knapsac - https://twitter.com/circleci/status/974703363542495232 - https://github.com/rdunlop/codeclimate_circle_ci_coverage --- .circleci/config.yml | 57 +++++-- Gemfile | 1 + Gemfile.lock | 3 + Rakefile | 1 + deploy/activate | 2 - knapsack_rspec_report.json | 307 +++++++++++++++++++++++++++++++++++++ spec/spec_helper.rb | 3 + 7 files changed, 359 insertions(+), 15 deletions(-) create mode 100644 knapsack_rspec_report.json diff --git a/.circleci/config.yml b/.circleci/config.yml index 0c61e7c365d..94167b1c478 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,6 +5,7 @@ version: 2 jobs: build: + parallelism: 4 docker: # Specify the Ruby version you desire here - image: circleci/ruby:2.3.6-node-browsers @@ -12,6 +13,7 @@ jobs: RAILS_ENV: test CC_TEST_REPORTER_ID: faecd27e9aed532634b3f4d3e251542d7de9457cfca96a94208a63270ef9b42e COVERAGE: true + PATH: "/opt/yarn/yarn-v1.5.1/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" # Specify service dependencies here if necessary # CircleCI maintains a library of pre-built images @@ -28,35 +30,59 @@ jobs: - checkout - restore-cache: - key: identity-idp-{{ checksum "Gemfile.lock" }} - + keys: + - identity-idp-bundle-{{ checksum "Gemfile.lock" }} + - identity-idp-bundle- - run: name: Install dependencies command: | gem install bundler - bundle install --deployment --jobs=4 --retry=3 --without deploy development doc production --path vendor/bundle + bundle check || bundle install --deployment --jobs=4 --retry=3 --without deploy development doc production --path vendor/bundle + - save-cache: + key: identity-idp-bundle-{{ checksum "Gemfile.lock" }} + paths: + - vendor/bundle + + - restore-cache: + keys: + - identity-idp-yarn-{{ checksum "yarn.lock" }} + - identity-idp-yarn- + - run: + name: Install Yarn + command: yarn install --cache-folder ~/.cache/yarn + - save-cache: + key: identity-idp-yarn-{{ checksum "yarn.lock" }} + paths: + - ~/.cache/yarn + - run: name: Install phantomjs command: | sudo curl --output /tmp/phantomjs https://s3.amazonaws.com/circle-downloads/phantomjs-2.1.1 sudo chmod ugo+x /tmp/phantomjs sudo ln -sf /tmp/phantomjs /usr/local/bin/phantomjs + + - run: + name: Install AWS CLI + command: | + sudo apt-get update + sudo apt-get install python-pip python-dev jq + sudo pip install awscli + - run: name: Install Code Climate Test Reporter command: | curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter chmod +x ./cc-test-reporter + aws s3 --region us-west-2 rm s3://login-gov-test-coverage/coverage/$CIRCLE_PREVIOUS_BUILD_NUM --recursive - # Store bundle cache - - save-cache: - key: identity-idp-{{ checksum "Gemfile.lock" }} - paths: - - vendor/bundle + - run: + name: Wait for DB + command: dockerize -wait tcp://localhost:5432 -timeout 1m - run: name: Test Setup command: | - yarn install cp config/application.yml.example config/application.yml cp certs/saml.crt.example certs/saml.crt cp certs/saml2018.crt.example certs/saml2018.crt @@ -72,15 +98,15 @@ jobs: mkdir /tmp/test-results ./cc-test-reporter before-build - bundle exec rspec --format progress + bundle exec rake knapsack:rspec yarn test bundle exec slim-lint app/views - run: - name: Upload Test Results to Code Climate + name: Code Climate Test Coverage command: | - ./cc-test-reporter format-coverage -t simplecov $CIRCLE_ARTIFACTS/coverage/.resultset.json - ./cc-test-reporter upload-coverage + ./cc-test-reporter format-coverage -t simplecov -o "coverage/codeclimate.$CIRCLE_NODE_INDEX.json" + aws s3 sync coverage/ "s3://login-gov-test-coverage/coverage/$CIRCLE_BUILD_NUM" # collect reports - store_test_results: @@ -88,3 +114,8 @@ jobs: - store_artifacts: path: /tmp/test-results destination: test-results + + - deploy: + command: | + aws s3 sync "s3://login-gov-test-coverage/coverage/$CIRCLE_BUILD_NUM" coverage/ + ./cc-test-reporter sum-coverage --output - --parts $CIRCLE_NODE_TOTAL coverage/codeclimate.*.json | ./cc-test-reporter upload-coverage --input - diff --git a/Gemfile b/Gemfile index 619922212d9..4a4eab5a9e8 100644 --- a/Gemfile +++ b/Gemfile @@ -81,6 +81,7 @@ group :development, :test do gem 'bullet' gem 'front_matter_parser' gem 'i18n-tasks' + gem 'knapsack' gem 'pry-byebug' gem 'rspec-rails', '~> 3.5.2' gem 'slim_lint' diff --git a/Gemfile.lock b/Gemfile.lock index b27314e04ce..a0e8a656870 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -322,6 +322,8 @@ GEM securecompare url_safe_base64 jwt (2.1.0) + knapsack (1.16.0) + rake launchy (2.4.3) addressable (~> 2.3) listen (3.1.5) @@ -694,6 +696,7 @@ DEPENDENCIES i18n-tasks identity-hostdata! json-jwt + knapsack lograge net-sftp newrelic_rpm diff --git a/Rakefile b/Rakefile index ba6768cca80..901b8dfc348 100644 --- a/Rakefile +++ b/Rakefile @@ -4,3 +4,4 @@ require File.expand_path('../config/application', __FILE__) Rails.application.load_tasks +Knapsack.load_tasks if defined?(Knapsack) diff --git a/deploy/activate b/deploy/activate index 3155e14f343..901f652be36 100755 --- a/deploy/activate +++ b/deploy/activate @@ -1,6 +1,4 @@ #!/usr/bin/env ruby -require 'bundler' -Bundler.setup(:default, :production) require 'active_support/core_ext/hash/deep_merge' require 'logger' diff --git a/knapsack_rspec_report.json b/knapsack_rspec_report.json new file mode 100644 index 00000000000..538bdd99a82 --- /dev/null +++ b/knapsack_rspec_report.json @@ -0,0 +1,307 @@ +{ + "spec/mailers/user_mailer_spec.rb": 3.986692428588867, + "spec/controllers/health/health_controller_spec.rb": 0.0879204273223877, + "spec/features/visitors/password_recovery_spec.rb": 18.320884704589844, + "spec/services/store_sp_metadata_in_session_spec.rb": 0.03163957595825195, + "spec/helpers/locale_helper_spec.rb": 0.00511479377746582, + "spec/lib/yaml_normalizer_spec.rb": 0.012772321701049805, + "spec/forms/totp_verification_form_spec.rb": 0.048506975173950195, + "spec/services/parse_controller_from_referer_spec.rb": 0.0026540756225585938, + "spec/views/sign_up/personal_keys/show.html.slim_spec.rb": 0.2504265308380127, + "spec/services/twilio_service_spec.rb": 0.021703004837036133, + "spec/forms/password_reset_email_form_spec.rb": 0.051154375076293945, + "spec/views/shared/_flashes.html.slim_spec.rb": 0.015145540237426758, + "spec/mailers/custom_devise_mailer_spec.rb": 0.02736043930053711, + "spec/controllers/reactivate_account_controller_spec.rb": 0.27582335472106934, + "spec/controllers/users/reset_passwords_controller_spec.rb": 1.8172168731689453, + "spec/services/access_token_verifier_spec.rb": 0.04410696029663086, + "spec/views/sign_up/emails/show.html.slim_spec.rb": 0.027134180068969727, + "spec/views/users/totp_setup/new.html.slim_spec.rb": 0.06975769996643066, + "spec/services/email_notifier_spec.rb": 0.07540345191955566, + "spec/controllers/users/verify_account_controller_spec.rb": 0.24046969413757324, + "spec/requests/invalid_encoding_spec.rb": 0.01710224151611328, + "spec/lib/worker_health_checker_spec.rb": 0.03649735450744629, + "spec/services/marketing_site_spec.rb": 0.011338233947753906, + "spec/features/accessibility/user_pages_spec.rb": 10.79332423210144, + "spec/services/service_provider_updater_spec.rb": 0.10974884033203125, + "spec/services/session_encryptor_spec.rb": 0.08093667030334473, + "spec/services/pii/password_encryptor_spec.rb": 0.05370473861694336, + "spec/features/users/user_profile_spec.rb": 6.8305253982543945, + "spec/features/idv/failed_job_spec.rb": 0.31787729263305664, + "spec/requests/redirects_spec.rb": 0.010896682739257812, + "spec/features/saml/loa3_sso_spec.rb": 6.205901145935059, + "spec/views/devise/passwords/edit.html.slim_spec.rb": 0.16029071807861328, + "spec/forms/verify_account_form_spec.rb": 0.3789637088775635, + "spec/models/agency_identity_spec.rb": 0.01060032844543457, + "spec/lib/encrypted_sidekiq_redis_spec.rb": 0.5380933284759521, + "spec/forms/idv/profile_form_spec.rb": 0.6596782207489014, + "spec/lib/feature_management_spec.rb": 0.05297350883483887, + "spec/controllers/reauthn_required_controller_spec.rb": 0.14781570434570312, + "spec/presenters/verify/otp_delivery_method_presenter_spec.rb": 0.0024442672729492188, + "spec/views/sign_up/registrations/new.html.slim_spec.rb": 0.043694496154785156, + "spec/helpers/application_helper_spec.rb": 0.011135101318359375, + "spec/controllers/accounts_controller_spec.rb": 0.17741727828979492, + "spec/services/completions_decider_spec.rb": 0.014150619506835938, + "spec/features/idv/max_attempts_spec.rb": 3.353008508682251, + "spec/features/idv/usps_verification_spec.rb": 4.886984825134277, + "spec/views/sign_up/passwords/new.html.slim_spec.rb": 0.14666056632995605, + "spec/controllers/sign_up/completions_controller_spec.rb": 0.3774387836456299, + "spec/controllers/users/emails_controller_spec.rb": 1.016021966934204, + "spec/controllers/openid_connect/user_info_controller_spec.rb": 0.0719907283782959, + "spec/features/visitors/phone_confirmation_spec.rb": 2.010852098464966, + "spec/services/create_account_verified_event_spec.rb": 0.04576611518859863, + "spec/services/saml_request_validator_spec.rb": 0.019919633865356445, + "spec/controllers/users/totp_setup_controller_spec.rb": 2.0150365829467773, + "spec/models/agency_spec.rb": 0.007433176040649414, + "spec/controllers/sign_up/emails_controller_spec.rb": 0.026720285415649414, + "spec/forms/reset_password_form_spec.rb": 1.023256778717041, + "spec/services/encrypted_attribute_spec.rb": 0.056391000747680664, + "spec/controllers/verify/come_back_later_controller_spec.rb": 0.04928183555603027, + "spec/services/id_token_builder_spec.rb": 0.22456741333007812, + "spec/features/visitors/navigation_spec.rb": 0.044025421142578125, + "spec/view_models/sign_up_completions_show_spec.rb": 0.0949711799621582, + "spec/jobs/sms_otp_sender_job_spec.rb": 0.012763261795043945, + "spec/services/database_health_checker_spec.rb": 0.004609823226928711, + "spec/models/usps_confirmation_code_spec.rb": 0.19820117950439453, + "spec/views/two_factor_authentication_setup/index.html.slim_spec.rb": 0.06401348114013672, + "spec/services/pii/encryptor_spec.rb": 0.005594730377197266, + "spec/models/nonexistent_user_spec.rb": 0.00439000129699707, + "spec/services/analytics_spec.rb": 0.05577898025512695, + "spec/controllers/concerns/user_session_context_spec.rb": 0.008252859115600586, + "spec/features/two_factor_authentication/sign_in_via_personal_key_spec.rb": 0.6739380359649658, + "spec/services/idv/upcase_vendor_env_vars_spec.rb": 0.003527402877807617, + "spec/views/layouts/user_mailer.html.slim_spec.rb": 0.13714957237243652, + "spec/jobs/voice_otp_sender_job_spec.rb": 0.4360339641571045, + "spec/lib/tasks/dev_rake_spec.rb": 0.811450719833374, + "spec/view_models/account_show_spec.rb": 0.02911853790283203, + "spec/features/saml/loa1_sso_spec.rb": 14.987728118896484, + "spec/presenters/saml_request_presenter_spec.rb": 0.0062482357025146484, + "spec/features/load_testing/email_sign_up_spec.rb": 0.5362625122070312, + "spec/services/secure_headers_whitelister_spec.rb": 0.0058612823486328125, + "spec/views/two_factor_authentication/personal_key_verification/show.html.slim_spec.rb": 0.14450454711914062, + "spec/presenters/two_factor_auth_code/authenticator_delivery_presenter_spec.rb": 0.004559040069580078, + "spec/features/idv/previous_address_spec.rb": 0.8982112407684326, + "spec/services/uri_service_spec.rb": 0.007273435592651367, + "spec/services/usps_confirmation_maker_spec.rb": 0.1388988494873047, + "spec/lib/i18n_override_spec.rb": 0.005015850067138672, + "spec/models/authorization_spec.rb": 0.1811199188232422, + "spec/forms/update_user_email_form_spec.rb": 1.088576078414917, + "spec/features/saml/idp_initiated_slo_spec.rb": 4.874002933502197, + "spec/services/key_rotator/attribute_encryption_spec.rb": 0.04194307327270508, + "spec/views/verify/_hardfail4.html.slim_spec.rb": 0.014057159423828125, + "spec/forms/otp_delivery_selection_form_spec.rb": 0.13730192184448242, + "spec/views/sign_up/email_resend/new.html.slim_spec.rb": 0.019286155700683594, + "spec/services/null_twilio_client_spec.rb": 0.0022110939025878906, + "spec/controllers/verify/confirmations_controller_spec.rb": 0.7694520950317383, + "spec/controllers/users/verify_personal_key_controller_spec.rb": 0.4001772403717041, + "spec/views/shared/_footer_lite.html.slim_spec.rb": 0.0685584545135498, + "spec/views/two_factor_authentication/shared/max_login_attempts_reached.html.erb_spec.rb": 0.0118255615234375, + "spec/features/session/decryption_spec.rb": 0.2482471466064453, + "spec/features/visitors/set_password_spec.rb": 2.215163469314575, + "spec/services/personal_key_generator_spec.rb": 0.3567509651184082, + "spec/presenters/two_factor_auth_code/generic_delivery_presenter_spec.rb": 0.004991292953491211, + "spec/services/attribute_asserter_spec.rb": 0.9589550495147705, + "spec/requests/openid_connect_cors_spec.rb": 0.1798079013824463, + "spec/presenters/openid_connect_configuration_presenter_spec.rb": 0.002230405807495117, + "spec/features/users/password_recovery_via_recovery_code_spec.rb": 18.8932204246521, + "spec/controllers/application_controller_spec.rb": 2.604541063308716, + "spec/services/otp_rate_limiter_spec.rb": 0.11582660675048828, + "spec/presenters/two_factor_auth_code/phone_delivery_presenter_spec.rb": 0.03949570655822754, + "spec/services/identity_linker_spec.rb": 0.1719038486480713, + "spec/views/devise/passwords/new.html.slim_spec.rb": 0.07641816139221191, + "spec/controllers/users/verify_password_controller_spec.rb": 0.38100528717041016, + "spec/decorators/event_decorator_spec.rb": 0.002351522445678711, + "spec/features/two_factor_authentication/sign_in_spec.rb": 14.74148154258728, + "spec/views/forgot_password/show.html.slim_spec.rb": 0.08753395080566406, + "spec/services/pii/fingerprinter_spec.rb": 0.017343521118164062, + "spec/controllers/openid_connect/logout_controller_spec.rb": 0.24807190895080566, + "spec/controllers/openid_connect/certs_controller_spec.rb": 0.009980201721191406, + "spec/controllers/sign_up/email_resend_controller_spec.rb": 0.8763036727905273, + "spec/features/idv/phone_spec.rb": 5.999727487564087, + "spec/services/openid_connect_attribute_scoper_spec.rb": 0.014177083969116211, + "spec/controllers/concerns/idv_step_concern_spec.rb": 0.41180920600891113, + "spec/controllers/two_factor_authentication/totp_verification_controller_spec.rb": 0.6080248355865479, + "spec/forms/user_phone_form_spec.rb": 0.6127245426177979, + "spec/forms/update_user_password_form_spec.rb": 1.0144028663635254, + "spec/controllers/verify/address_controller_spec.rb": 0.10412955284118652, + "spec/lib/production_database_configuration_spec.rb": 0.03624248504638672, + "spec/controllers/health/database_controller_spec.rb": 0.021276473999023438, + "spec/services/usps_confirmation_entry_spec.rb": 0.02858877182006836, + "spec/presenters/fully_signed_in_modal_presenter_spec.rb": 0.005531787872314453, + "spec/lib/fingerprinter_spec.rb": 0.002787351608276367, + "spec/features/two_factor_authentication/change_factor_spec.rb": 8.18818473815918, + "spec/models/profile_spec.rb": 0.801518440246582, + "spec/controllers/health/workers_controller_spec.rb": 0.017624378204345703, + "spec/controllers/openid_connect/authorization_controller_spec.rb": 0.746269941329956, + "spec/views/verify/_no_sp_hardfail.html.slim_spec.rb": 0.01296687126159668, + "spec/decorators/service_provider_session_decorator_spec.rb": 0.03127765655517578, + "spec/features/accessibility/idv_pages_spec.rb": 8.181209087371826, + "spec/features/session/timeout_spec.rb": 0.12663817405700684, + "spec/features/visitors/sign_up_with_email_spec.rb": 2.129502058029175, + "spec/forms/resend_email_confirmation_form_spec.rb": 0.06794166564941406, + "spec/controllers/voice/otp_controller_spec.rb": 3.840808153152466, + "spec/lib/headers_filter_spec.rb": 0.0028104782104492188, + "spec/features/users/sign_in_spec.rb": 29.498939037322998, + "spec/services/request_key_manager_spec.rb": 0.0025196075439453125, + "spec/services/random_phrase_spec.rb": 0.011853933334350586, + "spec/views/two_factor_authentication/otp_verification/show.html.slim_spec.rb": 0.6623010635375977, + "spec/features/saml/loa1/account_creation_spec.rb": 0.9472696781158447, + "spec/controllers/users/two_factor_authentication_setup_controller_spec.rb": 0.2068028450012207, + "spec/forms/idv/address_delivery_method_form_spec.rb": 0.004529714584350586, + "spec/decorators/identity_decorator_spec.rb": 0.04321479797363281, + "spec/controllers/sign_out_controller_spec.rb": 0.04851484298706055, + "spec/models/service_provider_spec.rb": 0.062378883361816406, + "spec/features/openid_connect/openid_connect_spec.rb": 22.434062480926514, + "spec/controllers/verify/sessions_controller_spec.rb": 1.210376262664795, + "spec/deploy/activate_spec.rb": 0.09220552444458008, + "spec/services/openid_connect_redirector_spec.rb": 0.026537418365478516, + "spec/services/update_user_spec.rb": 0.017661571502685547, + "spec/services/email_confirmation_token_validator_spec.rb": 0.03945326805114746, + "spec/views/accounts/show.html.slim_spec.rb": 0.9790208339691162, + "spec/services/service_provider_config_spec.rb": 0.002758026123046875, + "spec/models/service_provider_request_spec.rb": 0.006059885025024414, + "spec/views/layouts/application.html.slim_spec.rb": 2.376565456390381, + "spec/decorators/usps_decorator_spec.rb": 0.061933040618896484, + "spec/lib/aws/ses_spec.rb": 0.02424454689025879, + "spec/controllers/verify/otp_delivery_method_controller_spec.rb": 0.21142148971557617, + "spec/services/phone_number_capabilities_spec.rb": 0.007938623428344727, + "spec/lib/tasks/rotate_rake_spec.rb": 0.05372190475463867, + "spec/services/agency_seeder_spec.rb": 0.3446023464202881, + "spec/jobs/idv/phone_job_spec.rb": 0.01353311538696289, + "spec/services/idv/usps_mail_spec.rb": 0.12196493148803711, + "spec/lib/config_validator_spec.rb": 0.0029556751251220703, + "spec/controllers/users_controller_spec.rb": 0.1290736198425293, + "spec/services/link_agency_identities_spec.rb": 0.3420584201812744, + "spec/services/user_access_key_spec.rb": 0.2587099075317383, + "spec/services/idv/profile_step_spec.rb": 0.1603386402130127, + "spec/services/pii/cipher_spec.rb": 0.00513911247253418, + "spec/features/accessibility/visitor_pages_spec.rb": 1.5659127235412598, + "spec/features/users/verify_profile_spec.rb": 1.837984323501587, + "spec/controllers/forgot_password_controller_spec.rb": 0.022332191467285156, + "spec/services/service_provider_seeder_spec.rb": 0.30271053314208984, + "spec/presenters/openid_connect_certs_presenter_spec.rb": 0.0016524791717529297, + "spec/requests/rack_attack_spec.rb": 1.4524259567260742, + "spec/forms/openid_connect_authorize_form_spec.rb": 0.15820026397705078, + "spec/services/pii/cacher_spec.rb": 0.41342902183532715, + "spec/decorators/user_decorator_spec.rb": 0.6349921226501465, + "spec/features/saml/saml_spec.rb": 7.28932785987854, + "spec/features/users/sign_up_spec.rb": 9.32424545288086, + "spec/services/multi_health_checker_spec.rb": 0.004421234130859375, + "spec/services/usps_uploader_spec.rb": 0.028224945068359375, + "spec/services/idv/session_spec.rb": 0.2105872631072998, + "spec/views/users/emails/edit.html.slim_spec.rb": 0.048952579498291016, + "spec/views/shared/_nav_lite.html.slim_spec.rb": 0.010764598846435547, + "spec/features/users/sign_out_spec.rb": 0.17313599586486816, + "spec/models/usps_confirmation_spec.rb": 0.02008819580078125, + "spec/controllers/sign_up/personal_keys_controller_spec.rb": 0.26556921005249023, + "spec/forms/openid_connect_token_form_spec.rb": 0.967048168182373, + "spec/presenters/eastern_time_presenter_spec.rb": 0.001943826675415039, + "spec/services/active_profile_encryptor_spec.rb": 0.06891202926635742, + "spec/services/basic_auth_url_spec.rb": 0.004117012023925781, + "spec/controllers/openid_connect/token_controller_spec.rb": 0.18847179412841797, + "spec/views/reactivate_account/index.html.slim_spec.rb": 0.047515869140625, + "spec/view_models/verify/base_spec.rb": 0.007755756378173828, + "spec/services/pii/session_store_spec.rb": 0.009895563125610352, + "spec/views/users/delete/show.html.slim_spec.rb": 0.18936753273010254, + "spec/models/user_spec.rb": 0.67449951171875, + "spec/presenters/utc_time_presenter_spec.rb": 0.002670764923095703, + "spec/controllers/verify/review_controller_spec.rb": 1.2566099166870117, + "spec/services/pii/re_encryptor_spec.rb": 0.158766508102417, + "spec/features/saml/sp_initiated_slo_spec.rb": 13.137084722518921, + "spec/controllers/sign_up/passwords_controller_spec.rb": 0.11266326904296875, + "spec/views/devise/mailer/confirmation_instructions.html.slim_spec.rb": 0.15828180313110352, + "spec/jobs/idv/profile_job_spec.rb": 0.03270840644836426, + "spec/svg_spec.rb": 0.19542670249938965, + "spec/controllers/sign_up/registrations_controller_spec.rb": 1.4633290767669678, + "spec/models/otp_requests_tracker_spec.rb": 0.03232693672180176, + "spec/views/two_factor_authentication/totp_verification/show.html.slim_spec.rb": 0.3327643871307373, + "spec/services/reactivate_account_session_spec.rb": 0.21663618087768555, + "spec/views/devise/sessions/new.html.slim_spec.rb": 0.3100268840789795, + "spec/features/idv/flow_spec.rb": 20.391412258148193, + "spec/views/verify/come_back_later/show.html.slim_spec.rb": 0.044745445251464844, + "spec/controllers/users/two_factor_authentication_controller_spec.rb": 1.154895544052124, + "spec/features/visitors/email_confirmation_spec.rb": 3.8671469688415527, + "spec/forms/personal_key_form_spec.rb": 0.13913989067077637, + "spec/requests/page_not_found_spec.rb": 0.05068850517272949, + "spec/forms/register_user_email_form_spec.rb": 0.429274320602417, + "spec/views/sign_up/completions/show.html.slim_spec.rb": 0.14742016792297363, + "spec/features/idv/interrupted_session_spec.rb": 0.8815438747406006, + "spec/controllers/verify/phone_controller_spec.rb": 0.5535168647766113, + "spec/controllers/openid_connect/configuration_controller_spec.rb": 0.016040325164794922, + "spec/controllers/users/phones_controller_spec.rb": 0.2789463996887207, + "spec/services/idv/phone_step_spec.rb": 0.06299352645874023, + "spec/services/pii/attributes_spec.rb": 0.05000448226928711, + "spec/services/idv/profile_maker_spec.rb": 0.13973498344421387, + "spec/features/idv/account_creation_spec.rb": 58.99188446998596, + "spec/views/sign_up/registrations/show.html.slim_spec.rb": 0.11463713645935059, + "spec/services/form_response_spec.rb": 0.012616395950317383, + "spec/view_models/forgot_password_show_spec.rb": 0.0018150806427001953, + "spec/features/account_history_spec.rb": 0.3339567184448242, + "spec/controllers/two_factor_authentication/otp_verification_controller_spec.rb": 2.3806405067443848, + "spec/features/users/user_edit_spec.rb": 4.289666175842285, + "spec/controllers/verify_controller_spec.rb": 0.5461723804473877, + "spec/features/visitors/i18n_spec.rb": 0.7698218822479248, + "spec/forms/openid_connect_logout_form_spec.rb": 0.49080419540405273, + "spec/controllers/mfa_confirmation_controller_spec.rb": 0.2582416534423828, + "spec/services/file_encryptor_spec.rb": 0.0436246395111084, + "spec/views/users/phones/edit.html.slim_spec.rb": 0.09602212905883789, + "spec/requests/i18n_spec.rb": 0.10391592979431152, + "spec/forms/idv/phone_form_spec.rb": 1.2381629943847656, + "spec/forms/totp_setup_form_spec.rb": 0.04805493354797363, + "spec/presenters/partially_signed_in_modal_presenter_spec.rb": 0.008043527603149414, + "spec/models/null_identity_spec.rb": 0.0018167495727539062, + "spec/controllers/two_factor_authentication/personal_key_verification_controller_spec.rb": 0.44376420974731445, + "spec/services/usps_exporter_spec.rb": 0.24862337112426758, + "spec/lib/i18n_converter_spec.rb": 0.02085423469543457, + "spec/models/identity_spec.rb": 0.4868595600128174, + "spec/presenters/openid_connect_user_info_presenter_spec.rb": 0.09418439865112305, + "spec/i18n_spec.rb": 91.71177530288696, + "spec/views/verify/usps/index.html.slim_spec.rb": 0.030670881271362305, + "spec/controllers/sign_up/email_confirmations_controller_spec.rb": 0.589585542678833, + "spec/views/verify/fail.html.slim_spec.rb": 0.06615209579467773, + "spec/lib/no_retry_jobs_spec.rb": 0.006979465484619141, + "spec/controllers/users/delete_controller_spec.rb": 0.31728458404541016, + "spec/forms/otp_verification_form_spec.rb": 0.05375027656555176, + "spec/controllers/saml_idp_controller_spec.rb": 10.063886165618896, + "spec/views/shared/_nav_branded.html.slim_spec.rb": 0.020441532135009766, + "spec/routing/id_verification_routing_spec.rb": 4.729284286499023, + "spec/controllers/users/sessions_controller_spec.rb": 1.4109222888946533, + "spec/lib/sidekiq_logging_formatter_spec.rb": 0.004430055618286133, + "spec/views/accounts/_nav_auth.html.slim_spec.rb": 0.07155799865722656, + "spec/controllers/verify/usps_controller_spec.rb": 0.17763805389404297, + "spec/models/null_service_provider_spec.rb": 0.01243448257446289, + "spec/controllers/users/personal_keys_controller_spec.rb": 0.3106074333190918, + "spec/requests/openid_connect_authorize_spec.rb": 0.49600768089294434, + "spec/services/encrypted_key_maker_spec.rb": 0.0755319595336914, + "spec/services/request_password_reset_spec.rb": 0.052195072174072266, + "spec/services/agency_identity_linker_spec.rb": 0.3087284564971924, + "spec/services/idv/attempter_spec.rb": 0.10491800308227539, + "spec/features/users/regenerate_personal_key_spec.rb": 7.699583053588867, + "spec/decorators/openid_connect_authorize_decorator_spec.rb": 0.0014214515686035156, + "spec/services/phone_formatter_spec.rb": 0.0071485042572021484, + "spec/features/twilio/voice_spec.rb": 0.44109559059143066, + "spec/controllers/users/passwords_controller_spec.rb": 0.4353454113006592, + "spec/services/idv/vendor_result_spec.rb": 0.007738590240478516, + "spec/services/pii/attribute_spec.rb": 0.0023670196533203125, + "spec/features/accessibility/static_pages_spec.rb": 1.085855484008789, + "spec/services/key_rotator/hmac_fingerprinter_spec.rb": 0.1556539535522461, + "spec/views/verify/review/new.html.slim_spec.rb": 0.1504976749420166, + "spec/views/shared/_address.html.slim_spec.rb": 0.0063664913177490234, + "spec/helpers/session_timeout_warning_helper_spec.rb": 0.016561269760131836, + "spec/services/vendor_validator_result_storage_spec.rb": 0.005162239074707031, + "spec/views/verify/activated.html.slim_spec.rb": 0.015904664993286133, + "spec/requests/headers_spec.rb": 0.3333923816680908, + "spec/controllers/service_provider_controller_spec.rb": 0.04184269905090332, + "spec/features/visitors/resend_email_confirmation_spec.rb": 0.9515554904937744, + "spec/config/initializers/zxcvbn_overrides_spec.rb": 0.16351008415222168, + "spec/decorators/session_decorator_spec.rb": 0.015351057052612305, + "spec/requests/edit_user_spec.rb": 2.8019626140594482, + "spec/views/users/passwords/edit.html.slim_spec.rb": 0.11353373527526855, + "spec/services/idv/submit_idv_job_spec.rb": 0.028253555297851562, + "spec/models/event_spec.rb": 0.008981704711914062, + "spec/requests/constrained_route_spec.rb": 0.5246772766113281, + "spec/services/pii/nist_encryption_spec.rb": 0.06160473823547363, + "spec/forms/password_form_spec.rb": 1.0038785934448242, + "spec/controllers/users/verify_profile_phone_controller_spec.rb": 0.15323495864868164, + "spec/controllers/pages_controller_spec.rb": 0.07193756103515625 +} diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 50dce1ca0bd..320d249d6a6 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,3 +1,6 @@ +require 'knapsack' +Knapsack::Adapters::RSpecAdapter.bind + if ENV['COVERAGE'] require 'simplecov' SimpleCov.start 'rails' do From 99a9973f4c9d52d0bcb738dbc55f7aa713a8e0ff Mon Sep 17 00:00:00 2001 From: Tom Black Date: Tue, 27 Mar 2018 13:07:00 -0700 Subject: [PATCH 02/27] Change name of CBP OARS to ROAM **Why**: The CBP OARS app is being renamed to ROAM. This just updates their friendly name for brand consistency, leaving other config details the same. --- config/service_providers.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/service_providers.yml b/config/service_providers.yml index 30c0f6b7309..9c95d6c7df4 100644 --- a/config/service_providers.yml +++ b/config/service_providers.yml @@ -389,11 +389,11 @@ production: - 'https://ttp.cbp.dhs.gov' return_to_sp_url: https://ttp.cbp.dhs.gov/ - # CBP OARS + # CBP ROAM (formerly OARS) 'urn:gov:dhs.cbp.pspd.oars:openidconnect:prod:app': agency_id: 1 uuid_priority: 20 - friendly_name: 'CBP OARS' + friendly_name: 'CBP ROAM' agency: 'DHS' logo: 'cbp.png' redirect_uris: From fc2c9d450bcf3632a5ecf71da2fb7f209ffc53d7 Mon Sep 17 00:00:00 2001 From: TC Baxter Date: Tue, 27 Mar 2018 16:29:02 -0500 Subject: [PATCH 03/27] Updated Gemfile **Why** out-of-date parser gem was causing build problems. --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index a0e8a656870..1b0dd309599 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -369,7 +369,7 @@ GEM childprocess (~> 0.6, >= 0.6.3) iniparse (~> 1.4) parallel (1.12.1) - parser (2.5.0.4) + parser (2.5.0.5) ast (~> 2.4.0) pg (1.0.0) phonelib (0.6.19) From d2107179444413bc848380d6f4f8853b18e6d7d1 Mon Sep 17 00:00:00 2001 From: Moncef Belyamani Date: Tue, 27 Mar 2018 22:02:55 -0400 Subject: [PATCH 04/27] Update Devise from 4.4.1 to 4.4.3 --- Gemfile.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 1b0dd309599..0c4cfcf68c4 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -213,10 +213,10 @@ GEM descendants_tracker (0.0.4) thread_safe (~> 0.3, >= 0.3.1) device_detector (1.0.0) - devise (4.4.1) + devise (4.4.3) bcrypt (~> 3.0) orm_adapter (~> 0.1) - railties (>= 4.1.0, < 5.2) + railties (>= 4.1.0, < 6.0) responders warden (~> 1.2.3) diff-lcs (1.3) @@ -236,7 +236,7 @@ GEM encryptor (3.0.0) equalizer (0.0.11) errbase (0.1.0) - erubi (1.7.0) + erubi (1.7.1) ethon (0.11.0) ffi (>= 1.3.0) eventmachine (1.2.5) @@ -336,7 +336,7 @@ GEM activesupport (>= 4) railties (>= 4) request_store (~> 1.0) - loofah (2.2.0) + loofah (2.2.2) crass (~> 1.0.2) nokogiri (>= 1.5.9) lumberjack (1.0.11) @@ -407,7 +407,7 @@ GEM rack rack-proxy (0.6.3) rack - rack-test (0.8.2) + rack-test (1.0.0) rack (>= 1.0, < 3) rack-timeout (0.4.2) rack_session_access (0.1.1) @@ -437,8 +437,8 @@ GEM activesupport (>= 3.2) choice (~> 0.2.0) ruby-graphviz (~> 1.2) - rails-html-sanitizer (1.0.3) - loofah (~> 2.0) + rails-html-sanitizer (1.0.4) + loofah (~> 2.2, >= 2.2.2) railties (5.1.5) actionpack (= 5.1.5) activesupport (= 5.1.5) @@ -446,7 +446,7 @@ GEM rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) rainbow (3.0.0) - rake (12.3.0) + rake (12.3.1) randexp (0.1.7) rb-fsevent (0.9.8) rb-inotify (0.9.8) From 78b92c64e9af95419819618ca4c003e8a25d363f Mon Sep 17 00:00:00 2001 From: David Corwin Date: Wed, 28 Mar 2018 11:18:47 -0700 Subject: [PATCH 05/27] Add configuration and certificate for new SP **WHY** Because Elixir is an up and coming language and its nice to have more SP examples. --- certs/sp/sp_phoenix_demo.crt | 21 +++++++++++++++++++++ config/service_providers.yml | 8 ++++++++ 2 files changed, 29 insertions(+) create mode 100644 certs/sp/sp_phoenix_demo.crt diff --git a/certs/sp/sp_phoenix_demo.crt b/certs/sp/sp_phoenix_demo.crt new file mode 100644 index 00000000000..f1539fe168e --- /dev/null +++ b/certs/sp/sp_phoenix_demo.crt @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDgDCCAmgCCQCwpieA9CKuDDANBgkqhkiG9w0BAQUFADCBgTEYMBYGA1UEAwwP +U1AgU2luYXRyYSBEZW1vMQwwCgYDVQQKDANHU0ExDDAKBgNVBAsMAzE4ZjETMBEG +A1UEBwwKV2FzaGluZ3RvbjELMAkGA1UECAwCREMxCzAJBgNVBAYTAlVTMRowGAYJ +KoZIhvcNAQkBFgsxOGZAZ3NhLmdvdjAeFw0xNjA4MTgyMDI5MTFaFw0yNjA4MTYy +MDI5MTFaMIGBMRgwFgYDVQQDDA9TUCBTaW5hdHJhIERlbW8xDDAKBgNVBAoMA0dT +QTEMMAoGA1UECwwDMThmMRMwEQYDVQQHDApXYXNoaW5ndG9uMQswCQYDVQQIDAJE +QzELMAkGA1UEBhMCVVMxGjAYBgkqhkiG9w0BCQEWCzE4ZkBnc2EuZ292MIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxh42KlIlEGtl/6NOfN+5tSg/eggU +sW0dYdWIhshawe7h/9EhJemABXGI+VIiYHOt9QPE3HZ9ky2rUv7iC0MslIvI2sdQ +0aPPaYYCXbh8iU2kYEcRPIU9g5NNlKHyUS6jp5HDWeRmN2lF03/dBcnRl9VWPOmH +C9iS44xihTimcTZjlMfd59WXSNSbUACGR7vNjAA4N/DnqEUCWd9h016QgtRll6Qj +jSVBGmaHZjpOWsP+2I7evx51rUinGsgHuihxFT5dL/EcJ3RsncKYku47ekyAMMsm +2sJecLgUk4YPvdQzafK/7jeyCtBFcyRTvBs7yapgcuW+LW8PUfu7NT+vTQIDAQAB +MA0GCSqGSIb3DQEBBQUAA4IBAQBO3eTacRFKnFjQ9OCLXzJx0nt64jlQeiiElePe +i3l6t8YYYf81Lt2PG8kqs2/NJ1enKSFIH9bHM2chv82zKXgLUumCsLLo45MbxLEQ +fZfzbRYDxKWcOuf4yLrjL4bp7Bv0onnG9hSCLT9yTFskwEP6W9XW44W50RhrOfYN +Bfrscg6b8uq15y5WrH+A9wzDlZfvH7ouNAnWrp0GXI6LN8vVPYX0vBfZuiOqI32H +IYOalU+bIBpQt6EGN/mWBu7yZtgxKULZamJUUpd5xpcPcGKwf59etPVMTSxgeeQY +MFjibtIlMmAweHgIqDyF2s8Etz8hlcKrXIUAK5CoMvgUn41V +-----END CERTIFICATE----- diff --git a/config/service_providers.yml b/config/service_providers.yml index 30c0f6b7309..d18cfd4424c 100644 --- a/config/service_providers.yml +++ b/config/service_providers.yml @@ -173,6 +173,14 @@ development: - 'http://localhost:8080/' - 'http://localhost:8080/auth/login-gov/callback' + 'urn:gov:gsa:openidconnect:sp:phoenix': + agency: 'GSA' + cert: 'sp_phoenix_demo' + friendly_name: 'Example OIDC Client (Phoenix)' + logo: '18f.svg' + redirect_uris: + - 'http://localhost:4000/' + production: 'https://idp.dev.login.gov': metadata_url: 'https://idp.dev.login.gov/api/saml/metadata' From 594facae7b80a8e9007f0e06a83c14d23f247531 Mon Sep 17 00:00:00 2001 From: Tom Black Date: Wed, 28 Mar 2018 12:57:13 -0700 Subject: [PATCH 06/27] Add USDA SP logo --- app/assets/images/sp-logos/usda.svg | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 app/assets/images/sp-logos/usda.svg diff --git a/app/assets/images/sp-logos/usda.svg b/app/assets/images/sp-logos/usda.svg new file mode 100644 index 00000000000..d8f492a1dd2 --- /dev/null +++ b/app/assets/images/sp-logos/usda.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + From 0476a9991e8acc47b88ee9906b9aa809cf9cfe7c Mon Sep 17 00:00:00 2001 From: Moncef Belyamani Date: Wed, 28 Mar 2018 13:33:19 -0400 Subject: [PATCH 07/27] Refactor deploy/activate script **Why**: If the `deploy/activate` script is a shell script, it requires calling `Bundler.setup` so that the files that the script depends on are loaded. The problem is that the `Bundler.setup` call was preventing us from running parallel builds in Circle CI. I removed the `Bundler.setup` call in #2060 to see if that would allow parallel builds, which it did, but I forgot to check if this would break build deployment, and it did. In order to allow the script to run during deployment and also allow parallel builds to work, I defined a shell script that will fetch the config from S3 by calling the ruby file directly using `bundle exec`. That way, the gems will already be loaded. This also separates concerns and makes it easier to test the S3 fetching in isolation. It also keeps things consistent with the other scripts in the `deploy` directory. --- bin/activate | 5 ++ deploy/activate | 64 +++++-------------- lib/deploy/activate.rb | 53 ++++++++++++++++ spec/deploy/activate_spec.rb | 102 ------------------------------- spec/lib/deploy/activate_spec.rb | 99 ++++++++++++++++++++++++++++++ 5 files changed, 171 insertions(+), 152 deletions(-) create mode 100755 bin/activate create mode 100644 lib/deploy/activate.rb delete mode 100644 spec/deploy/activate_spec.rb create mode 100644 spec/lib/deploy/activate_spec.rb diff --git a/bin/activate b/bin/activate new file mode 100755 index 00000000000..844657f8745 --- /dev/null +++ b/bin/activate @@ -0,0 +1,5 @@ +#!/usr/bin/env ruby + +load File.expand_path('../lib/deploy/activate.rb', File.dirname(__FILE__)) + +Deploy::Activate.new.run diff --git a/deploy/activate b/deploy/activate index 901f652be36..30b6de9d7b7 100755 --- a/deploy/activate +++ b/deploy/activate @@ -1,58 +1,22 @@ -#!/usr/bin/env ruby +#!/bin/bash -require 'active_support/core_ext/hash/deep_merge' -require 'logger' -require 'login_gov/hostdata' -require 'yaml' +# This script is called by identity-devops cookbooks as part of the deployment +# process. It fetches the latest application.yml from S3 to ensure the app is +# properly configured. -module Deploy - class Activate - attr_reader :logger, :s3_client +set -euo pipefail - def initialize(logger: default_logger, s3_client: nil) - @logger = logger - @s3_client = s3_client - end +echo "deploy/activate starting" +echo "HOME: ${HOME-}" +cd "$(dirname "$0")/.." - # rubocop:disable Metrics/AbcSize - def run - logger.info "app root: #{root}" +set -x - LoginGov::Hostdata.s3(logger: logger, s3_client: s3_client).download_configs( - '/%s/idp/v1/application.yml' => env_yaml_path - ) +id +which bundle - application_config = YAML.load_file(example_application_yaml_path). - deep_merge(YAML.load_file(env_yaml_path)) +bundle exec bin/activate - File.open(result_yaml_path, 'w') { |file| file.puts YAML.dump(application_config) } +set +x - FileUtils.chmod(0o640, [env_yaml_path, result_yaml_path]) - end - # rubocop:enable Metrics/AbcSize - - def default_logger - logger = Logger.new(STDOUT) - logger.progname = 'deploy/activate' - logger - end - - def root - File.expand_path('../../', __FILE__) - end - - def env_yaml_path - File.join(root, 'config/application_s3_env.yml') - end - - def example_application_yaml_path - File.join(root, 'config/application.yml.example') - end - - def result_yaml_path - File.join(root, 'config/application.yml') - end - end -end - -Deploy::Activate.new.run if $PROGRAM_NAME == __FILE__ +echo "deploy/activate finished" diff --git a/lib/deploy/activate.rb b/lib/deploy/activate.rb new file mode 100644 index 00000000000..a7e710269b7 --- /dev/null +++ b/lib/deploy/activate.rb @@ -0,0 +1,53 @@ +require 'active_support/core_ext/hash/deep_merge' +require 'logger' +require 'login_gov/hostdata' +require 'yaml' + +module Deploy + class Activate + attr_reader :logger, :s3_client + + def initialize(logger: default_logger, s3_client: nil) + @logger = logger + @s3_client = s3_client + end + + def run + LoginGov::Hostdata.s3(logger: logger, s3_client: s3_client).download_configs( + '/%s/idp/v1/application.yml' => env_yaml_path + ) + + File.open(result_yaml_path, 'w') { |file| file.puts YAML.dump(application_config) } + + FileUtils.chmod(0o640, [env_yaml_path, result_yaml_path]) + end + + private + + def default_logger + logger = Logger.new(STDOUT) + logger.progname = 'deploy/activate' + logger + end + + def env_yaml_path + File.join(root, 'config/application_s3_env.yml') + end + + def root + File.expand_path('../../../', __FILE__) + end + + def application_config + YAML.load_file(example_application_yaml_path).deep_merge(YAML.load_file(env_yaml_path)) + end + + def example_application_yaml_path + File.join(root, 'config/application.yml.example') + end + + def result_yaml_path + File.join(root, 'config/application.yml') + end + end +end diff --git a/spec/deploy/activate_spec.rb b/spec/deploy/activate_spec.rb deleted file mode 100644 index 333d0db8336..00000000000 --- a/spec/deploy/activate_spec.rb +++ /dev/null @@ -1,102 +0,0 @@ -require 'spec_helper' -require 'fakefs/spec_helpers' -require 'login_gov/hostdata/fake_s3_client' - -load File.expand_path('../../deploy/activate', File.dirname(__FILE__)) - -RSpec.describe 'deploy/activate' do - let(:app_root) { File.expand_path('../../', File.dirname(__FILE__)) } - let(:config_dir) { File.join(app_root, 'config') } - - around(:each) do |ex| - LoginGov::Hostdata.reset! - - @logger = Logger.new('/dev/null') - - FakeFS do - FakeFS::FileSystem.clone(config_dir) - - ex.run - end - end - - subject(:script) { Deploy::Activate.new(logger: logger, s3_client: s3_client) } - - let(:logger) { @logger } - let(:s3_client) { LoginGov::Hostdata::FakeS3Client.new } - let(:set_up_files!) {} - - describe '#run' do - context 'in a deployed production environment' do - before do - stub_request(:get, 'http://169.254.169.254/2016-09-02/dynamic/instance-identity/document'). - to_return(body: { - 'region' => 'us-west-1', - 'accountId' => '12345', - }.to_json) - - s3_client.put_object( - bucket: 'login-gov.app-secrets.12345-us-west-1', - key: '/int/idp/v1/application.yml', - body: application_yml - ) - - FileUtils.mkdir_p('/etc/login.gov/info') - File.open('/etc/login.gov/info/env', 'w') { |file| file.puts 'int' } - end - - let(:application_yml) do - <<~YAML - production: - usps_confirmation_max_days: '5' - YAML - end - - it 'downloads configs from s3' do - script.run - - expect(File.exist?(File.join(config_dir, 'application.yml'))).to eq(true) - end - - it 'merges the application.yml from s3 over the application.yml.example' do - script.run - - combined_application_yml = YAML.load_file(File.join(config_dir, 'application.yml')) - - # top-level key from application.yml.example - expect(combined_application_yml['recovery_code_length']).to eq('4') - # overridden production key from s3 - expect(combined_application_yml['production']['usps_confirmation_max_days']).to eq('5') - # production key from applicaiton.yml.example, not overwritten - expect(combined_application_yml['production']['lockout_period_in_minutes']).to eq('10') - end - - it 'sets the correct permissions on the YAML files' do - script.run - - application_yml = File.new(File.join(config_dir, 'application.yml')) - expect(application_yml.stat.mode.to_s(8)).to eq('100640') - - application_env_yml = File.new(File.join(config_dir, 'application_s3_env.yml')) - expect(application_env_yml.stat.mode.to_s(8)).to eq('100640') - end - end - - context 'outside a deployed production environment' do - before do - stub_request(:get, 'http://169.254.169.254/2016-09-02/dynamic/instance-identity/document'). - to_timeout - end - - it 'errors' do - expect { script.run }.to raise_error(Net::OpenTimeout) - end - end - end - - describe '#default_logger' do - it 'sets the progname' do - expect(script.default_logger.progname).to eq('deploy/activate') - end - end -end diff --git a/spec/lib/deploy/activate_spec.rb b/spec/lib/deploy/activate_spec.rb new file mode 100644 index 00000000000..c201507ee0d --- /dev/null +++ b/spec/lib/deploy/activate_spec.rb @@ -0,0 +1,99 @@ +require 'rails_helper' +require 'fakefs/spec_helpers' +require 'login_gov/hostdata/fake_s3_client' +require Rails.root.join('lib', 'deploy', 'activate.rb') + +describe Deploy::Activate do + let(:config_dir) { Rails.root.join('config') } + + around(:each) do |ex| + LoginGov::Hostdata.reset! + + @logger = Logger.new('/dev/null') + + FakeFS do + FakeFS::FileSystem.clone(config_dir) + + ex.run + end + end + + let(:logger) { @logger } + let(:s3_client) { LoginGov::Hostdata::FakeS3Client.new } + let(:set_up_files!) {} + + let(:subject) { Deploy::Activate.new(logger: logger, s3_client: s3_client) } + + context 'in a deployed production environment' do + before do + stub_request(:get, 'http://169.254.169.254/2016-09-02/dynamic/instance-identity/document'). + to_return(body: { + 'region' => 'us-west-1', + 'accountId' => '12345', + }.to_json) + + s3_client.put_object( + bucket: 'login-gov.app-secrets.12345-us-west-1', + key: '/int/idp/v1/application.yml', + body: application_yml + ) + + FileUtils.mkdir_p('/etc/login.gov/info') + File.open('/etc/login.gov/info/env', 'w') { |file| file.puts 'int' } + end + + let(:application_yml) do + <<~YAML + production: + usps_confirmation_max_days: '5' + YAML + end + + it 'downloads configs from s3' do + subject.run + + expect(File.exist?(File.join(config_dir, 'application.yml'))).to eq(true) + end + + it 'merges the application.yml from s3 over the application.yml.example' do + subject.run + + combined_application_yml = YAML.load_file(File.join(config_dir, 'application.yml')) + + # top-level key from application.yml.example + expect(combined_application_yml['recovery_code_length']).to eq('4') + # overridden production key from s3 + expect(combined_application_yml['production']['usps_confirmation_max_days']).to eq('5') + # production key from applicaiton.yml.example, not overwritten + expect(combined_application_yml['production']['lockout_period_in_minutes']).to eq('10') + end + + it 'sets the correct permissions on the YAML files' do + subject.run + + application_yml = File.new(File.join(config_dir, 'application.yml')) + expect(application_yml.stat.mode.to_s(8)).to eq('100640') + + application_env_yml = File.new(File.join(config_dir, 'application_s3_env.yml')) + expect(application_env_yml.stat.mode.to_s(8)).to eq('100640') + end + + it 'uses a default logger with a progname' do + subject = Deploy::Activate.new(s3_client: s3_client) + subject.run + + expect(subject.logger.progname).to eq('deploy/activate') + end + end + + context 'outside a deployed production environment' do + before do + stub_request(:get, 'http://169.254.169.254/2016-09-02/dynamic/instance-identity/document'). + to_timeout + end + + it 'errors' do + expect { subject.run }.to raise_error(Net::OpenTimeout) + end + end +end From 4e98ebd57beb23bf6e59696b39a5d47ba413a19b Mon Sep 17 00:00:00 2001 From: David Corwin Date: Thu, 29 Mar 2018 11:22:57 -0700 Subject: [PATCH 08/27] Fix onboarding and setup by updating Rails setup commands (#2071) * Update Rails setup commands **WHY**: - Onboarding and setup fail due to an issue with the `db:schema:load` rake task that sets the *environment* of the development database to "test", preventing subsequent rake tasks from completing successfully. - The `dev:prime` task has `db:setup` as a dependency, also triggering the above issue. **HOW**: - Until this is fixed in Rails, use `db:environment:set` before and after `db:reset` for the development environment to make sure that the *environment* is set to "development" instead of "test". - Update `dev:prime` to depend on `environment` and not `db:setup` --- bin/setup | 21 ++++++++++++--------- lib/tasks/dev.rake | 2 +- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/bin/setup b/bin/setup index 38e8293b078..56a94bb5f10 100755 --- a/bin/setup +++ b/bin/setup @@ -39,18 +39,17 @@ Dir.chdir APP_ROOT do run 'docker-compose build' run 'docker-compose run --rm web bin/generate-example-keys' run 'docker-compose run --rm web yarn install' - run 'docker-compose run --rm web rake db:reset RAILS_ENV=development' - run 'docker-compose run --rm web rake db:reset RAILS_ENV=test' + run 'docker-compose run --rm web rake db:create' + run 'docker-compose run --rm web rake db:environment:set' + run 'docker-compose run --rm web rake db:reset' + run 'docker-compose run --rm web rake db:environment:set' run 'docker-compose run --rm web rake dev:prime' + run 'docker-compose run --rm web rake db:create RAILS_ENV=test' + run 'docker-compose run --rm web rake db:reset RAILS_ENV=test' run 'docker-compose up' exit end - puts "\n== Example Key Generation ==" - run "which gpg || brew install gpg" - run "which yarn || brew install yarn" - run "bin/generate-example-keys" - puts "\n== Installing dependencies ==" run "gem install bundler --conservative" run 'gem install foreman --conservative && gem update foreman' @@ -59,8 +58,12 @@ Dir.chdir APP_ROOT do run "gem install mailcatcher" puts "\n== Preparing database ==" - run 'bin/rake db:reset RAILS_ENV=development' - run 'bin/rake dev:prime RAILS_ENV=development' + run 'bin/rake db:create' + run 'bin/rake db:environment:set' + run 'bin/rake db:reset' + run 'bin/rake db:environment:set' + run 'bin/rake dev:prime' + run 'bin/rake db:create RAILS_ENV=test' run 'bin/rake db:reset RAILS_ENV=test' puts "\n== Removing old logs and tempfiles ==" diff --git a/lib/tasks/dev.rake b/lib/tasks/dev.rake index d16d92c68f1..6fe97e301aa 100644 --- a/lib/tasks/dev.rake +++ b/lib/tasks/dev.rake @@ -1,6 +1,6 @@ namespace :dev do desc 'Sample data for local development environment' - task prime: 'db:setup' do + task prime: :environment do pw = 'salty pickles' %w[test1@test.com test2@test.com].each_with_index do |email, index| ee = EncryptedAttribute.new_from_decrypted(email) From d8a87274d45e4b7e1cdd1428be5d64ea6803a5c7 Mon Sep 17 00:00:00 2001 From: Moncef Belyamani Date: Thu, 29 Mar 2018 21:00:56 -0400 Subject: [PATCH 09/27] Upgrade Ruby from 2.3.5 to 2.3.7 **Why**: To address multiple security vulnerabilities: https://www.ruby-lang.org/en/news/2018/03/28/ruby-2-3-7-released/ - CVE-2017-17742: HTTP response splitting in WEBrick - CVE-2018-8777: DoS by large request in WEBrick - CVE-2018-6914: Unintentional file and directory creation with directory traversal in tempfile and tmpdir - CVE-2018-8778: Buffer under-read in String#unpack - CVE-2018-8779: Unintentional socket creation by poisoned NUL byte in UNIXServer and UNIXSocket - CVE-2018-8780: Unintentional directory traversal by poisoned NUL byte in Dir - Multiple vulnerabilities in RubyGems --- .circleci/config.yml | 2 +- Gemfile | 2 +- Gemfile.lock | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 94167b1c478..550ea53bfd3 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -8,7 +8,7 @@ jobs: parallelism: 4 docker: # Specify the Ruby version you desire here - - image: circleci/ruby:2.3.6-node-browsers + - image: circleci/ruby:2.3-node-browsers environment: RAILS_ENV: test CC_TEST_REPORTER_ID: faecd27e9aed532634b3f4d3e251542d7de9457cfca96a94208a63270ef9b42e diff --git a/Gemfile b/Gemfile index 4a4eab5a9e8..99952d168d3 100644 --- a/Gemfile +++ b/Gemfile @@ -1,7 +1,7 @@ source 'https://rubygems.org' git_source(:github) { |repo_name| "https://github.com/#{repo_name}.git" } -ruby '~> 2.3.5' +ruby '~> 2.3.7' gem 'rails', '~> 5.1.3' diff --git a/Gemfile.lock b/Gemfile.lock index 0c4cfcf68c4..e071c9e76c8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -754,7 +754,7 @@ DEPENDENCIES zxcvbn-js RUBY VERSION - ruby 2.3.5p376 + ruby 2.3.7p456 BUNDLED WITH - 1.16.0 + 1.16.1 From 5e53af1ee102bfc81e98717e4fdd871225445a80 Mon Sep 17 00:00:00 2001 From: Moncef Belyamani Date: Thu, 29 Mar 2018 21:29:37 -0400 Subject: [PATCH 10/27] Update brakeman from 4.2.0 to 4.2.1 --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 0c4cfcf68c4..bcf47314ef2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -159,7 +159,7 @@ GEM bindata (2.4.3) binding_of_caller (0.8.0) debug_inspector (>= 0.0.1) - brakeman (4.2.0) + brakeman (4.2.1) browser (2.5.3) builder (3.2.3) bullet (5.7.5) @@ -757,4 +757,4 @@ RUBY VERSION ruby 2.3.5p376 BUNDLED WITH - 1.16.0 + 1.16.1 From 6dd927996a43a7fbd1b70df5f1ab21af71f7d048 Mon Sep 17 00:00:00 2001 From: Moncef Belyamani Date: Thu, 29 Mar 2018 21:29:47 -0400 Subject: [PATCH 11/27] Update fakefs from 0.13.2 to 0.13.3 --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index bcf47314ef2..516a78903f0 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -249,7 +249,7 @@ GEM factory_bot_rails (4.8.2) factory_bot (~> 4.8.2) railties (>= 3.0.0) - fakefs (0.13.2) + fakefs (0.13.3) faker (1.8.7) i18n (>= 0.7) faraday (0.14.0) From 499dc0951edb09fa15224daa906356512ff178ef Mon Sep 17 00:00:00 2001 From: Moncef Belyamani Date: Thu, 29 Mar 2018 21:30:00 -0400 Subject: [PATCH 12/27] Update lograge from 0.9.0 to 0.10.0 --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 516a78903f0..e613369a0f8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -331,7 +331,7 @@ GEM rb-inotify (~> 0.9, >= 0.9.7) ruby_dep (~> 1.2) logger (1.2.8) - lograge (0.9.0) + lograge (0.10.0) actionpack (>= 4) activesupport (>= 4) railties (>= 4) @@ -460,7 +460,7 @@ GEM parser (>= 2.5.0.0, < 2.6) rainbow (~> 3.0) referer-parser (0.3.0) - request_store (1.4.0) + request_store (1.4.1) rack (>= 1.4) responders (2.4.0) actionpack (>= 4.2.0, < 5.3) From 94301915faa6389ab9b7a0ad2b47c1818a0418f8 Mon Sep 17 00:00:00 2001 From: Moncef Belyamani Date: Thu, 29 Mar 2018 21:30:11 -0400 Subject: [PATCH 13/27] Update newrelic_rpm from 4.8.0.341 to 5.0.0.342 --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index e613369a0f8..ebc1b0d6224 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -356,7 +356,7 @@ GEM net-sftp (2.1.2) net-ssh (>= 2.6.5) net-ssh (4.1.0) - newrelic_rpm (4.8.0.341) + newrelic_rpm (5.0.0.342) nio4r (2.2.0) nokogiri (1.8.2) mini_portile2 (~> 2.3.0) From af5018ae328d36fb7825b51cf1b27cdc1534481b Mon Sep 17 00:00:00 2001 From: Moncef Belyamani Date: Thu, 29 Mar 2018 21:30:21 -0400 Subject: [PATCH 14/27] Update rack-attack from 5.1.0 to 5.2.0 --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index ebc1b0d6224..f845a56b40a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -397,7 +397,7 @@ GEM pry (~> 0.10) public_suffix (3.0.2) rack (2.0.4) - rack-attack (5.1.0) + rack-attack (5.2.0) rack rack-cors (1.0.2) rack-headers_filter (0.0.1) From 170bf7eb0d90ee0d219ad250fc28011f38c8eb71 Mon Sep 17 00:00:00 2001 From: Moncef Belyamani Date: Thu, 29 Mar 2018 21:30:31 -0400 Subject: [PATCH 15/27] Update rack-mini-profiler from 0.10.7 to 1.0.0 --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index f845a56b40a..91a92667213 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -401,7 +401,7 @@ GEM rack rack-cors (1.0.2) rack-headers_filter (0.0.1) - rack-mini-profiler (0.10.7) + rack-mini-profiler (1.0.0) rack (>= 1.2.0) rack-protection (2.0.1) rack From ea12e8ea5bce1aa7fa722534b04a2802750f516a Mon Sep 17 00:00:00 2001 From: Moncef Belyamani Date: Thu, 29 Mar 2018 21:30:46 -0400 Subject: [PATCH 16/27] Update rails from 5.1.5 to 5.1.6 --- Gemfile.lock | 70 ++++++++++++++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 91a92667213..d5a784d5534 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -69,41 +69,41 @@ GIT GEM remote: https://rubygems.org/ specs: - actioncable (5.1.5) - actionpack (= 5.1.5) + actioncable (5.1.6) + actionpack (= 5.1.6) nio4r (~> 2.0) websocket-driver (~> 0.6.1) - actionmailer (5.1.5) - actionpack (= 5.1.5) - actionview (= 5.1.5) - activejob (= 5.1.5) + actionmailer (5.1.6) + actionpack (= 5.1.6) + actionview (= 5.1.6) + activejob (= 5.1.6) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (5.1.5) - actionview (= 5.1.5) - activesupport (= 5.1.5) + actionpack (5.1.6) + actionview (= 5.1.6) + activesupport (= 5.1.6) rack (~> 2.0) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (5.1.5) - activesupport (= 5.1.5) + actionview (5.1.6) + activesupport (= 5.1.6) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.3) - activejob (5.1.5) - activesupport (= 5.1.5) + activejob (5.1.6) + activesupport (= 5.1.6) globalid (>= 0.3.6) - activemodel (5.1.5) - activesupport (= 5.1.5) - activerecord (5.1.5) - activemodel (= 5.1.5) - activesupport (= 5.1.5) + activemodel (5.1.6) + activesupport (= 5.1.6) + activerecord (5.1.6) + activemodel (= 5.1.6) + activesupport (= 5.1.6) arel (~> 8.0) - activesupport (5.1.5) + activesupport (5.1.6) concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (~> 0.7) + i18n (>= 0.7, < 2) minitest (~> 5.1) tzinfo (~> 1.1) addressable (2.5.2) @@ -299,7 +299,7 @@ GEM httpi (2.4.2) rack socksify - i18n (0.9.5) + i18n (1.0.0) concurrent-ruby (~> 1.0) i18n-tasks (0.9.21) activesupport (>= 4.0.2) @@ -357,7 +357,7 @@ GEM net-ssh (>= 2.6.5) net-ssh (4.1.0) newrelic_rpm (5.0.0.342) - nio4r (2.2.0) + nio4r (2.3.0) nokogiri (1.8.2) mini_portile2 (~> 2.3.0) nori (2.6.0) @@ -413,17 +413,17 @@ GEM rack_session_access (0.1.1) builder (>= 2.0.0) rack (>= 1.0.0) - rails (5.1.5) - actioncable (= 5.1.5) - actionmailer (= 5.1.5) - actionpack (= 5.1.5) - actionview (= 5.1.5) - activejob (= 5.1.5) - activemodel (= 5.1.5) - activerecord (= 5.1.5) - activesupport (= 5.1.5) + rails (5.1.6) + actioncable (= 5.1.6) + actionmailer (= 5.1.6) + actionpack (= 5.1.6) + actionview (= 5.1.6) + activejob (= 5.1.6) + activemodel (= 5.1.6) + activerecord (= 5.1.6) + activesupport (= 5.1.6) bundler (>= 1.3.0) - railties (= 5.1.5) + railties (= 5.1.6) sprockets-rails (>= 2.0.0) rails-controller-testing (1.0.2) actionpack (~> 5.x, >= 5.0.1) @@ -439,9 +439,9 @@ GEM ruby-graphviz (~> 1.2) rails-html-sanitizer (1.0.4) loofah (~> 2.2, >= 2.2.2) - railties (5.1.5) - actionpack (= 5.1.5) - activesupport (= 5.1.5) + railties (5.1.6) + actionpack (= 5.1.6) + activesupport (= 5.1.6) method_source rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) From 7dfb731189f7de8db64117137273521b18a950bd Mon Sep 17 00:00:00 2001 From: Moncef Belyamani Date: Thu, 29 Mar 2018 21:30:56 -0400 Subject: [PATCH 17/27] Update rubocop from 0.52.1 to 0.54.0 --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index d5a784d5534..7724a9190fb 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -489,9 +489,9 @@ GEM rspec-mocks (~> 3.5.0) rspec-support (~> 3.5.0) rspec-support (3.5.0) - rubocop (0.52.1) + rubocop (0.54.0) parallel (~> 1.10) - parser (>= 2.4.0.2, < 3.0) + parser (>= 2.5) powerpack (~> 0.1) rainbow (>= 2.2.2, < 4.0) ruby-progressbar (~> 1.7) From 2fcaf88140fabc02e45964257315bcbf048d4cdb Mon Sep 17 00:00:00 2001 From: Moncef Belyamani Date: Thu, 29 Mar 2018 21:31:06 -0400 Subject: [PATCH 18/27] Update sidekiq from 5.1.1 to 5.1.2 --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 7724a9190fb..0e4e07f5cac 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -534,7 +534,7 @@ GEM shellany (0.0.1) shoulda-matchers (3.1.2) activesupport (>= 4.0.0) - sidekiq (5.1.1) + sidekiq (5.1.2) concurrent-ruby (~> 1.0) connection_pool (~> 2.2, >= 2.2.0) rack-protection (>= 1.5.0) From 1d53edcc8b6b2f3d028da45506addf51e6d0cf60 Mon Sep 17 00:00:00 2001 From: Moncef Belyamani Date: Thu, 29 Mar 2018 21:31:18 -0400 Subject: [PATCH 19/27] Update twilio-ruby from 5.7.1 to 5.7.2 --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 0e4e07f5cac..95c91b59951 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -587,7 +587,7 @@ GEM thread_safe (0.3.6) tilt (2.0.8) timecop (0.9.1) - twilio-ruby (5.7.1) + twilio-ruby (5.7.2) faraday (~> 0.9) jwt (>= 1.5, <= 2.5) nokogiri (>= 1.6, < 2.0) From f53662dabb1a02973c486ab1582fb08559eba816 Mon Sep 17 00:00:00 2001 From: Moncef Belyamani Date: Thu, 29 Mar 2018 21:31:30 -0400 Subject: [PATCH 20/27] Update two_factor_authentication from 2.0.1 to 2.1.0 --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 95c91b59951..de7e1a3a492 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -465,7 +465,7 @@ GEM responders (2.4.0) actionpack (>= 4.2.0, < 5.3) railties (>= 4.2.0, < 5.3) - rotp (3.3.0) + rotp (3.3.1) rqrcode (0.10.1) chunky_png (~> 1.0) rspec (3.5.0) @@ -591,7 +591,7 @@ GEM faraday (~> 0.9) jwt (>= 1.5, <= 2.5) nokogiri (>= 1.6, < 2.0) - two_factor_authentication (2.0.1) + two_factor_authentication (2.1.0) devise encryptor rails (>= 3.1.1) From 8af84f7de28a9f73e8b6fb23dd97c1c4e177bb3c Mon Sep 17 00:00:00 2001 From: Moncef Belyamani Date: Mon, 2 Apr 2018 20:34:12 -0400 Subject: [PATCH 21/27] Make Ahoy visit duration match session timeout **Why**: So that Ahoy's `visit_id` can be used to track a user's events within a particular session. --- config/initializers/ahoy.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/initializers/ahoy.rb b/config/initializers/ahoy.rb index 88bbf118106..6bf4544d0b6 100644 --- a/config/initializers/ahoy.rb +++ b/config/initializers/ahoy.rb @@ -1,7 +1,7 @@ Ahoy.mount = false Ahoy.throttle = false # Period of inactivity before a new visit is created -Ahoy.visit_duration = 30.minutes +Ahoy.visit_duration = Figaro.env.session_timeout_in_minutes.to_i.minutes module Ahoy class Store < Ahoy::Stores::LogStore From 72dda72ac194b3a30251f286e567da4882bac962 Mon Sep 17 00:00:00 2001 From: Andy Brody Date: Mon, 2 Apr 2018 17:54:53 -0400 Subject: [PATCH 22/27] Use system libxml2, not nokogiri bundled version. **Why**: Nokogiri includes a vendored version of the libxml2 library that ships with the gem. This is designed to ensure version compatibility in case your system is running an older version of libxml2, and to facilitate security updates by making it possible to take security updates just by upgrading nokogiri. However, on our systems this creates more problems than it solves. For reasons that I have not been able to figure out, the nokogiri compilation attempts to create temporary directories under /etc/login.gov/repos/identity-devops/kitchen/local-mode-cache/cache/, which it doesn't have permissions to do. This causes the bundle install to fail. In addition, we already get timely security updates of libxml2 from security updates of the ubuntu package. The version included in Ubuntu 16.04 is libxml2 2.9.3, which is compatible with Nokogiri. https://packages.ubuntu.com/source/xenial-updates/libxml2 Using the system libxml2 allows us to take security updates just with an apt-get upgrade, which already happens automatically as part of provisioning. **How**: Run `bundle config build.nokogiri --use-system-libraries` prior to running `bundle install` during the build process. Also run `env` as an aid to debugging to show what all of the environment variables are during provisioning. --- deploy/build | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/deploy/build b/deploy/build index 570cef5f787..f0c3a8b3842 100755 --- a/deploy/build +++ b/deploy/build @@ -14,11 +14,16 @@ cd "$(dirname "$0")/.." set -x +env + id which bundle bundle_dir=/srv/idp/shared +# use system libxml2, not the one vendored with nokogiri +bundle config build.nokogiri --use-system-libraries + bundle install --deployment --jobs 4 \ --path "$bundle_dir/bundle" \ --binstubs "$bundle_dir/bin" \ From 55dae4d64ec16511e04f484e9173c92ded8437c7 Mon Sep 17 00:00:00 2001 From: David Corwin Date: Wed, 4 Apr 2018 10:32:02 -0700 Subject: [PATCH 23/27] Pin Rubocop version and sync local and code climate lint configuration **WHY**: - Prevent local linting errors until Code Climate upgrades Rubocop support - Reduce noise when linting locally --- .reek | 1 + .rubocop.yml | 11 ++++++----- Gemfile | 2 +- Gemfile.lock | 6 +++--- config/initializers/devise.rb | 2 ++ 5 files changed, 13 insertions(+), 9 deletions(-) diff --git a/.reek b/.reek index db34ff01c73..69ebee1f99d 100644 --- a/.reek +++ b/.reek @@ -178,3 +178,4 @@ UtilityFunction: enabled: false exclude_paths: - db/migrate + - spec diff --git a/.rubocop.yml b/.rubocop.yml index 4c73fe37aa4..32228d61128 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -11,13 +11,14 @@ AllCops: - '**/Capfile' Exclude: - 'db/schema.rb' - - 'bin/**/*' - - 'config/initializers/devise.rb' - - 'db/migrate/*' - - 'spec/services/pii/nist_encryption_spec.rb' + - 'node_modules/**/*' - 'lib/rspec/user_flow_formatter.rb' - 'lib/user_flow_exporter.rb' - - 'node_modules/**/*' + - 'scripts/load_testing/*' + - 'spec/**/*' + - 'tmp/**/*' + - 'bin/**/*' + - 'db/migrate/*' TargetRubyVersion: 2.3 TargetRailsVersion: 5.1 UseCache: true diff --git a/Gemfile b/Gemfile index 99952d168d3..d6a401e1ab5 100644 --- a/Gemfile +++ b/Gemfile @@ -74,7 +74,7 @@ group :development do gem 'rack-mini-profiler', require: false gem 'rails-erd' gem 'reek' - gem 'rubocop', require: false + gem 'rubocop', '~> 0.52.0', require: false end group :development, :test do diff --git a/Gemfile.lock b/Gemfile.lock index 792ad8fb45f..3973a054aee 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -489,9 +489,9 @@ GEM rspec-mocks (~> 3.5.0) rspec-support (~> 3.5.0) rspec-support (3.5.0) - rubocop (0.54.0) + rubocop (0.52.1) parallel (~> 1.10) - parser (>= 2.5) + parser (>= 2.4.0.2, < 3.0) powerpack (~> 0.1) rainbow (>= 2.2.2, < 4.0) ruby-progressbar (~> 1.7) @@ -723,7 +723,7 @@ DEPENDENCIES reek rqrcode rspec-rails (~> 3.5.2) - rubocop + rubocop (~> 0.52.0) ruby-progressbar ruby-saml saml_idp! diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 4ed7e59fadf..aca6e167693 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -1,6 +1,7 @@ require 'saml_idp_constants' require 'custom_devise_failure_app' +# rubocop:disable Metrics/BlockLength Devise.setup do |config| include Mailable require 'devise/orm/active_record' @@ -33,3 +34,4 @@ manager.failure_app = CustomDeviseFailureApp end end +# rubocop:enable Metrics/BlockLength From 3e15b578131aa087213013402cd2b33893aedba0 Mon Sep 17 00:00:00 2001 From: Tom Black Date: Wed, 4 Apr 2018 13:55:31 -0700 Subject: [PATCH 24/27] Add NGA SPs **Why**: This adds two new NGA SPs going live at the same time. --- app/assets/images/sp-logos/nga.png | Bin 0 -> 31287 bytes certs/sp/nga_geoint_viewer_prod.crt | 12 +++++++++ certs/sp/nga_geoworks_prod.crt | 20 +++++++++++++++ certs/sp/nga_hiper_look_prod.crt | 24 ++++++++++++++++++ config/service_providers.yml | 37 ++++++++++++++++++++++++++++ 5 files changed, 93 insertions(+) create mode 100644 app/assets/images/sp-logos/nga.png create mode 100644 certs/sp/nga_geoint_viewer_prod.crt create mode 100644 certs/sp/nga_geoworks_prod.crt create mode 100644 certs/sp/nga_hiper_look_prod.crt diff --git a/app/assets/images/sp-logos/nga.png b/app/assets/images/sp-logos/nga.png new file mode 100644 index 0000000000000000000000000000000000000000..528eb4cc3bb184d8812962372db5d1654f67b329 GIT binary patch literal 31287 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 Date: Fri, 6 Apr 2018 09:52:54 -0500 Subject: [PATCH 25/27] Use proper rotation path suffix in SAML metadata **Why**: So that the saml2018 metadata endpoint will show the saml2018 auth and logout paths instead of the auth and logout paths with the expired certificate. --- app/controllers/saml_idp_controller.rb | 18 +++++++++++++----- spec/features/saml/saml_spec.rb | 10 ++++++++++ 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/app/controllers/saml_idp_controller.rb b/app/controllers/saml_idp_controller.rb index a7226e3ac26..70390920203 100644 --- a/app/controllers/saml_idp_controller.rb +++ b/app/controllers/saml_idp_controller.rb @@ -40,16 +40,24 @@ def logout def saml_metadata if SamlCertRotationManager.use_new_secrets_for_request?(request) - SamlIdp::MetadataBuilder.new( - SamlIdp.config, - SamlCertRotationManager.new_certificate, - SamlCertRotationManager.new_secret_key - ) + cert_rotation_saml_metadata else SamlIdp.metadata end end + def cert_rotation_saml_metadata + config = SamlIdp.config.dup + suffix = SamlCertRotationManager.rotation_path_suffix + config.single_service_post_location = config.single_service_post_location + suffix + config.single_logout_service_post_location = config.single_logout_service_post_location + suffix + SamlIdp::MetadataBuilder.new( + config, + SamlCertRotationManager.new_certificate, + SamlCertRotationManager.new_secret_key + ) + end + def redirect_to_account_or_verify_profile_url return redirect_to(account_or_verify_profile_url) if profile_needs_verification? redirect_to(verify_url) if identity_needs_verification? diff --git a/spec/features/saml/saml_spec.rb b/spec/features/saml/saml_spec.rb index 9bb02c94cfe..2421fe60cdb 100644 --- a/spec/features/saml/saml_spec.rb +++ b/spec/features/saml/saml_spec.rb @@ -254,6 +254,16 @@ cert_base64 = REXML::XPath.first(document, '//X509Certificate').text expect(cert_base64).to eq(Base64.strict_encode64(new_x509_cert.to_der)) end + + it 'includes the correct auth and logout urls' do + visit api_saml_metadata2018_path + document = REXML::Document.new(page.html) + auth_node = REXML::XPath.first(document, '//SingleSignOnService') + logout_node = REXML::XPath.first(document, '//SingleLogoutService') + + expect(auth_node.attributes['Location']).to include(api_saml_auth2018_path) + expect(logout_node.attributes['Location']).to include(destroy_user_session2018_path) + end end end end From 35e1e1bd9a9d51f5a0f47f5d2808ba1aed83c4fa Mon Sep 17 00:00:00 2001 From: Tom Black Date: Sun, 8 Apr 2018 23:44:20 -0700 Subject: [PATCH 26/27] Update NGA SP URLs --- config/service_providers.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/config/service_providers.yml b/config/service_providers.yml index da247468e34..a820f0aff50 100644 --- a/config/service_providers.yml +++ b/config/service_providers.yml @@ -501,9 +501,9 @@ production: agency: 'NGA' logo: 'nga.png' cert: 'nga_geoworks_prod' - return_to_sp_url: 'https://geoworks.geointservices.io' + return_to_sp_url: 'https://geoworks.nga-geoworks.com' redirect_uris: - - 'https://geoworks.geointservices.io/auth/login-gov/callback/loa-1' + - 'https://geoworks.nga-geoworks.com/auth/login-gov/callback/loa-1' restrict_to_deploy_env: 'prod' # NGA GEOINT Viewer @@ -513,9 +513,9 @@ production: agency: 'NGA' logo: 'nga.png' cert: 'nga_geoint_viewer_prod' - return_to_sp_url: 'https://gv-geoworks.geointservices.io' + return_to_sp_url: 'https://gv-geoworks.nga-geoworks.com' redirect_uris: - - 'https://gv-geoworks.geointservices.io/protected/callback' + - 'https://gv-geoworks.nga-geoworks.com/protected/callback' restrict_to_deploy_env: 'prod' # NGA HiPER CLOUD @@ -525,8 +525,8 @@ production: agency: 'NGA' logo: 'nga.png' cert: 'nga_hiper_look_prod' - return_to_sp_url: 'https://hiperlook-ppp.geointservices.io/' + return_to_sp_url: 'https://hiperlook-ppp.nga-geoworks.com' redirect_uris: - - 'https://hiperlook-ppp.geointservices.io/auth_redirect' - - 'https://hiperlook-ppp.geointservices.io:443/auth_redirect' + - 'https://hiperlook-ppp.nga-geoworks.com/auth_redirect' + - 'https://hiperlook-ppp.nga-geoworks.com:443/auth_redirect' restrict_to_deploy_env: 'prod' From d02f7e4d526e2934fbca587c1f5b2be9a7f95c78 Mon Sep 17 00:00:00 2001 From: Steve Urciuoli Date: Wed, 4 Apr 2018 13:12:04 -0400 Subject: [PATCH 27/27] LG-142 Password reset should count as email confirmation **Why**: When you don't have an account and request a password reset and click through to that email that says create your account now, users are taken to the very first step of having to confirm their email address again. **How**: Override the functionality of reset password when the user is not found to behave like create account. --- .../users/reset_passwords_controller.rb | 10 ++++++- app/forms/register_user_email_form.rb | 8 +++--- app/mailers/custom_devise_mailer.rb | 2 +- app/models/user.rb | 6 ++-- app/services/request_password_reset.rb | 9 +++++- config/locales/mailer/en.yml | 3 ++ config/locales/mailer/es.yml | 4 +++ config/locales/mailer/fr.yml | 4 +++ .../users/reset_passwords_controller_spec.rb | 28 +++++++++++++------ spec/services/request_password_reset_spec.rb | 13 ++++----- 10 files changed, 62 insertions(+), 25 deletions(-) diff --git a/app/controllers/users/reset_passwords_controller.rb b/app/controllers/users/reset_passwords_controller.rb index b3f2455db66..d7937d5b34f 100644 --- a/app/controllers/users/reset_passwords_controller.rb +++ b/app/controllers/users/reset_passwords_controller.rb @@ -62,7 +62,7 @@ def request_id end def handle_valid_email - RequestPasswordReset.new(email, request_id).perform + create_account_if_email_not_found session[:email] = email resend_confirmation = email_params[:resend] @@ -70,6 +70,14 @@ def handle_valid_email redirect_to forgot_password_url(resend: resend_confirmation, request_id: request_id) end + def create_account_if_email_not_found + user, result = RequestPasswordReset.new(email, request_id).perform + return unless result + + analytics.track_event(Analytics::USER_REGISTRATION_EMAIL, result.to_h) + create_user_event(:account_created, user) + end + def handle_invalid_or_expired_token(result) flash[:error] = t("devise.passwords.#{result.errors[:user].first}") redirect_to new_user_password_url diff --git a/app/forms/register_user_email_form.rb b/app/forms/register_user_email_form.rb index b03dd212536..6737e58b6c5 100644 --- a/app/forms/register_user_email_form.rb +++ b/app/forms/register_user_email_form.rb @@ -16,12 +16,12 @@ def resend 'true' end - def submit(params) + def submit(params, instructions = nil) user.email = params[:email] request_id = params[:request_id] if valid_form? - process_successful_submission(request_id) + process_successful_submission(request_id, instructions) else @success = process_errors(request_id) end @@ -38,10 +38,10 @@ def valid_form? valid? && !email_taken? end - def process_successful_submission(request_id) + def process_successful_submission(request_id, instructions) @success = true user.save! - user.send_custom_confirmation_instructions(request_id) + user.send_custom_confirmation_instructions(request_id, instructions) end def extra_analytics_attributes diff --git a/app/mailers/custom_devise_mailer.rb b/app/mailers/custom_devise_mailer.rb index ca9cfb44757..32a96e09a9f 100644 --- a/app/mailers/custom_devise_mailer.rb +++ b/app/mailers/custom_devise_mailer.rb @@ -12,7 +12,7 @@ def reset_password_instructions(*) def confirmation_instructions(record, token, options = {}) presenter = ConfirmationEmailPresenter.new(record, view_context) - @first_sentence = presenter.first_sentence + @first_sentence = options[:first_sentence] || presenter.first_sentence @confirmation_period = presenter.confirmation_period @request_id = options[:request_id] @locale = locale_url_param diff --git a/app/models/user.rb b/app/models/user.rb index fa3d0f22736..a8d17d9c12e 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -142,11 +142,13 @@ def send_confirmation_instructions # no-op end - def send_custom_confirmation_instructions(id = nil) + def send_custom_confirmation_instructions(id = nil, instructions = nil) generate_confirmation_token! unless @raw_confirmation_token opts = pending_reconfirmation? ? { to: unconfirmed_email, request_id: id } : { request_id: id } - send_devise_notification(:confirmation_instructions, @raw_confirmation_token, opts) + opts[:first_sentence] = instructions if instructions + send_devise_notification(:confirmation_instructions, + @raw_confirmation_token, opts) end end # rubocop:enable Rails/HasManyOrHasOneDependent diff --git a/app/services/request_password_reset.rb b/app/services/request_password_reset.rb index c7fadc30e40..ca46a280c19 100644 --- a/app/services/request_password_reset.rb +++ b/app/services/request_password_reset.rb @@ -5,14 +5,21 @@ def perform return if user_found_but_is_an_admin_or_tech? if user_not_found? - UserMailer.account_does_not_exist(email, request_id).deliver_later + form = RegisterUserEmailForm.new + result = form.submit({ email: email }, instructions) + [form.user, result] else user.send_reset_password_instructions + nil end end private + def instructions + I18n.t('mailer.confirmation_instructions.first_sentence.forgot_password') + end + def user_not_found? user.is_a?(NonexistentUser) end diff --git a/config/locales/mailer/en.yml b/config/locales/mailer/en.yml index 7bcb630ff1e..4d94434e712 100644 --- a/config/locales/mailer/en.yml +++ b/config/locales/mailer/en.yml @@ -5,6 +5,9 @@ en: confirmation_instructions: first_sentence: confirmed: Trying to change your email address? + forgot_password: You tried to reset your login.gov password but we don't have + an account linked to this email address. If you'd like to set up a new + account linked to this email, confirm your email address below. reset_requested: Your %{app} account has been reset by a tech support representative. To continue, you must confirm your email address. unconfirmed: Thanks for creating an account. diff --git a/config/locales/mailer/es.yml b/config/locales/mailer/es.yml index 2a946221188..7d00469ddd2 100644 --- a/config/locales/mailer/es.yml +++ b/config/locales/mailer/es.yml @@ -5,6 +5,10 @@ es: confirmation_instructions: first_sentence: confirmed: "¿Desea cambiar su email?" + forgot_password: Intentó restablecer su contraseña de login.gov pero no tenemos + una cuenta vinculada a esta dirección de correo electrónico. Si desea configurar + una nueva cuenta vinculada a este correo electrónico, confirme su dirección + de correo electrónico a continuación. reset_requested: Su cuenta de %{app} ha sido restablecida por un representante de soporte técnico. Para continuar, debe confirmar su email. unconfirmed: Gracias por crear una cuenta. diff --git a/config/locales/mailer/fr.yml b/config/locales/mailer/fr.yml index 6dbfbf8d340..b9b645db1a7 100644 --- a/config/locales/mailer/fr.yml +++ b/config/locales/mailer/fr.yml @@ -5,6 +5,10 @@ fr: confirmation_instructions: first_sentence: confirmed: Vous tentez de changer votre adresse courriel? + forgot_password: Vous avez essayé de réinitialiser le mot de passe de votre + compte login.gov, mais nous ne possédons pas de compte associé à cette adresse + courriel. Si vous souhaitez créer un nouveau compte associé à cette adresse + courriel, confirmez votre adresse courriel ci-dessous. reset_requested: Votre compte %{app} a été réinitialisé par un représentant du soutien technique. Pour continuer, vous devez confirmer votre adresse courriel. diff --git a/spec/controllers/users/reset_passwords_controller_spec.rb b/spec/controllers/users/reset_passwords_controller_spec.rb index 11d92843cd7..932b3924e96 100644 --- a/spec/controllers/users/reset_passwords_controller_spec.rb +++ b/spec/controllers/users/reset_passwords_controller_spec.rb @@ -261,7 +261,16 @@ describe '#create' do context 'no user matches email' do it 'send an email to tell the user they do not have an account yet' do - stub_analytics + analytics = instance_double(Analytics) + allow(Analytics).to receive(:new).and_return(analytics) + allow(analytics).to receive(:track_event) + email = 'nonexistent@example.com' + + expect do + put :create, params: { + password_reset_email_form: { email: email }, + } + end.to(change { ActionMailer::Base.deliveries.count }.by(1)) analytics_hash = { success: true, @@ -270,15 +279,18 @@ role: 'nonexistent', confirmed: false, } - - expect(@analytics).to receive(:track_event). + expect(analytics).to have_received(:track_event). with(Analytics::PASSWORD_RESET_EMAIL, analytics_hash) - expect do - put :create, params: { - password_reset_email_form: { email: 'nonexistent@example.com' }, - } - end.to(change { ActionMailer::Base.deliveries.count }.by(1)) + analytics_hash = { + success: true, + errors: {}, + email_already_exists: false, + user_id: User.find_with_email(email).uuid, + domain_name: 'example.com', + } + expect(analytics).to have_received(:track_event). + with(Analytics::USER_REGISTRATION_EMAIL, analytics_hash) expect(response).to redirect_to forgot_password_path end diff --git a/spec/services/request_password_reset_spec.rb b/spec/services/request_password_reset_spec.rb index 0dc4806df05..a36da55481c 100644 --- a/spec/services/request_password_reset_spec.rb +++ b/spec/services/request_password_reset_spec.rb @@ -3,15 +3,12 @@ describe RequestPasswordReset do describe '#perform' do context 'when the user is not found' do - it 'sends the account does not exist email' do + it 'sends the account registration email' do email = 'nonexistent@example.com' - - mailer = instance_double(ActionMailer::MessageDelivery, deliver_later: true) - allow(UserMailer).to receive(:account_does_not_exist). - with(email, 'request_id').and_return(mailer) - expect(mailer).to receive(:deliver_later) - - RequestPasswordReset.new(email, 'request_id').perform + expect_any_instance_of(User).to receive(:send_custom_confirmation_instructions). + with(nil, I18n.t('mailer.confirmation_instructions.first_sentence.forgot_password')) + RequestPasswordReset.new(email).perform + expect(User.find_with_email(email)).to be_present end end