diff --git a/.github/workflows/rspec.yml b/.github/workflows/rspec.yml index 8b194b7..d87306a 100644 --- a/.github/workflows/rspec.yml +++ b/.github/workflows/rspec.yml @@ -31,11 +31,11 @@ jobs: - name: Run rspec env: DATABASE_URL: ${{ steps.setup.outputs.database_url }} - rspec_oscal_timestamp: false + rspec_oscal_output: tmp run: bundle exec rspec - name: Save assessment results uses: actions/upload-artifact@v4 with: name: continuous_monitoring_assessment - path: tmp/oscal_assessment + path: tmp/oscal diff --git a/Gemfile b/Gemfile index 45b8ae5..a11cc16 100644 --- a/Gemfile +++ b/Gemfile @@ -75,7 +75,7 @@ end group :test do gem "climate_control", "~> 1.0" gem "shoulda-matchers", "~> 6.2" - gem "oscal", github: "rahearn/oscal-ruby", branch: "allow-setting-logger" - gem "rspec_oscal_formatter", github: "rahearn/rspec_oscal_formatter", branch: "mix-test-types" + gem "rspec_oscal_formatter", github: "gsa-tts/rspec_oscal_formatter", branch: "main" + # gem "rspec_oscal_formatter", path: "/Users/ryancahearn/software/devtools/oscal/rspec_oscal_formatter" gem "byebug", "~> 11.1" end diff --git a/Gemfile.lock b/Gemfile.lock index 8702183..8346a81 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,18 +1,11 @@ GIT - remote: https://github.com/rahearn/oscal-ruby.git - revision: 56faf2931931370acb47e05e7668883c48ffa9ec - branch: allow-setting-logger + remote: https://github.com/gsa-tts/rspec_oscal_formatter.git + revision: 430090714aa8aca0e650ff240c35ac3b18ddab3a + branch: main specs: - oscal (0.2.1) - yaml - -GIT - remote: https://github.com/rahearn/rspec_oscal_formatter.git - revision: 64dbf70748bfde0f9837dd6087f9813caa1c257c - branch: mix-test-types - specs: - rspec_oscal_formatter (0.1.1) - oscal (~> 0.2) + rspec_oscal_formatter (0.2.0) + method_source (~> 1.1) + oscal (~> 0.2, >= 0.2.3) rspec-core (~> 3.13) GEM @@ -133,7 +126,8 @@ GEM erubi (1.13.0) globalid (1.2.1) activesupport (>= 6.1) - highline (3.0.1) + highline (3.1.0) + reline i18n (1.14.5) concurrent-ruby (~> 1.0) i18n-tasks (1.0.14) @@ -168,6 +162,7 @@ GEM net-pop net-smtp marcel (1.0.4) + method_source (1.1.0) mini_mime (1.1.5) minitest (5.24.1) msgpack (1.7.2) @@ -195,8 +190,10 @@ GEM nokogiri (1.16.6-x86_64-linux) racc (~> 1.4) orm_adapter (0.5.0) + oscal (0.2.3) + yaml parallel (1.25.1) - parser (3.3.3.0) + parser (3.3.4.0) ast (~> 2.4.1) racc pg (1.5.6) @@ -207,7 +204,7 @@ GEM pundit (2.3.2) activesupport (>= 3.0.0) racc (1.8.0) - rack (3.1.6) + rack (3.1.7) rack-session (2.0.0) rack (>= 3.0.0) rack-test (2.1.0) @@ -269,7 +266,7 @@ GEM responders (3.1.1) actionpack (>= 5.2) railties (>= 5.2) - rexml (3.3.1) + rexml (3.3.2) strscan rspec-core (3.13.0) rspec-support (~> 3.13.0) @@ -323,7 +320,7 @@ GEM actionpack (>= 6.1) activesupport (>= 6.1) sprockets (>= 3.0.0) - standard (1.39.1) + standard (1.39.2) language_server-protocol (~> 3.17.0.2) lint_roller (~> 1.0) rubocop (~> 1.64.0) @@ -379,7 +376,6 @@ DEPENDENCIES i18n-tasks (~> 1.0) jbuilder jsbundling-rails - oscal! pg (~> 1.1) puma (>= 5.0) pundit (~> 2.3) diff --git a/doc/compliance/oscal/control-statements/ac-6.5.md b/doc/compliance/oscal/control-statements/ac-6.5.md index 7461f67..17f4af0 100644 --- a/doc/compliance/oscal/control-statements/ac-6.5.md +++ b/doc/compliance/oscal/control-statements/ac-6.5.md @@ -54,6 +54,8 @@ ______________________________________________________________________ ### This System +Users can be assigned the admin role to allow access to privileged functions. + Privileged accounts within the application are limited to Ryan only. #### Implementation Status: implemented diff --git a/doc/compliance/oscal/system-security-plans/continuous_monitoring/system-security-plan.json b/doc/compliance/oscal/system-security-plans/continuous_monitoring/system-security-plan.json index 3f46b62..6ab9b4f 100644 --- a/doc/compliance/oscal/system-security-plans/continuous_monitoring/system-security-plan.json +++ b/doc/compliance/oscal/system-security-plans/continuous_monitoring/system-security-plan.json @@ -292,7 +292,7 @@ { "component-uuid": "3dd05e37-06f1-4f8b-a4b7-7a80f2a0101b", "uuid": "4e53aec0-3d42-41c6-ae63-a25545705b69", - "description": "Privileged accounts within the application are limited to Ryan only.", + "description": "Users can be assigned the admin role to allow access to privileged functions.\n\nPrivileged accounts within the application are limited to Ryan only.", "implementation-status": { "state": "implemented" } diff --git a/doc/compliance/oscal/system-security-plans/continuous_monitoring/system-security-plan/metadata.json b/doc/compliance/oscal/system-security-plans/continuous_monitoring/system-security-plan/metadata.json index 7b0be77..3642469 100644 --- a/doc/compliance/oscal/system-security-plans/continuous_monitoring/system-security-plan/metadata.json +++ b/doc/compliance/oscal/system-security-plans/continuous_monitoring/system-security-plan/metadata.json @@ -1,7 +1,7 @@ { "metadata": { "title": "Continuous Monitoring Proof of Concept SSPP", - "last-modified": "2024-06-26T21:28:24.221862+00:00", + "last-modified": "2024-07-22T14:12:50.233680+00:00", "version": "0.0.1", "oscal-version": "1.1.2" } diff --git a/doc/compliance/oscal/system-security-plans/continuous_monitoring/system-security-plan/system-characteristics.json b/doc/compliance/oscal/system-security-plans/continuous_monitoring/system-security-plan/system-characteristics.json index 04d9b32..54c5110 100644 --- a/doc/compliance/oscal/system-security-plans/continuous_monitoring/system-security-plan/system-characteristics.json +++ b/doc/compliance/oscal/system-security-plans/continuous_monitoring/system-security-plan/system-characteristics.json @@ -50,4 +50,4 @@ "description": "REPLACE_ME" } } -} +} \ No newline at end of file diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 0ada119..f0fa049 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -1,7 +1,7 @@ require "rails_helper" RSpec.describe User, type: :model do - describe "#admin?" do + describe "#admin?", control_id: "ac-6.5", statement_id: "ac-6.5_smt", rule_ids: "system-roles-needed" do context "default" do it { expect(subject).not_to be_admin } end @@ -13,7 +13,7 @@ end end - it "should have a minimum password length", control_id: "ia-2", statement_id: "ia-2_smt", assessment_plan_uuid: "acb25d5d-8e18-4400-9fbf-433b21442de4" do + it "should have a minimum password length", control_id: "ia-2", statement_id: "ia-2_smt" do subject.password = "12345" expect(subject).not_to be_valid expect(subject.errors[:password]).to eq ["is too short (minimum is 6 characters)"] diff --git a/spec/policies/document_policy_spec.rb b/spec/policies/document_policy_spec.rb index 7497799..ad2162c 100644 --- a/spec/policies/document_policy_spec.rb +++ b/spec/policies/document_policy_spec.rb @@ -16,44 +16,18 @@ it { expect(subject).to permit(user, record) } end - permissions :create? do - it "Users cannot create a new document", control_id: "ac-3", statement_id: "ac-3_smt", assessment_plan_uuid: "4635e122-87fc-4533-b3bb-14674f2562b8" do - expect(subject).not_to permit(user, record) - end - - context "admin" do - let(:user) { User.new admin: true } - - it "Admins can create a new document", control_id: "ac-3", statement_id: "ac-3_smt", assessment_plan_uuid: "4635e122-87fc-4533-b3bb-14674f2562b8" do - expect(subject).to permit(user, record) - end - end - end - - permissions :update? do - it "Users cannot update documents", control_id: "ac-3", statement_id: "ac-3_smt", assessment_plan_uuid: "4635e122-87fc-4533-b3bb-14674f2562b8" do - expect(subject).not_to permit(user, record) - end - - context "admin" do - let(:user) { User.new admin: true } - - it "Admins can update documents", control_id: "ac-3", statement_id: "ac-3_smt", assessment_plan_uuid: "4635e122-87fc-4533-b3bb-14674f2562b8" do - expect(subject).to permit(user, record) + context "privileged actions", control_id: "ac-3", statement_id: "ac-3_smt" do + permissions :create?, :update?, :destroy? do + it "users are not authorized" do + expect(subject).not_to permit(user, record) end - end - end - - permissions :destroy? do - it "Users cannot destroy documents", control_id: "ac-3", statement_id: "ac-3_smt", assessment_plan_uuid: "4635e122-87fc-4533-b3bb-14674f2562b8" do - expect(subject).not_to permit(user, record) - end - context "admin" do - let(:user) { User.new admin: true } + context "admins" do + let(:user) { User.new admin: true } - it "Admins can destroy documents", control_id: "ac-3", statement_id: "ac-3_smt", assessment_plan_uuid: "4635e122-87fc-4533-b3bb-14674f2562b8" do - expect(subject).to permit(user, record) + it "are authorized" do |example| + expect(subject).to permit(user, record) + end end end end diff --git a/spec/requests/documents_spec.rb b/spec/requests/documents_spec.rb index cbbe451..a4e1693 100644 --- a/spec/requests/documents_spec.rb +++ b/spec/requests/documents_spec.rb @@ -84,7 +84,7 @@ expect(response).to redirect_to(document_url(Document.last)) end - it "logs the use of this privileged function", control_id: "ac-6.9", statement_id: "ac-6.9_smt", assessment_plan_uuid: "06eb2b97-7665-467b-88d5-027170dc6f63" do + it "logs the use of this privileged function", control_id: "ac-6.9", statement_id: "ac-6.9_smt", implementation_statement_uuid: "c2db0c86-cfa5-4fb5-9f92-66a066bf5604" do allow(Rails.logger).to receive(:info) expect(Rails.logger).to receive(:info).with(/\[PRIVILEGED\] Document\(\d+\) created by #{user.id}/) post documents_url, params: {document: valid_attributes} @@ -128,7 +128,7 @@ expect(response).to redirect_to(document_url(document)) end - it "logs the use of this privileged function", control_id: "ac-6.9", statement_id: "ac-6.9_smt", assessment_plan_uuid: "06eb2b97-7665-467b-88d5-027170dc6f63" do + it "logs the use of this privileged function", control_id: "ac-6.9", statement_id: "ac-6.9_smt", implementation_statement_uuid: "c2db0c86-cfa5-4fb5-9f92-66a066bf5604" do allow(Rails.logger).to receive(:info) expect(Rails.logger).to receive(:info).with("[PRIVILEGED] Document(#{document.id}) updated by #{user.id}") patch document_url(document), params: {document: new_attributes} @@ -159,7 +159,7 @@ expect(response).to redirect_to(documents_url) end - it "logs the use of this privileged function", control_id: "ac-6.9", statement_id: "ac-6.9_smt", assessment_plan_uuid: "06eb2b97-7665-467b-88d5-027170dc6f63" do + it "logs the use of this privileged function", control_id: "ac-6.9", statement_id: "ac-6.9_smt", implementation_statement_uuid: "c2db0c86-cfa5-4fb5-9f92-66a066bf5604" do allow(Rails.logger).to receive(:info) expect(Rails.logger).to receive(:info).with("[PRIVILEGED] Document(#{document.id}) destroyed by #{user.id}") delete document_url(document) diff --git a/spec/support/oscal_formatter.rb b/spec/support/oscal_formatter.rb index 704e3af..dba535f 100644 --- a/spec/support/oscal_formatter.rb +++ b/spec/support/oscal_formatter.rb @@ -1,11 +1,25 @@ +return if ENV['rspec_oscal_output'].blank? + +require 'oscal' Oscal::ParsingLogger.logger = Rails.logger -RSpec::RSpecOscalFormatter::Formatter.output_directory = Rails.root.join("tmp", "oscal_assessment") -RSpec::RSpecOscalFormatter::Formatter.use_timestamp_dirs = ENV.fetch("rspec_oscal_timestamp", "true") == "true" + +RSpecOscalFormatter.configure do |config| + config.assessment_plan_uuid = SecureRandom.uuid + config.plan_filename = "trestle://assessment-plans/rspec/assessment-plan.json" + config.ssp_filename = "trestle://system-security-plans/continuous_monitoring/system-security-plan.json" +end + RSpec.configure do |config| if config.files_to_run.one? config.add_formatter "doc" else config.add_formatter "progress" end - config.add_formatter RSpec::RSpecOscalFormatter::Formatter + oscal_directory = if ENV['rspec_oscal_output'] == 'tmp' + Rails.root.join("tmp", "oscal") + else + Rails.root.join("doc/compliance/oscal") + end + config.add_formatter RSpecOscalFormatter::PlanFormatter, oscal_directory.join("assessment-plans", "rspec", "assessment-plan.json") + config.add_formatter RSpecOscalFormatter::ResultsFormatter, oscal_directory.join("assessment-results", "rspec", "assessment-results.json") end