├── .envrc ├── rustfmt.toml ├── roscal_cli ├── src │ ├── cli │ │ ├── mod.rs │ │ ├── cli_fn.rs │ │ └── cli_opts.rs │ ├── lib.rs │ ├── models │ │ ├── mod.rs │ │ ├── utils.rs │ │ ├── workspace.rs │ │ ├── validate.rs │ │ └── validation.rs │ └── main.rs ├── tests │ ├── data │ │ ├── edit_uuid │ │ ├── edit_back_matter │ │ ├── compdef.yaml │ │ ├── ap.yaml │ │ ├── ar.yaml │ │ └── poam.yaml │ ├── dissect.rs │ ├── merge.rs │ └── roundtrip.rs └── Cargo.toml ├── roscal_lib ├── tests │ ├── loc │ ├── malformed.rs │ ├── component-definition │ │ ├── yaml │ │ │ ├── example-component.yaml │ │ │ └── example-component-definition.yaml │ │ └── json │ │ │ ├── example-component.json │ │ │ ├── example-component-min.json │ │ │ ├── example-component-definition-min.json │ │ │ └── example-component-definition.json │ ├── ap │ │ ├── yaml │ │ │ └── ifa_assessment-plan-example.yaml │ │ └── json │ │ │ ├── ifa_assessment-plan-example-min.json │ │ │ └── ifa_assessment-plan-example.json │ ├── parse_test.rs │ ├── ar │ │ └── yaml │ │ │ └── ifa_assessment-results-example.yaml │ ├── poam │ │ └── yaml │ │ │ └── ifa_plan-of-action-and-milestones.yaml │ ├── ssp │ │ └── yaml │ │ │ └── oscal_leveraged-example_ssp.yaml │ └── malformed │ │ ├── uuid.yaml │ │ └── datetime.yaml ├── jsonschema │ ├── baseline_unified │ │ └── loc │ ├── previous_unified │ │ └── loc │ └── tracking_latest_unified │ │ └── loc ├── src │ ├── control │ │ └── mod.rs │ ├── implementation │ │ └── mod.rs │ ├── assessment │ │ └── mod.rs │ ├── uuid_impl.rs │ └── lib.rs ├── README.md └── Cargo.toml ├── CHANGELOG.md ├── .github ├── dependabot.yml └── workflows │ └── ci.yaml ├── .gitignore ├── shell.nix ├── default.nix ├── .pre-commit-config.yaml ├── SECURITY.md ├── flake.nix ├── LICENSE-MIT ├── deny.toml ├── Cargo.toml ├── cliff.toml ├── flake.lock └── ROADMAP.md /.envrc: -------------------------------------------------------------------------------- 1 | use flake -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | max_width = 80 2 | tab_spaces = 4 -------------------------------------------------------------------------------- /roscal_cli/src/cli/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod cli_fn; 2 | pub mod cli_opts; 3 | -------------------------------------------------------------------------------- /roscal_cli/tests/data/edit_uuid: -------------------------------------------------------------------------------- 1 | 74c8ba1e-5cd4-4ad1-bbfd-d888e2f6c721 -------------------------------------------------------------------------------- /roscal_lib/tests/loc: -------------------------------------------------------------------------------- 1 | https://github.com/usnistgov/oscal-content/tree/main/examples -------------------------------------------------------------------------------- /roscal_cli/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![forbid(unsafe_code)] 2 | 3 | pub mod cli; 4 | pub mod models; 5 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | Changelog 2 | 3 | ## [0.1.0] - 2024-02-26 4 | 5 | ### Changed 6 | 7 | - Initial commit 8 | -------------------------------------------------------------------------------- /roscal_lib/jsonschema/baseline_unified/loc: -------------------------------------------------------------------------------- 1 | https://github.com/usnistgov/OSCAL/releases/download/v1.0.0/oscal_complete_schema.json -------------------------------------------------------------------------------- /roscal_lib/jsonschema/previous_unified/loc: -------------------------------------------------------------------------------- 1 | https://github.com/usnistgov/OSCAL/releases/download/v1.1.1/oscal_complete_schema.json -------------------------------------------------------------------------------- /roscal_lib/jsonschema/tracking_latest_unified/loc: -------------------------------------------------------------------------------- 1 | https://github.com/usnistgov/OSCAL/releases/download/v1.1.2/oscal_complete_schema.json -------------------------------------------------------------------------------- /roscal_lib/src/control/mod.rs: -------------------------------------------------------------------------------- 1 | //! OSCAL Control Layer. 2 | 3 | /// Catalog Model 4 | pub mod catalog; 5 | /// Profile Model 6 | pub mod profile; 7 | -------------------------------------------------------------------------------- /roscal_cli/src/models/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod dissect; 2 | pub mod merge; 3 | pub mod model; 4 | pub mod utils; 5 | pub mod validate; 6 | pub mod validation; 7 | pub mod workspace; 8 | -------------------------------------------------------------------------------- /roscal_lib/src/implementation/mod.rs: -------------------------------------------------------------------------------- 1 | //! OSCAL Implementation Layer. 2 | 3 | /// Component Definition Model 4 | pub mod component_definition; 5 | /// System Security Plan Model 6 | pub mod ssp; 7 | -------------------------------------------------------------------------------- /roscal_lib/src/assessment/mod.rs: -------------------------------------------------------------------------------- 1 | //! OSCAL Assessment Layer. 2 | 3 | /// Assessment Plan Model 4 | pub mod assessment_plan; 5 | /// Assessment Results Model 6 | pub mod assessment_results; 7 | /// Plan of Action and Milestones Model 8 | pub mod poam; 9 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: cargo 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | open-pull-requests-limit: 10 8 | 9 | - package-ecosystem: github-actions 10 | directory: "/" 11 | schedule: 12 | interval: daily 13 | open-pull-requests-limit: 10 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | debug/ 4 | target/ 5 | 6 | # These are backup files generated by rustfmt 7 | **/*.rs.bk 8 | 9 | # MSVC Windows builds of rustc generate these, which store debugging information 10 | *.pdb 11 | 12 | 13 | # Added by cargo 14 | 15 | /target 16 | 17 | /result 18 | 19 | .cargo 20 | .vscode -------------------------------------------------------------------------------- /shell.nix: -------------------------------------------------------------------------------- 1 | (import 2 | ( 3 | let lock = builtins.fromJSON (builtins.readFile ./flake.lock); in 4 | fetchTarball { 5 | url = lock.nodes.flake-compat.locked.url or "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz"; 6 | sha256 = lock.nodes.flake-compat.locked.narHash; 7 | } 8 | ) 9 | { src = ./.; } 10 | ).shellNix -------------------------------------------------------------------------------- /default.nix: -------------------------------------------------------------------------------- 1 | (import 2 | ( 3 | let lock = builtins.fromJSON (builtins.readFile ./flake.lock); in 4 | fetchTarball { 5 | url = lock.nodes.flake-compat.locked.url or "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz"; 6 | sha256 = lock.nodes.flake-compat.locked.narHash; 7 | } 8 | ) 9 | { src = ./.; } 10 | ).defaultNix -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: local 3 | hooks: 4 | - id: clippy 5 | name: clippy 6 | description: cargo clippy 7 | entry: cargo clippy 8 | language: system 9 | args: ["--", "-D", "warnings"] 10 | types: [rust] 11 | pass_filenames: false 12 | - id: fmt 13 | name: fmt 14 | description: cargo fmt 15 | entry: cargo fmt 16 | language: system 17 | types: [rust] 18 | args: ["--all"] -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Reporting a Vulnerability 4 | 5 | To report a security vulnerability, please email the maintainers at `geoffrey.borough@outlook.com`. Please do not create a Github issue 6 | for security vulnerabilities. 7 | 8 | If you can, please include the following details: 9 | * An MCVE (minimum complete verifiable example) – this is a short code snippet which demonstrates the error in the simplest possible (or just a simple) way. 10 | * Which versions the vulnerability is present in 11 | * What effects the vulnerability has and how serious the vulnerability is 12 | -------------------------------------------------------------------------------- /roscal_cli/src/main.rs: -------------------------------------------------------------------------------- 1 | mod cli; 2 | mod models; 3 | 4 | use clap::Parser; 5 | use cli::{ 6 | cli_fn::{run_dissect, run_merge, run_validate, show_dissect}, 7 | cli_opts::{Commands, OscalCli}, 8 | }; 9 | 10 | #[tokio::main] 11 | async fn main() -> Result<(), Box> { 12 | let cli = OscalCli::parse(); 13 | 14 | match cli.command { 15 | Commands::Dissect(ref opts) => run_dissect(opts).await?, 16 | Commands::Merge(ref opts) => run_merge(opts).await?, 17 | Commands::Validate(ref opts) => run_validate(opts).await?, 18 | Commands::ShowDissect => show_dissect().await?, 19 | } 20 | 21 | Ok(()) 22 | } 23 | -------------------------------------------------------------------------------- /roscal_cli/tests/data/edit_back_matter: -------------------------------------------------------------------------------- 1 | resources: 2 | - uuid: 84cbf061-eb87-4ec1-8112-1f529232e907 3 | description: 'NIST Special Publication 800-53 Revision 5: Security and Privacy Controls for Federal Information Systems and Organizations' 4 | rlinks: 5 | - href: ../../../../nist.gov/SP800-53/rev5/xml/NIST_SP-800-53_rev5_catalog.xml 6 | media-type: application/oscal.catalog+xml 7 | - href: ../../../../nist.gov/SP800-53/rev5/json/NIST_SP-800-53_rev5_catalog.json 8 | media-type: application/oscal.catalog+json 9 | - href: ../../../../nist.gov/SP800-53/rev5/yaml/NIST_SP-800-53_rev5_catalog.yaml 10 | media-type: application/oscal.catalog+yaml -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "roscal"; 3 | inputs = { 4 | flake-utils.url = "github:numtide/flake-utils"; 5 | naersk.url = "github:nix-community/naersk"; 6 | nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; 7 | }; 8 | 9 | outputs = { self, flake-utils, naersk, nixpkgs }: 10 | flake-utils.lib.eachDefaultSystem (system: 11 | let 12 | pkgs = (import nixpkgs) { 13 | inherit system; 14 | }; 15 | 16 | naersk' = pkgs.callPackage naersk {}; 17 | 18 | in rec { 19 | defaultPackage = naersk'.buildPackage { 20 | src = ./.; 21 | nativeBuildInputs = with pkgs; [ quicktype ]; 22 | doCheck = true; 23 | }; 24 | 25 | devShell = pkgs.mkShell { 26 | nativeBuildInputs = with pkgs; [ rustc cargo quicktype ]; 27 | }; 28 | } 29 | ); 30 | } -------------------------------------------------------------------------------- /roscal_cli/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "roscal_cli" 3 | version = "0.1.0" 4 | edition = "2021" 5 | authors = ["Geoffrey Borough "] 6 | homepage = "https://github.com/gborough/roscal" 7 | repository = "https://github.com/gborough/roscal" 8 | license = "MIT OR Apache-2.0" 9 | description = """ 10 | CLI For Open Security Controls Assessment Language In Rust 11 | """ 12 | 13 | [dependencies] 14 | roscal_lib = "0.1.0" 15 | 16 | anyhow = { workspace = true } 17 | clap = { workspace = true } 18 | chrono = { workspace = true } 19 | iana-time-zone = { workspace = true } 20 | rand = { workspace = true } 21 | serde = { workspace = true } 22 | serde_json = { workspace = true } 23 | serde_yaml = { workspace = true } 24 | sha2 = { workspace = true } 25 | strum = { workspace = true } 26 | thiserror = { workspace = true } 27 | tokio = { workspace = true } 28 | 29 | [dev-dependencies] 30 | assert_cmd = { workspace = true } 31 | tempfile = { workspace = true } 32 | walkdir = { workspace = true } 33 | 34 | [[bin]] 35 | name = "roscal" 36 | path = "src/main.rs" 37 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Geoffrey Borough 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /roscal_lib/README.md: -------------------------------------------------------------------------------- 1 | # roscal_lib: Referential implementation of Open Security Controls Assessment Language(OSCAL) 2 | 3 | This library enables users to programmatically build, and parse various OSCAL 4 | models using the builder pattern, with bi-directional validation enabled on key 5 | fields during serialisation/deserialisation. 6 | 7 | All textual fields are represented as `String` type such as uuid, datetime etc. 8 | This library strives to be unopinionated about which libraries user use to build 9 | certain data fields, therefore it does not re-export some of the libraries used 10 | internally for validation. The libraries for building these types 11 | are specified Cargo.toml such as `chrono`, `uriparse`, `uuid` etc, although you 12 | can follow the OSCAL specification and choose whichever that conforms to the requirements. 13 | See 14 | 15 | Currently the latest v1.x is being tracked by this library and compatible all the way 16 | back to v1.0.0. It primarily supports the roscal_cli tool. 17 | 18 | Note: The generation of Rust structs are done via external tool called quicktype. Future 19 | plan is to migrate away from this and derive structs using a Rust native solution. The 20 | naming of types are subject to change once this is completed. -------------------------------------------------------------------------------- /roscal_lib/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "roscal_lib" 3 | version = "0.1.0" 4 | edition = "2021" 5 | authors = ["Geoffrey Borough "] 6 | readme = "README.md" 7 | homepage = "https://github.com/gborough/roscal" 8 | repository = "https://github.com/gborough/roscal" 9 | description = """ 10 | Open Security Controls Assessment Language In Rust 11 | """ 12 | license = "MIT OR Apache-2.0" 13 | keywords = ["OSCAL", "cybersecurity"] 14 | categories = ["api-bindings", "encoding"] 15 | publish = ["crates-io"] 16 | exclude = ["jsonschema/", "build.rs"] 17 | 18 | [dependencies] 19 | chrono = { workspace = true } 20 | derivative = { workspace = true } 21 | derive_builder = { workspace = true } 22 | lazy_static = { workspace = true } 23 | pulldown-cmark = { workspace = true } 24 | regex = { workspace = true } 25 | serde = { workspace = true } 26 | strum = { workspace = true } 27 | uriparse = { workspace = true } 28 | uuid = { workspace = true } 29 | 30 | [dev-dependencies] 31 | serde_json = { workspace = true } 32 | serde_yaml = { workspace = true } 33 | 34 | [build-dependencies] 35 | json-schema-diff = { workspace = true } 36 | prettyplease = { workspace = true } 37 | proc-macro2 = { workspace = true } 38 | quote = { workspace = true } 39 | serde_json = { workspace = true } 40 | syn = { workspace = true } -------------------------------------------------------------------------------- /roscal_lib/src/uuid_impl.rs: -------------------------------------------------------------------------------- 1 | use crate::{assessment::*, control::*, implementation::*, UpdateUuid}; 2 | 3 | macro_rules! impl_update_uuid { 4 | ( $( $t:ty ),* ) => { 5 | $( 6 | impl UpdateUuid for $t { 7 | fn update_uuid_v4(&mut self, rhs: &Self) -> &mut Self { 8 | if self != rhs { 9 | self.uuid = String::from(uuid::Uuid::new_v4()); 10 | 11 | return self 12 | } 13 | 14 | self 15 | } 16 | 17 | fn update_uuid_v5(&mut self, rhs: &Self) -> &mut Self { 18 | if self != rhs { 19 | self.uuid = String::from(uuid::Uuid::new_v5( 20 | &uuid::Uuid::NAMESPACE_URL, 21 | b"http://csrc.nist.gov/ns/oscal", 22 | )); 23 | 24 | return self 25 | } 26 | 27 | self 28 | } 29 | } 30 | )* 31 | }; 32 | } 33 | 34 | impl_update_uuid!( 35 | assessment_plan::SecurityAssessmentPlanSap, 36 | assessment_results::SecurityAssessmentResultsSar, 37 | poam::PlanOfActionAndMilestonesPoaM, 38 | catalog::CatalogClass, 39 | profile::ProfileClass, 40 | component_definition::ComponentDefinitionClass, 41 | ssp::SystemSecurityPlanSsp 42 | ); 43 | -------------------------------------------------------------------------------- /deny.toml: -------------------------------------------------------------------------------- 1 | # See all available configuration options at: 2 | # https://embarkstudios.github.io/cargo-deny/index.html 3 | 4 | # -------------------------------------------------- 5 | # General 6 | # -------------------------------------------------- 7 | 8 | [graph] 9 | all-features = true 10 | no-default-features = true 11 | 12 | # -------------------------------------------------- 13 | # BANS 14 | # -------------------------------------------------- 15 | 16 | [bans] 17 | highlight = "all" 18 | wildcards = "deny" 19 | multiple-versions = "allow" 20 | workspace-default-features = "allow" 21 | external-default-features = "allow" 22 | 23 | # -------------------------------------------------- 24 | # SOURCES 25 | # -------------------------------------------------- 26 | 27 | [sources] 28 | unknown-git = "deny" 29 | unknown-registry = "deny" 30 | allow-registry = ["https://github.com/rust-lang/crates.io-index"] 31 | allow-git = [] 32 | 33 | # -------------------------------------------------- 34 | # ADVISORIES 35 | # -------------------------------------------------- 36 | 37 | [advisories] 38 | db-urls = ["https://github.com/rustsec/advisory-db"] 39 | db-path = "~/.cargo/advisory-db" 40 | yanked = "warn" 41 | ignore = ["RUSTSEC-2024-0388"] 42 | 43 | # -------------------------------------------------- 44 | # LICENSES 45 | # -------------------------------------------------- 46 | 47 | [licenses] 48 | allow = [ 49 | "MIT", 50 | "Zlib", 51 | "BSL-1.0", 52 | "Apache-2.0", 53 | "BSD-3-Clause", 54 | "Unlicense", 55 | ] 56 | confidence-threshold = 0.95 57 | 58 | [[licenses.exceptions]] 59 | name = "unicode-ident" 60 | version = "*" 61 | allow = ["Unicode-DFS-2016"] -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | resolver = "2" 3 | members = ["roscal_lib", "roscal_cli"] 4 | 5 | # Config for 'cargo dist' 6 | [workspace.metadata.dist] 7 | # The preferred cargo-dist version to use in CI (Cargo.toml SemVer syntax) 8 | cargo-dist-version = "0.10.0" 9 | # CI backends to support 10 | ci = ["github"] 11 | # The installers to generate for each app 12 | installers = [] 13 | # Target platforms to build apps for (Rust target-triple syntax) 14 | targets = ["aarch64-apple-darwin", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu"] 15 | # Publish jobs to run in CI 16 | pr-run-mode = "plan" 17 | # Skip checking whether the specified configuration files are up to date 18 | allow-dirty = ["ci"] 19 | 20 | [workspace.dependencies] 21 | anyhow = "1.0.98" 22 | assert_cmd = "2.0.17" 23 | clap = { version = "4.5.13", features = ["derive"] } 24 | chrono = { version = "0.4.40", features = ["serde"] } 25 | derivative = "2.2.0" 26 | derive_builder = "0.20.0" 27 | iana-time-zone = "0.1.63" 28 | json-schema-diff = "0.1.7" 29 | lazy_static = "1.5.0" 30 | prettyplease = "0.2.32" 31 | proc-macro2 = "1.0.95" 32 | pulldown-cmark = "0.10.3" 33 | quote = "1.0.40" 34 | rand = "0.9.1" 35 | regex = "1.11.1" 36 | sha2 = "0.10.8" 37 | serde = { version = "1.0.219", features = ["derive"] } 38 | serde_json = { version = "1.0.140", features = ["preserve_order"] } 39 | serde_yaml = "0.9.34" 40 | strum = { version = "0.26.3", features = ["derive"] } 41 | syn = {version = "2.0.100", features = ["full"]} 42 | tempfile = "3.20.0" 43 | thiserror = "1.0.60" 44 | tokio = { version = "1.44.2", features = ["full"] } 45 | uriparse = "0.6.4" 46 | uuid = { version = "1.16.0", features = ["v4", "v5", "fast-rng", "serde"] } 47 | walkdir = "2.5.0" 48 | 49 | [profile.release] 50 | lto = true 51 | strip = true 52 | opt-level = 2 53 | panic = 'abort' 54 | 55 | # The profile that 'cargo dist' will build with 56 | [profile.dist] 57 | inherits = "release" 58 | lto = "thin" 59 | -------------------------------------------------------------------------------- /cliff.toml: -------------------------------------------------------------------------------- 1 | [changelog] 2 | header = """ 3 | Changelog\n 4 | """ 5 | 6 | body = """ 7 | {% if version -%} 8 | ## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }} 9 | {% else -%} 10 | ## [Unreleased] 11 | {% endif -%} 12 | {% for group, commits in commits | group_by(attribute="group") %} 13 | ### {{ group | upper_first }} 14 | {% for commit in commits %} 15 | - {{ commit.message | upper_first }}\ 16 | {% endfor %} 17 | {% endfor %}\n 18 | """ 19 | 20 | footer = """ 21 | {% for release in releases -%} 22 | {% if release.version -%} 23 | {% if release.previous.version -%} 24 | [{{ release.version | trim_start_matches(pat="v") }}]: \ 25 | https://github.com/{{ remote.github.owner }}/{{ remote.github.repo }}\ 26 | /compare/{{ release.previous.version }}..{{ release.version }} 27 | {% endif -%} 28 | {% else -%} 29 | [unreleased]: https://github.com/{{ remote.github.owner }}/{{ remote.github.repo }}\ 30 | /compare/{{ release.previous.version }}..HEAD 31 | {% endif -%} 32 | {% endfor %} 33 | 34 | """ 35 | trim = true 36 | 37 | [git] 38 | conventional_commits = true 39 | filter_unconventional = false 40 | split_commits = false 41 | commit_parsers = [ 42 | { message = "^.*: add", group = "Added" }, 43 | { message = "^.*: support", group = "Added" }, 44 | { message = "^.*: remove", group = "Removed" }, 45 | { message = "^.*: delete", group = "Removed" }, 46 | { message = "^test", group = "Fixed" }, 47 | { message = "^fix", group = "Fixed" }, 48 | { message = "^.*: fix", group = "Fixed" }, 49 | { message = "^.*", group = "Changed" }, 50 | ] 51 | protect_breaking_commits = false 52 | filter_commits = true 53 | tag_pattern = "v[0-9].*" 54 | skip_tags = "v0.1.0-beta.1" 55 | ignore_tags = "" 56 | topo_order = false 57 | sort_commits = "newest" 58 | -------------------------------------------------------------------------------- /roscal_lib/tests/malformed.rs: -------------------------------------------------------------------------------- 1 | use std::{fs::File, io::BufReader}; 2 | 3 | use roscal_lib::{ 4 | control::profile::Profile, implementation::ssp::SystemSecurityPlan, 5 | }; 6 | 7 | #[test] 8 | fn wrong_date() { 9 | let file = File::open("tests/malformed/date.yaml").unwrap(); 10 | let reader = BufReader::new(file); 11 | let res: Result = 12 | serde_yaml::from_reader(reader); 13 | 14 | let e = res.err().unwrap().to_string(); 15 | 16 | assert_eq!("system-security-plan.system-characteristics: invalid date pattern at line 54 column 5", e) 17 | } 18 | 19 | #[test] 20 | fn wrong_datetime() { 21 | let file = File::open("tests/malformed/datetime.yaml").unwrap(); 22 | let reader = BufReader::new(file); 23 | let res: Result = 24 | serde_yaml::from_reader(reader); 25 | 26 | let e = res.err().unwrap().to_string(); 27 | 28 | assert_eq!( 29 | "profile.metadata: invalid datetime pattern at line 4 column 5", 30 | e 31 | ) 32 | } 33 | 34 | #[test] 35 | fn wrong_email() { 36 | let file = File::open("tests/malformed/email.yaml").unwrap(); 37 | let reader = BufReader::new(file); 38 | let res: Result = 39 | serde_yaml::from_reader(reader); 40 | 41 | let e = res.err().unwrap().to_string(); 42 | 43 | assert_eq!("profile.metadata.parties[0]: invalid email pattern at line 14 column 9", e) 44 | } 45 | 46 | #[test] 47 | fn wrong_uri() { 48 | let file = File::open("tests/malformed/uri.yaml").unwrap(); 49 | let reader = BufReader::new(file); 50 | let res: Result = 51 | serde_yaml::from_reader(reader); 52 | 53 | let e = res.err().unwrap().to_string(); 54 | 55 | assert_eq!("profile.back-matter.resources[0].rlinks[0]: invalid uri reference pattern at line 416 column 13", e) 56 | } 57 | 58 | #[test] 59 | fn wrong_uuid() { 60 | let file = File::open("tests/malformed/uuid.yaml").unwrap(); 61 | let reader = BufReader::new(file); 62 | let res: Result = 63 | serde_yaml::from_reader(reader); 64 | 65 | let e = res.err().unwrap().to_string(); 66 | 67 | assert_eq!("profile: invalid uuid pattern at line 2 column 3", e) 68 | } 69 | -------------------------------------------------------------------------------- /roscal_cli/src/models/utils.rs: -------------------------------------------------------------------------------- 1 | #![allow(clippy::single_char_pattern)] 2 | use std::{fs::File, io::Read, path::Path}; 3 | 4 | use anyhow::{Context, Result}; 5 | use chrono::Utc; 6 | use rand::{distr::Alphanumeric, rng, Rng}; 7 | use sha2::{Digest, Sha256}; 8 | 9 | pub(super) fn check_filename_len(path: impl AsRef) -> bool { 10 | if path.as_ref().to_string_lossy().len() > 202 { 11 | eprintln!("File name is too long"); 12 | return false; 13 | } 14 | 15 | true 16 | } 17 | 18 | pub(super) fn is_valid_file(path: impl AsRef) -> bool { 19 | if check_filename_len(&path) && !path.as_ref().is_file() { 20 | eprintln!("Invalid file provided: {}", path.as_ref().display()); 21 | return false; 22 | } 23 | 24 | true 25 | } 26 | 27 | pub(super) fn is_valid_dir(path: impl AsRef) -> bool { 28 | if !path.as_ref().is_dir() { 29 | eprintln!( 30 | "Invalid directory provided: {}", 31 | path.as_ref().to_string_lossy() 32 | ); 33 | return false; 34 | } 35 | 36 | true 37 | } 38 | 39 | pub(super) fn gen_created_at() -> String { 40 | let now = Utc::now().to_string(); 41 | 42 | now.as_str().replace(" ", "_") 43 | } 44 | 45 | pub(super) fn gen_rand() -> String { 46 | rng() 47 | .sample_iter(&Alphanumeric) 48 | .take(8) 49 | .map(char::from) 50 | .collect() 51 | } 52 | 53 | pub(super) fn gen_hash_from_path(path: &impl AsRef) -> Result { 54 | let mut file = File::open(path).with_context(|| { 55 | format!("Could not open file: `{}`", path.as_ref().display()) 56 | })?; 57 | 58 | let mut hasher = Sha256::new(); 59 | 60 | let mut buffer = [0; 4096]; 61 | 62 | loop { 63 | let bytes_read = file.read(&mut buffer).with_context(|| { 64 | format!("Could not read file: `{}`", path.as_ref().display()) 65 | })?; 66 | if bytes_read == 0 { 67 | break; 68 | } 69 | hasher.update(&buffer[..bytes_read]); 70 | } 71 | 72 | Ok(format!("{:x}", hasher.finalize())) 73 | } 74 | 75 | pub(super) fn gen_hash_from_str(content: &str) -> Result { 76 | let mut hasher = Sha256::new(); 77 | 78 | hasher.update(content.as_bytes()); 79 | 80 | Ok(format!("{:x}", hasher.finalize())) 81 | } 82 | -------------------------------------------------------------------------------- /roscal_cli/src/models/workspace.rs: -------------------------------------------------------------------------------- 1 | use std::path::PathBuf; 2 | 3 | use anyhow::Result; 4 | use serde::{Deserialize, Serialize}; 5 | use thiserror::Error; 6 | 7 | use crate::cli::cli_opts::{Dissect, Merge, Validate}; 8 | 9 | use super::{ 10 | dissect::dissect_workspace, merge::merge_workspace, utils::*, 11 | validate::validate_model, 12 | }; 13 | 14 | #[derive(Error, Debug)] 15 | pub enum CliError { 16 | #[error("Could not parse {0} model from file: {1}\nCause ---> {2}")] 17 | ParseModel(String, String, String), 18 | #[error("Could not parse {0} field for model {1} from file: {2}\nCause ---> {3}")] 19 | ParseBlock(String, String, String, String), 20 | #[error("Unknown output format. Use json or yaml")] 21 | UnknownMergeOpt, 22 | #[error("Unknown uuid version. Use v4 or v5")] 23 | UnknownUuidVer, 24 | } 25 | 26 | #[derive(Debug, Clone)] 27 | pub struct Workspace; 28 | 29 | impl Workspace { 30 | pub async fn dissect( 31 | opts: &Dissect, 32 | ) -> Result<(), Box> { 33 | dissect_workspace(opts).await?; 34 | 35 | Ok(()) 36 | } 37 | 38 | pub async fn merge(opts: &Merge) -> Result<(), Box> { 39 | merge_workspace(opts).await?; 40 | 41 | Ok(()) 42 | } 43 | } 44 | 45 | #[derive(Debug, Clone)] 46 | pub struct Validator; 47 | 48 | impl Validator { 49 | pub async fn validate( 50 | opts: &Validate, 51 | ) -> Result<(), Box> { 52 | validate_model(opts).await?; 53 | 54 | Ok(()) 55 | } 56 | } 57 | 58 | #[derive(Debug, Default, Clone, Deserialize, Serialize)] 59 | pub struct DissectCtx { 60 | pub created_at: String, 61 | pub model_loc: PathBuf, 62 | pub model: String, 63 | pub blocks: Vec, 64 | pub rand: String, 65 | pub root: String, 66 | pub backup: String, 67 | pub modifiable: String, 68 | pub hash: String, 69 | } 70 | 71 | impl DissectCtx { 72 | pub fn is_valid_hash(&self) -> Result { 73 | let path = format!("{}/backup", &self.backup); 74 | let hash = gen_hash_from_path(&path); 75 | 76 | Ok(hash.is_ok() && hash? == self.hash) 77 | } 78 | } 79 | 80 | #[derive(Debug, Default, Clone, Deserialize, Serialize)] 81 | pub struct MergeCtx { 82 | pub created_at: String, 83 | pub hash: String, 84 | pub rand: String, 85 | pub output_dir: String, 86 | pub dissect_workspace_ref: DissectCtx, 87 | } 88 | 89 | impl MergeCtx { 90 | pub fn update_hash(&mut self, content: &str) -> Result<()> { 91 | let hash = gen_hash_from_str(content)?; 92 | self.hash = hash; 93 | 94 | Ok(()) 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "flake-utils": { 4 | "inputs": { 5 | "systems": "systems" 6 | }, 7 | "locked": { 8 | "lastModified": 1705309234, 9 | "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=", 10 | "owner": "numtide", 11 | "repo": "flake-utils", 12 | "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26", 13 | "type": "github" 14 | }, 15 | "original": { 16 | "owner": "numtide", 17 | "repo": "flake-utils", 18 | "type": "github" 19 | } 20 | }, 21 | "naersk": { 22 | "inputs": { 23 | "nixpkgs": "nixpkgs" 24 | }, 25 | "locked": { 26 | "lastModified": 1698420672, 27 | "narHash": "sha256-/TdeHMPRjjdJub7p7+w55vyABrsJlt5QkznPYy55vKA=", 28 | "owner": "nix-community", 29 | "repo": "naersk", 30 | "rev": "aeb58d5e8faead8980a807c840232697982d47b9", 31 | "type": "github" 32 | }, 33 | "original": { 34 | "owner": "nix-community", 35 | "repo": "naersk", 36 | "type": "github" 37 | } 38 | }, 39 | "nixpkgs": { 40 | "locked": { 41 | "lastModified": 1708407374, 42 | "narHash": "sha256-EECzarm+uqnNDCwaGg/ppXCO11qibZ1iigORShkkDf0=", 43 | "owner": "NixOS", 44 | "repo": "nixpkgs", 45 | "rev": "f33dd27a47ebdf11dc8a5eb05e7c8fbdaf89e73f", 46 | "type": "github" 47 | }, 48 | "original": { 49 | "id": "nixpkgs", 50 | "type": "indirect" 51 | } 52 | }, 53 | "nixpkgs_2": { 54 | "locked": { 55 | "lastModified": 1708407374, 56 | "narHash": "sha256-EECzarm+uqnNDCwaGg/ppXCO11qibZ1iigORShkkDf0=", 57 | "owner": "NixOS", 58 | "repo": "nixpkgs", 59 | "rev": "f33dd27a47ebdf11dc8a5eb05e7c8fbdaf89e73f", 60 | "type": "github" 61 | }, 62 | "original": { 63 | "owner": "NixOS", 64 | "ref": "nixpkgs-unstable", 65 | "repo": "nixpkgs", 66 | "type": "github" 67 | } 68 | }, 69 | "root": { 70 | "inputs": { 71 | "flake-utils": "flake-utils", 72 | "naersk": "naersk", 73 | "nixpkgs": "nixpkgs_2" 74 | } 75 | }, 76 | "systems": { 77 | "locked": { 78 | "lastModified": 1681028828, 79 | "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", 80 | "owner": "nix-systems", 81 | "repo": "default", 82 | "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", 83 | "type": "github" 84 | }, 85 | "original": { 86 | "owner": "nix-systems", 87 | "repo": "default", 88 | "type": "github" 89 | } 90 | } 91 | }, 92 | "root": "root", 93 | "version": 7 94 | } 95 | -------------------------------------------------------------------------------- /ROADMAP.md: -------------------------------------------------------------------------------- 1 | # Roadmap And Goals 2 | 3 | If you would like to see your ideas and suggestions getting implemented, please 4 | feel free to make a PR to the roadmap, let's get the conversation started. Any 5 | contributions to the code base are welcome! 6 | 7 | ## Immediate Term 8 | 9 | ### Conversion and Normalisation 10 | 11 | There is a vast swathe of specialised security tools such as DAST, SAST, 12 | SCA, various scanners, audit and compliance checkers etc, each producing their 13 | own data schemas and output formats. As the adoption of OSCAL keeps rising, 14 | undoubtedly it will become one of the primary means of documenting and asserting 15 | security controls. How are we going to convert existing data format to OSCAL 16 | in a relevant and standardised way is one of the first set of problems that 17 | need to be addressed urgently, e.g. ingesting data output such as Sarif, Snyk, 18 | SonarQube, Jfrog XRay and produce risk related blocks for Assessment Results, 19 | or how to parse Splunk output and build observation related blocks for Plan of 20 | Action and Milestones? These points are yet to be answered and warrants the 21 | following actions to be taken: 22 | 23 | - Liaise with companies that build these tools and open up discussions on 24 | normalisation of data 25 | - Obtain advice and feedback from OSCAL end users on what they like to be 26 | implemented, find common ground amongst use cases that can be generalised and 27 | perhaps one day to be standardised 28 | - Build bespoke conversion and normalisation solutions for OSCAL end users and 29 | seek public feedback. Please free free to reach out if your organisation have 30 | such needs 31 | 32 | ### Library and CLI 33 | - Support recursive uuid update for all data types(Currently only core types) 34 | - Support generating full-skeleton empty model templates with placeholders 35 | - Generate auditable logs for CLI runs 36 | - Document signing and encryption, better file integrity checks 37 | 38 | ## Medium Term 39 | 40 | ### Continuously Building OSCAL 41 | - Incorporate into CI/CD pipelines to enable collection of relevant data 42 | - Start looking into annotation/DSL based instrumentation point insertion 43 | 44 | ### OSCAL Visualiser 45 | - Build a web application capable of inspecting, generating and editing OSCAL 46 | model files, focusing on non-tech user friendliness 47 | - Support building task lists, memos, action monitors and external references 48 | for staged model building 49 | 50 | ### Library and CLI 51 | - Support XML format?(This is uncertain given the amount of effort required 52 | and somewhat limited use cases) 53 | - Build adaptor to various storage solutions for documentation indexing and 54 | safeguarding 55 | 56 | ## Long Term Goals 57 | 58 | ### Automatic OSCAL Enforcement 59 | - Documentation-as-Code style automatic security and control enforcement 60 | - Monitoring as well as integration with other existing solutions 61 | -------------------------------------------------------------------------------- /roscal_lib/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! # OSCAL: Referential implementation of Open Security Controls Assessment Language(OSCAL) 2 | //! This library enables users to programmatically parse and build various OSCAL 3 | //! models using the builder pattern, with bi-directional validation enabled on key 4 | //! fields during serialisation/deserialisation. 5 | //! 6 | //! All textual fields are represented as `String` type such as uuid, datetime etc. 7 | //! This library strives to be unopinionated about which library is being used by 8 | //! the user to build certain data field, therefore it does not re-export some of 9 | //! the libraries used internally for validation. The libraries for building these types 10 | //! are specified Cargo.toml such as `chrono`, `uriparse`, `uuid` etc, although you 11 | //! can follow the OSCAL specification and choose whichever that conforms to the requirement. 12 | //! See 13 | //! 14 | //! Currently the latest v1.x is being tracked by this library and primarily supports 15 | //! the roscal_cli tool. 16 | //! 17 | //! 18 | //! # Example of a building a minimum Catalog model 19 | //! 20 | //! ```toml 21 | //! [dependencies] 22 | //! roscal_lib = "0.1.0" 23 | //! uuid = { version = "1.6.1", features = ["v4"] } 24 | //! chrono = { version = "0.4.31", features = ["serde"] } 25 | //! ``` 26 | //! 27 | //! ``` 28 | //! use roscal_lib::control::catalog::{self, CatalogBuilder, CatalogClassBuilder}; 29 | //! 30 | //! fn builder() { 31 | //! let mut catalog_builder = CatalogBuilder::default(); 32 | //! let mut catalog_class_builder = CatalogClassBuilder::default(); 33 | //! 34 | //! let uuid = uuid::Uuid::new_v4().to_string(); 35 | //! let last_modified = chrono::DateTime::parse_from_rfc3339("2023-12-31T23:59:59Z") 36 | //! .unwrap().to_string(); 37 | //! let metadata = catalog::DocumentMetadataBuilder::default() 38 | //! .version("1") 39 | //! .title("catalog") 40 | //! .oscal_version("1.0.0") 41 | //! .last_modified(last_modified) 42 | //! .build() 43 | //! .expect("unable to build metadata"); 44 | //! 45 | //! let catalog_class = catalog_class_builder 46 | //! .uuid(uuid) 47 | //! .metadata(metadata) 48 | //! .build() 49 | //! .expect("unable to build catalog class"); 50 | //! let catalog = catalog_builder 51 | //! .catalog(catalog_class) 52 | //! .build() 53 | //! .expect("unable to build catalog"); 54 | //! 55 | //! assert_eq!(true, serde_json::to_string(&catalog).is_ok()) 56 | //! } 57 | //! ``` 58 | #![forbid(unsafe_code)] 59 | 60 | pub mod assessment; 61 | mod common_impl; 62 | pub mod control; 63 | pub mod implementation; 64 | mod uuid_impl; 65 | mod validation; 66 | 67 | /// Update UUID v4/v5 if model content has changed 68 | pub trait UpdateUuid: Sized { 69 | fn update_uuid_v4(&mut self, rhs: &Self) -> &mut Self; 70 | fn update_uuid_v5(&mut self, rhs: &Self) -> &mut Self; 71 | } 72 | -------------------------------------------------------------------------------- /roscal_cli/src/cli/cli_fn.rs: -------------------------------------------------------------------------------- 1 | use crate::models::workspace::{Validator, Workspace}; 2 | 3 | use super::cli_opts::{Dissect, Merge, Validate}; 4 | 5 | pub async fn run_dissect( 6 | opts: &Dissect, 7 | ) -> Result<(), Box> { 8 | Workspace::dissect(opts).await?; 9 | 10 | Ok(()) 11 | } 12 | 13 | pub async fn run_merge(opts: &Merge) -> Result<(), Box> { 14 | Workspace::merge(opts).await?; 15 | 16 | Ok(()) 17 | } 18 | 19 | pub async fn run_validate( 20 | opts: &Validate, 21 | ) -> Result<(), Box> { 22 | Validator::validate(opts).await?; 23 | 24 | Ok(()) 25 | } 26 | 27 | pub async fn show_dissect() -> Result<(), Box> { 28 | let desc = r#" 29 | Available Model Options: 30 | 31 | One of: 32 | - AssessmentPlan 33 | - AssessmentResults 34 | - Poam 35 | - Catalog 36 | - Profile 37 | - ComponentDefinition 38 | - Ssp 39 | 40 | Available Blocks Options: 41 | 42 | Under Assessment Plan Model: 43 | 44 | One of: 45 | - all 46 | 47 | Or 48 | 49 | Any of: 50 | - uuid 51 | - metadata 52 | - import_ssp 53 | - local_definitions 54 | - terms_and_conditions 55 | - reviewed_controls 56 | - assessment_subjects 57 | - assessment_assets 58 | - tasks 59 | - back_matter 60 | 61 | Under Assessment Results Model: 62 | 63 | One of: 64 | - all 65 | 66 | Or 67 | 68 | Any of: 69 | - uuid 70 | - metadata 71 | - import_ap 72 | - local_definitions 73 | - results 74 | - back_matter 75 | 76 | Under Plan of Action and Milestones Model: 77 | 78 | One of: 79 | - all 80 | 81 | Or 82 | 83 | Any of: 84 | - uuid 85 | - metadata 86 | - import_ssp 87 | - system_id 88 | - local_definitions 89 | - observations 90 | - risks 91 | - findings 92 | - poam_items 93 | - back_matter 94 | 95 | Under Catalog Model: 96 | 97 | One of: 98 | - all 99 | 100 | Or 101 | 102 | Any of: 103 | - uuid 104 | - metadata 105 | - params 106 | - controls 107 | - groups 108 | - back_matter 109 | 110 | Under Profile Model: 111 | 112 | One of: 113 | - all 114 | 115 | Or 116 | 117 | Any of: 118 | - uuid 119 | - metadata 120 | - imports 121 | - merge 122 | - modify 123 | - back_matter 124 | 125 | Under Component Definition Model: 126 | 127 | One of: 128 | - all 129 | 130 | Or 131 | 132 | Any of: 133 | - uuid 134 | - metadata 135 | - import_component_definitions 136 | - components 137 | - capabilities 138 | - back_matter 139 | 140 | Under System Security Plan Model: 141 | 142 | One of: 143 | - all 144 | 145 | Or 146 | 147 | Any of: 148 | - uuid 149 | - metadata 150 | - import_profile 151 | - system_characteristics 152 | - system_implementation 153 | - control_implementation 154 | - back_matter 155 | "#; 156 | 157 | println!("{desc}"); 158 | 159 | Ok(()) 160 | } 161 | -------------------------------------------------------------------------------- /roscal_lib/tests/component-definition/yaml/example-component.yaml: -------------------------------------------------------------------------------- 1 | component-definition: 2 | uuid: 8223d65f-57a9-4689-8f06-2a975ae2ad72 3 | metadata: 4 | title: Test Component Definition 5 | last-modified: "2024-02-01T13:57:28.355446-04:00" 6 | version: "20231012" 7 | oscal-version: 1.1.2 8 | parties: 9 | - uuid: ee47836c-877c-4007-bbf3-c9d9bd805a9a 10 | type: organization 11 | name: Test Vendor 12 | components: 13 | - uuid: b036a6ac-6cff-4066-92bc-74ddfd9ad6fa 14 | type: software 15 | title: test component 1 16 | description: This is a software component that implements basic authentication mechanisms. 17 | responsible-roles: 18 | - role-id: provider 19 | party-uuids: 20 | - ee47836c-877c-4007-bbf3-c9d9bd805a9a 21 | control-implementations: 22 | - uuid: cfcdd674-8595-4f98-a9d1-3ac70825c49f 23 | source: '#f52e1458-7a97-49fd-8189-6af6a4e7051b' 24 | description: This is a partial implementation of the SP 800-53 rev4 catalog, focusing on the control enhancement AC-2 (3). 25 | implemented-requirements: 26 | - uuid: d1016df0-9b5c-4839-86cd-f9c1d113077b 27 | control-id: ac-2.3 28 | description: Inactive accounts are automatically disabled based on the duration specified by the duration parameter. Disabled accounts are expected to be reviewed and removed when appropriate. 29 | - uuid: 22dbff65-9729-449f-9dfc-4e5fee0906de 30 | source: '#ec013e7d-e2a2-4ddb-a174-fbd9da24b0d8' 31 | description: This is a partial implementation of the FedRAMP High profile, focusing on the control enhancement AC-2 (3). 32 | implemented-requirements: 33 | - uuid: 65e30b37-0640-4844-9f42-b2a7ae944bb1 34 | control-id: ac-2.3 35 | description: An alternate narrative for FedRAMP.. 36 | back-matter: 37 | resources: 38 | - uuid: f52e1458-7a97-49fd-8189-6af6a4e7051b 39 | description: 'NIST Special Publication 800-53 Revision 4: Security and Privacy Controls for Federal Information Systems and Organizations' 40 | rlinks: 41 | - href: ../../../../nist.gov/SP800-53/rev4/xml/NIST_SP-800-53_rev4_catalog.xml 42 | media-type: application/oscal.catalog+xml 43 | - href: ../../../../nist.gov/SP800-53/rev4/json/NIST_SP-800-53_rev4_catalog.json 44 | media-type: application/oscal.catalog+json 45 | - href: ../../../../nist.gov/SP800-53/rev4/yaml/NIST_SP-800-53_rev4_catalog.yaml 46 | media-type: application/oscal.catalog+yaml 47 | - uuid: ec013e7d-e2a2-4ddb-a174-fbd9da24b0d8 48 | description: FedRAMP Revision 4 High Baseline Profile 49 | rlinks: 50 | - href: https://raw.githubusercontent.com/GSA/fedramp-automation/master/dist/content/rev4/baselines/xml/FedRAMP_rev4_HIGH-baseline_profile.xml 51 | media-type: application/oscal.catalog+xml 52 | - href: https://raw.githubusercontent.com/GSA/fedramp-automation/master/dist/content/rev4/baselines/json/FedRAMP_rev4_HIGH-baseline_profile.json 53 | media-type: application/oscal.catalog+json 54 | - href: https://raw.githubusercontent.com/GSA/fedramp-automation/master/dist/content/rev4/baselines/yaml/FedRAMP_rev4_HIGH-baseline_profile.yaml 55 | media-type: application/oscal.catalog+yaml 56 | -------------------------------------------------------------------------------- /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | run-name: "CI run '${{ github.head_ref || github.ref_name }}'" 4 | 5 | on: 6 | workflow_dispatch: 7 | push: 8 | branches: 9 | - main 10 | pull_request: 11 | 12 | concurrency: 13 | group: '${{ github.workflow }} @ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}' 14 | cancel-in-progress: true 15 | 16 | jobs: 17 | format: 18 | name: Cargo format 19 | runs-on: ubuntu-latest 20 | steps: 21 | 22 | - name: Install toolchain 23 | uses: dtolnay/rust-toolchain@stable 24 | with: 25 | toolchain: 1.85.0 26 | components: rustfmt 27 | 28 | - name: Checkout source 29 | uses: actions/checkout@v4 30 | 31 | - name: Setup cache 32 | uses: Swatinem/rust-cache@v2 33 | with: 34 | save-if: ${{ github.ref == 'refs/heads/main' }} 35 | 36 | - name: Check format 37 | run: cargo fmt --all 38 | 39 | security-check: 40 | name: Security check 41 | runs-on: ubuntu-latest 42 | steps: 43 | 44 | - name: Install toolchain 45 | uses: dtolnay/rust-toolchain@stable 46 | with: 47 | toolchain: 1.85.0 48 | components: rustfmt 49 | 50 | - name: Checkout sources 51 | uses: actions/checkout@v4 52 | 53 | - name: Install cargo-deny 54 | run: cargo install cargo-deny --locked 55 | 56 | - name: Install cargo-vet 57 | run: cargo install cargo-vet --locked 58 | 59 | - name: Run cargo deny 60 | run: cargo deny check 61 | 62 | - name: Run cargo vet 63 | run: cargo vet init && cargo vet 64 | 65 | - name: Report failure 66 | if: failure() 67 | run: | 68 | echo "## Security Check Failed" >> $GITHUB_STEP_SUMMARY 69 | 70 | clippy: 71 | name: Check clippy 72 | runs-on: ubuntu-latest 73 | steps: 74 | 75 | - name: Install toolchain 76 | uses: dtolnay/rust-toolchain@stable 77 | with: 78 | toolchain: 1.85.0 79 | components: clippy 80 | 81 | - name: Checkout sources 82 | uses: actions/checkout@v4 83 | 84 | - name: Setup cache 85 | uses: Swatinem/rust-cache@v2 86 | with: 87 | save-if: ${{ github.ref == 'refs/heads/main' }} 88 | 89 | - name: Install dependencies 90 | run: | 91 | sudo apt-get -y update 92 | sudo apt-get -y install npm 93 | 94 | - name: Install quicktype 95 | run: | 96 | npm install -g quicktype 97 | 98 | - name: Run clippy 99 | run: cargo clippy -- -D warnings 100 | 101 | build-test: 102 | name: Cargo test 103 | runs-on: ubuntu-latest 104 | steps: 105 | 106 | - name: Install stable toolchain 107 | uses: dtolnay/rust-toolchain@stable 108 | with: 109 | toolchain: 1.85.0 110 | 111 | - name: Checkout sources 112 | uses: actions/checkout@v4 113 | 114 | - name: Setup cache 115 | uses: Swatinem/rust-cache@v2 116 | with: 117 | save-if: ${{ github.ref == 'refs/heads/main' }} 118 | 119 | - name: Install dependencies 120 | run: | 121 | sudo apt-get -y update 122 | sudo apt-get -y install npm 123 | 124 | - name: Install quicktype 125 | run: | 126 | npm install -g quicktype 127 | 128 | - name: Run test 129 | run: cargo test 130 | -------------------------------------------------------------------------------- /roscal_cli/src/cli/cli_opts.rs: -------------------------------------------------------------------------------- 1 | use std::path::PathBuf; 2 | 3 | use clap::{Args, Parser, Subcommand}; 4 | 5 | #[derive(Debug, Clone, Parser)] 6 | #[clap(author = "Author: Geoffrey Borough")] 7 | #[clap(version)] 8 | #[clap(about = "Cli Tool For Processing and Manipulating OSCAL Model File")] 9 | pub struct OscalCli { 10 | #[clap(subcommand)] 11 | pub command: Commands, 12 | } 13 | 14 | #[non_exhaustive] 15 | #[derive(Debug, Clone, Subcommand)] 16 | pub enum Commands { 17 | /// Dissect OSCAL model file and generate a workspace for viewing and editing 18 | /// Full Example: 19 | /// roscal dissect --file /dir/catalog.json 20 | /// --model Catalog 21 | /// --blocks controls,groups 22 | /// --output-dir /home/workspace 23 | /// --parse-markup 24 | #[clap(verbatim_doc_comment)] 25 | Dissect(#[clap(flatten)] Dissect), 26 | /// Merge existing worspace and generate new OSCAL model file 27 | /// Full Example: 28 | /// roscal merge --dir /dir/existing_workspace 29 | /// --output-dir /dir/merged 30 | /// --output-format yaml 31 | /// --update-uuid v4 32 | #[clap(verbatim_doc_comment)] 33 | Merge(#[clap(flatten)] Merge), 34 | /// Validate a specific type of OSCAL model file 35 | /// Full Example: 36 | /// roscal validate --file /dir/catalog.json 37 | /// --model Catalog 38 | #[clap(verbatim_doc_comment)] 39 | Validate(#[clap(flatten)] Validate), 40 | /// Show available models and blocks for dissect operation 41 | ShowDissect, 42 | } 43 | 44 | #[derive(Args, Debug, Default, Clone)] 45 | pub struct Dissect { 46 | /// Location of the OSCAL model file 47 | #[arg(long)] 48 | pub file: PathBuf, 49 | /// Specifiy which OSCAL model to be processed 50 | /// Run `roscal show-dissect` for available models 51 | #[arg(long, verbatim_doc_comment)] 52 | pub model: String, 53 | /// Specifiy which blocks to be dissected 54 | /// Duplicate blocks will be combined 55 | /// Run `roscal show-dissect` for available blocks 56 | #[arg(long, num_args = 1.., value_delimiter = ',', verbatim_doc_comment)] 57 | pub blocks: Vec, 58 | /// Specify where dissect workspace should be created 59 | /// Optional. Will use current directory if unspecified 60 | #[arg(long, verbatim_doc_comment)] 61 | pub output_dir: Option, 62 | /// Whether to parse markup lines 63 | /// Currently experimental feature 64 | /// see https://pages.nist.gov/metaschema/specification/datatypes/#markup-data-types 65 | #[arg(long, verbatim_doc_comment)] 66 | pub parse_markup: bool, 67 | } 68 | 69 | #[derive(Args, Debug, Default, Clone)] 70 | pub struct Merge { 71 | /// Location of existing workspace created by dissect operation 72 | /// Optional. Can be run directly in existing workspace 73 | #[arg(long, verbatim_doc_comment)] 74 | pub dir: Option, 75 | /// Specify where merged file should be created 76 | /// Optional. Can be run directly in existing workspace 77 | #[arg(long, verbatim_doc_comment)] 78 | pub output_dir: Option, 79 | /// Options: json or yaml 80 | #[arg(long)] 81 | pub output_format: String, 82 | /// Options: v4 or v5 (as in uuid version) 83 | /// Optional. No-op if model unchanged or uuid manually updated 84 | #[arg(long, verbatim_doc_comment)] 85 | pub update_uuid: Option, 86 | } 87 | 88 | #[derive(Args, Debug, Default, Clone)] 89 | pub struct Validate { 90 | /// Location of OSCAL model file 91 | #[arg(long)] 92 | pub file: PathBuf, 93 | /// Model type of OSCAL model file 94 | /// Run `roscal show-dissect` for available models 95 | #[arg(long, verbatim_doc_comment)] 96 | pub model: String, 97 | } 98 | -------------------------------------------------------------------------------- /roscal_cli/src/models/validate.rs: -------------------------------------------------------------------------------- 1 | use std::{fs::File, io::BufReader, str::FromStr}; 2 | 3 | use anyhow::{Context, Result}; 4 | use roscal_lib::{ 5 | assessment::{ 6 | assessment_plan::AssessmentPlan, assessment_results::AssessmentResults, 7 | poam::PlanOfActionAndMilestones, 8 | }, 9 | control::{catalog::Catalog, profile::Profile}, 10 | implementation::{ 11 | component_definition::ComponentDefinition, ssp::SystemSecurityPlan, 12 | }, 13 | }; 14 | 15 | use crate::cli::cli_opts::Validate; 16 | 17 | use super::{model::OscalModels, validation::is_valid_model}; 18 | 19 | pub(super) async fn validate_model(opts: &Validate) -> Result<()> { 20 | if !is_valid_model(&opts.model) { 21 | std::process::exit(1) 22 | } 23 | 24 | let file = File::open(&opts.file).with_context(|| { 25 | format!("Could not open model file: `{}`", &opts.file.display()) 26 | })?; 27 | 28 | let reader = BufReader::new(file); 29 | 30 | match OscalModels::from_str(&opts.model).with_context(|| { 31 | "Could not determine the provided OSCAL model".to_string() 32 | })? { 33 | OscalModels::AssessmentPlan => { 34 | let res: Result = 35 | serde_json::from_reader(reader); 36 | if res.is_ok() { 37 | println!("This is a valid Assessment Plan model") 38 | } else { 39 | println!("This is not a valid Assessment Plan model") 40 | } 41 | } 42 | OscalModels::AssessmentResults => { 43 | let res: Result = 44 | serde_json::from_reader(reader); 45 | if res.is_ok() { 46 | println!("This is a valid Assessment Result model") 47 | } else { 48 | println!("This is not a valid Assessment Result model") 49 | } 50 | } 51 | OscalModels::Poam => { 52 | let res: Result = 53 | serde_json::from_reader(reader); 54 | if res.is_ok() { 55 | println!("This is a valid Plan of Action and Milestones model") 56 | } else { 57 | println!( 58 | "This is not a valid Plan of Action and Milestones model" 59 | ) 60 | } 61 | } 62 | OscalModels::Catalog => { 63 | let res: Result = 64 | serde_json::from_reader(reader); 65 | if res.is_ok() { 66 | println!("This is a valid Catalog model") 67 | } else { 68 | println!("This is not a valid Catalog model") 69 | } 70 | } 71 | OscalModels::Profile => { 72 | let res: Result = 73 | serde_json::from_reader(reader); 74 | if res.is_ok() { 75 | println!("This is a valid Profile model") 76 | } else { 77 | println!("This is not a valid Profile model") 78 | } 79 | } 80 | OscalModels::ComponentDefinition => { 81 | let res: Result = 82 | serde_json::from_reader(reader); 83 | if res.is_ok() { 84 | println!("This is a valid Component Definition model") 85 | } else { 86 | println!("This is not a valid Component Definition model") 87 | } 88 | } 89 | OscalModels::Ssp => { 90 | let res: Result = 91 | serde_json::from_reader(reader); 92 | if res.is_ok() { 93 | println!("This is a valid System Security Plan model") 94 | } else { 95 | println!("This is not a valid System Security Plan model") 96 | } 97 | } 98 | } 99 | 100 | Ok(()) 101 | } 102 | -------------------------------------------------------------------------------- /roscal_lib/tests/component-definition/json/example-component.json: -------------------------------------------------------------------------------- 1 | { 2 | "component-definition": { 3 | "uuid": "8223d65f-57a9-4689-8f06-2a975ae2ad72", 4 | "metadata": { 5 | "title": "Test Component Definition", 6 | "last-modified": "2024-02-01T13:57:28.355446-04:00", 7 | "version": "20231012", 8 | "oscal-version": "1.1.2", 9 | "parties": [ 10 | { 11 | "uuid": "ee47836c-877c-4007-bbf3-c9d9bd805a9a", 12 | "type": "organization", 13 | "name": "Test Vendor" 14 | } 15 | ] 16 | }, 17 | "components": [ 18 | { 19 | "uuid": "b036a6ac-6cff-4066-92bc-74ddfd9ad6fa", 20 | "type": "software", 21 | "title": "test component 1", 22 | "description": "This is a software component that implements basic authentication mechanisms.", 23 | "responsible-roles": [ 24 | { 25 | "role-id": "provider", 26 | "party-uuids": ["ee47836c-877c-4007-bbf3-c9d9bd805a9a"] 27 | } 28 | ], 29 | "control-implementations": [ 30 | { 31 | "uuid": "cfcdd674-8595-4f98-a9d1-3ac70825c49f", 32 | "source": "#f52e1458-7a97-49fd-8189-6af6a4e7051b", 33 | "description": "This is a partial implementation of the SP 800-53 rev4 catalog, focusing on the control enhancement AC-2 (3).", 34 | "implemented-requirements": [ 35 | { 36 | "uuid": "d1016df0-9b5c-4839-86cd-f9c1d113077b", 37 | "control-id": "ac-2.3", 38 | "description": "Inactive accounts are automatically disabled based on the duration specified by the duration parameter. Disabled accounts are expected to be reviewed and removed when appropriate." 39 | } 40 | ] 41 | }, 42 | { 43 | "uuid": "22dbff65-9729-449f-9dfc-4e5fee0906de", 44 | "source": "#ec013e7d-e2a2-4ddb-a174-fbd9da24b0d8", 45 | "description": "This is a partial implementation of the FedRAMP High profile, focusing on the control enhancement AC-2 (3).", 46 | "implemented-requirements": [ 47 | { 48 | "uuid": "65e30b37-0640-4844-9f42-b2a7ae944bb1", 49 | "control-id": "ac-2.3", 50 | "description": "An alternate narrative for FedRAMP.." 51 | } 52 | ] 53 | } 54 | ] 55 | } 56 | ], 57 | "back-matter": { 58 | "resources": [ 59 | { 60 | "uuid": "f52e1458-7a97-49fd-8189-6af6a4e7051b", 61 | "description": "NIST Special Publication 800-53 Revision 4: Security and Privacy Controls for Federal Information Systems and Organizations", 62 | "rlinks": [ 63 | { 64 | "href": "../../../../nist.gov/SP800-53/rev4/xml/NIST_SP-800-53_rev4_catalog.xml", 65 | "media-type": "application/oscal.catalog+xml" 66 | }, 67 | { 68 | "href": "../../../../nist.gov/SP800-53/rev4/json/NIST_SP-800-53_rev4_catalog.json", 69 | "media-type": "application/oscal.catalog+json" 70 | }, 71 | { 72 | "href": "../../../../nist.gov/SP800-53/rev4/yaml/NIST_SP-800-53_rev4_catalog.yaml", 73 | "media-type": "application/oscal.catalog+yaml" 74 | } 75 | ] 76 | }, 77 | { 78 | "uuid": "ec013e7d-e2a2-4ddb-a174-fbd9da24b0d8", 79 | "description": "FedRAMP Revision 4 High Baseline Profile", 80 | "rlinks": [ 81 | { 82 | "href": "https://raw.githubusercontent.com/GSA/fedramp-automation/master/dist/content/rev4/baselines/xml/FedRAMP_rev4_HIGH-baseline_profile.xml", 83 | "media-type": "application/oscal.catalog+xml" 84 | }, 85 | { 86 | "href": "https://raw.githubusercontent.com/GSA/fedramp-automation/master/dist/content/rev4/baselines/json/FedRAMP_rev4_HIGH-baseline_profile.json", 87 | "media-type": "application/oscal.catalog+json" 88 | }, 89 | { 90 | "href": "https://raw.githubusercontent.com/GSA/fedramp-automation/master/dist/content/rev4/baselines/yaml/FedRAMP_rev4_HIGH-baseline_profile.yaml", 91 | "media-type": "application/oscal.catalog+yaml" 92 | } 93 | ] 94 | } 95 | ] 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /roscal_lib/tests/component-definition/json/example-component-min.json: -------------------------------------------------------------------------------- 1 | { 2 | "component-definition": { 3 | "uuid": "8223d65f-57a9-4689-8f06-2a975ae2ad72", 4 | "metadata": { 5 | "title": "Test Component Definition", 6 | "last-modified": "2024-02-01T13:57:28.355446-04:00", 7 | "version": "20231012", 8 | "oscal-version": "1.1.2", 9 | "parties": [ 10 | { 11 | "uuid": "ee47836c-877c-4007-bbf3-c9d9bd805a9a", 12 | "type": "organization", 13 | "name": "Test Vendor" 14 | } 15 | ] 16 | }, 17 | "components": [ 18 | { 19 | "uuid": "b036a6ac-6cff-4066-92bc-74ddfd9ad6fa", 20 | "type": "software", 21 | "title": "test component 1", 22 | "description": "This is a software component that implements basic authentication mechanisms.", 23 | "responsible-roles": [ 24 | { 25 | "role-id": "provider", 26 | "party-uuids": ["ee47836c-877c-4007-bbf3-c9d9bd805a9a"] 27 | } 28 | ], 29 | "control-implementations": [ 30 | { 31 | "uuid": "cfcdd674-8595-4f98-a9d1-3ac70825c49f", 32 | "source": "#f52e1458-7a97-49fd-8189-6af6a4e7051b", 33 | "description": "This is a partial implementation of the SP 800-53 rev4 catalog, focusing on the control enhancement AC-2 (3).", 34 | "implemented-requirements": [ 35 | { 36 | "uuid": "d1016df0-9b5c-4839-86cd-f9c1d113077b", 37 | "control-id": "ac-2.3", 38 | "description": "Inactive accounts are automatically disabled based on the duration specified by the duration parameter. Disabled accounts are expected to be reviewed and removed when appropriate." 39 | } 40 | ] 41 | }, 42 | { 43 | "uuid": "22dbff65-9729-449f-9dfc-4e5fee0906de", 44 | "source": "#ec013e7d-e2a2-4ddb-a174-fbd9da24b0d8", 45 | "description": "This is a partial implementation of the FedRAMP High profile, focusing on the control enhancement AC-2 (3).", 46 | "implemented-requirements": [ 47 | { 48 | "uuid": "65e30b37-0640-4844-9f42-b2a7ae944bb1", 49 | "control-id": "ac-2.3", 50 | "description": "An alternate narrative for FedRAMP.." 51 | } 52 | ] 53 | } 54 | ] 55 | } 56 | ], 57 | "back-matter": { 58 | "resources": [ 59 | { 60 | "uuid": "f52e1458-7a97-49fd-8189-6af6a4e7051b", 61 | "description": "NIST Special Publication 800-53 Revision 4: Security and Privacy Controls for Federal Information Systems and Organizations", 62 | "rlinks": [ 63 | { 64 | "href": "../../../../nist.gov/SP800-53/rev4/xml/NIST_SP-800-53_rev4_catalog.xml", 65 | "media-type": "application/oscal.catalog+xml" 66 | }, 67 | { 68 | "href": "../../../../nist.gov/SP800-53/rev4/json/NIST_SP-800-53_rev4_catalog.json", 69 | "media-type": "application/oscal.catalog+json" 70 | }, 71 | { 72 | "href": "../../../../nist.gov/SP800-53/rev4/yaml/NIST_SP-800-53_rev4_catalog.yaml", 73 | "media-type": "application/oscal.catalog+yaml" 74 | } 75 | ] 76 | }, 77 | { 78 | "uuid": "ec013e7d-e2a2-4ddb-a174-fbd9da24b0d8", 79 | "description": "FedRAMP Revision 4 High Baseline Profile", 80 | "rlinks": [ 81 | { 82 | "href": "https://raw.githubusercontent.com/GSA/fedramp-automation/master/dist/content/rev4/baselines/xml/FedRAMP_rev4_HIGH-baseline_profile.xml", 83 | "media-type": "application/oscal.catalog+xml" 84 | }, 85 | { 86 | "href": "https://raw.githubusercontent.com/GSA/fedramp-automation/master/dist/content/rev4/baselines/json/FedRAMP_rev4_HIGH-baseline_profile.json", 87 | "media-type": "application/oscal.catalog+json" 88 | }, 89 | { 90 | "href": "https://raw.githubusercontent.com/GSA/fedramp-automation/master/dist/content/rev4/baselines/yaml/FedRAMP_rev4_HIGH-baseline_profile.yaml", 91 | "media-type": "application/oscal.catalog+yaml" 92 | } 93 | ] 94 | } 95 | ] 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /roscal_cli/src/models/validation.rs: -------------------------------------------------------------------------------- 1 | use std::str::FromStr; 2 | 3 | use super::model::*; 4 | 5 | pub(super) fn is_valid_model(model: &str) -> bool { 6 | if OscalModels::from_str(model).is_err() { 7 | eprintln!("Invalid model provided: {}", model); 8 | return false; 9 | } 10 | 11 | true 12 | } 13 | 14 | pub(super) fn is_valid_assessment_plan_block(blocks: &Vec) -> bool { 15 | let mut col = String::new(); 16 | 17 | if blocks.len() > 1 && blocks.iter().any(|v| v == "all") { 18 | eprintln!("Multiple block cannot include `all` option"); 19 | return false; 20 | } 21 | 22 | blocks 23 | .iter() 24 | .filter(|v| AssessmentPlanBlock::from_str(v).is_err()) 25 | .for_each(|v| col.push_str(v)); 26 | 27 | if col.is_empty() { 28 | true 29 | } else { 30 | eprintln!("Invalid assessment plan block provided: {:?}", blocks); 31 | false 32 | } 33 | } 34 | 35 | pub(super) fn is_valid_assessment_results_block(blocks: &Vec) -> bool { 36 | let mut col = String::new(); 37 | 38 | if blocks.len() > 1 && blocks.iter().any(|v| v == "all") { 39 | eprintln!("Multiple block cannot include `all` option"); 40 | return false; 41 | } 42 | 43 | blocks 44 | .iter() 45 | .filter(|v| AssessmentResultsBlock::from_str(v).is_err()) 46 | .for_each(|v| col.push_str(v)); 47 | 48 | if col.is_empty() { 49 | true 50 | } else { 51 | eprintln!("Invalid assessment results block provided: {:?}", blocks); 52 | false 53 | } 54 | } 55 | 56 | pub(super) fn is_valid_poam_block(blocks: &Vec) -> bool { 57 | let mut col = String::new(); 58 | 59 | if blocks.len() > 1 && blocks.iter().any(|v| v == "all") { 60 | eprintln!("Multiple block cannot include `all` option"); 61 | return false; 62 | } 63 | 64 | blocks 65 | .iter() 66 | .filter(|v| PoamBlock::from_str(v).is_err()) 67 | .for_each(|v| col.push_str(v)); 68 | 69 | if col.is_empty() { 70 | true 71 | } else { 72 | eprintln!("Invalid poam block provided: {:?}", blocks); 73 | false 74 | } 75 | } 76 | 77 | pub(super) fn is_valid_catalog_block(blocks: &Vec) -> bool { 78 | let mut col = String::new(); 79 | 80 | if blocks.len() > 1 && blocks.iter().any(|v| v == "all") { 81 | eprintln!("Multiple block cannot include `all` option"); 82 | return false; 83 | } 84 | 85 | blocks 86 | .iter() 87 | .filter(|v| CatalogBlock::from_str(v).is_err()) 88 | .for_each(|v| col.push_str(v)); 89 | 90 | if col.is_empty() { 91 | true 92 | } else { 93 | eprintln!("Invalid catalog block provided: {:?}", blocks); 94 | false 95 | } 96 | } 97 | 98 | pub(super) fn is_valid_profile_block(blocks: &Vec) -> bool { 99 | let mut col = String::new(); 100 | 101 | if blocks.len() > 1 && blocks.iter().any(|v| v == "all") { 102 | eprintln!("Multiple block cannot include `all` option"); 103 | return false; 104 | } 105 | 106 | blocks 107 | .iter() 108 | .filter(|v| ProfileBlock::from_str(v).is_err()) 109 | .for_each(|v| col.push_str(v)); 110 | 111 | if col.is_empty() { 112 | true 113 | } else { 114 | eprintln!("Invalid profile block provided: {:?}", blocks); 115 | false 116 | } 117 | } 118 | 119 | pub(super) fn is_valid_component_definition_block( 120 | blocks: &Vec, 121 | ) -> bool { 122 | let mut col = String::new(); 123 | 124 | if blocks.len() > 1 && blocks.iter().any(|v| v == "all") { 125 | eprintln!("Multiple block cannot include `all` option"); 126 | return false; 127 | } 128 | 129 | blocks 130 | .iter() 131 | .filter(|v| ComponentDefinitionBlock::from_str(v).is_err()) 132 | .for_each(|v| col.push_str(v)); 133 | 134 | if col.is_empty() { 135 | true 136 | } else { 137 | eprintln!("Invalid component definition block provided: {:?}", blocks); 138 | false 139 | } 140 | } 141 | 142 | pub(super) fn is_valid_ssp_block(blocks: &Vec) -> bool { 143 | let mut col = String::new(); 144 | 145 | if blocks.len() > 1 && blocks.iter().any(|v| v == "all") { 146 | eprintln!("Multiple block cannot include `all` option"); 147 | return false; 148 | } 149 | 150 | blocks 151 | .iter() 152 | .filter(|v| SspBlock::from_str(v).is_err()) 153 | .for_each(|v| col.push_str(v)); 154 | 155 | if col.is_empty() { 156 | true 157 | } else { 158 | eprintln!("Invalid ssp block provided: {:?}", blocks); 159 | false 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /roscal_cli/tests/data/compdef.yaml: -------------------------------------------------------------------------------- 1 | component-definition: 2 | uuid: a7ba800c-a432-44cd-9075-0862cd66da6b 3 | metadata: 4 | title: MongoDB Component Definition Example 5 | last-modified: "2024-02-01T13:57:28.355446-04:00" 6 | version: "20231012" 7 | oscal-version: 1.1.2 8 | roles: 9 | - id: provider 10 | title: Provider 11 | parties: 12 | - uuid: ef7c799a-c50e-49ab-83e0-515e989e6df1 13 | type: organization 14 | name: MongoDB 15 | links: 16 | - href: https://www.mongodb.com 17 | rel: website 18 | components: 19 | - uuid: 91f646c5-b1b6-4786-9ec3-2305a044e217 20 | type: service 21 | title: MongoDB 22 | description: MongoDB is a source-available, cross-platform document-oriented database program. Classified as a NoSQL database program, MongoDB uses JSON-like documents with optional schemas. 23 | purpose: Provides a NoSQL database service 24 | responsible-roles: 25 | - role-id: provider 26 | party-uuids: 27 | - ef7c799a-c50e-49ab-83e0-515e989e6df1 28 | - role-id: customer 29 | protocols: 30 | - uuid: 2b4a1b3a-cbc5-4cc8-bde6-7437c28c4e54 31 | name: mongodb 32 | title: Primary daemon process for the MongoDB system. 33 | port-ranges: 34 | - start: 27017 35 | end: 27017 36 | transport: TCP 37 | - uuid: 99d8d4e5-e734-4e05-a2f9-7353097b8b61 38 | name: mongodb-shardsrv 39 | title: MongoDB protocol for sharding with shardsrv option. 40 | port-ranges: 41 | - start: 27018 42 | end: 27018 43 | transport: TCP 44 | - uuid: 6fa762f1-09ca-44d5-a94c-cfceb57debd5 45 | name: mongodb-configsvr 46 | title: MongoDB protocol for configsrv operation. 47 | port-ranges: 48 | - start: 27019 49 | end: 27019 50 | transport: TCP 51 | control-implementations: 52 | - uuid: 49f0b690-ed9f-4f32-aae0-625b77aa6d27 53 | source: '#ba047e56-faef-430c-bafb-c54e9a87c6e8' 54 | description: MongoDB control implementations for NIST SP 800-53 revision 5. 55 | implemented-requirements: 56 | - uuid: cf8338c5-fb6e-4593-a4a8-b3c4946ee080 57 | control-id: sc-8 58 | description: MongoDB's implementation of SC-8 control. The details of the implementation are provided at the statement level. 59 | set-parameters: 60 | - param-id: sc-8_prm_1 61 | values: 62 | - confidentiality 63 | statements: 64 | - statement-id: sc-8_smt 65 | uuid: bb9219b1-e51c-4680-abb0-616a43bbfbb1 66 | description: 'MongoDB implements TLS 1.x to protect the {{ insert: param, sc-8_prm_1 }} of transmitted data by encrypting data in transit, preventing unauthorized disclosure or changes to information during transmission.' 67 | - uuid: cf8338c5-fb6e-4593-a4a8-b3c4946ee081 68 | control-id: sc-8.1 69 | description: MongoDB implements cryptographic mechanisms (TLS 1.x) to provide cryptographic protection for data in transit. 70 | set-parameters: 71 | - param-id: sc-8.1_prm_1 72 | values: 73 | - prevent unauthorized disclosure of information 74 | statements: 75 | - statement-id: sc-8.1_smt 76 | uuid: bb9219b1-e51c-4680-abb0-616a43bbfbb1 77 | description: 'To implement cryptographic mechanisms (aka enable TLS 1.x) to {{ insert: param, sc-8.1_prm_1 }}, customers need to set the `PEMKeyFile` option in the configuration file `/etc/mongod.conf` to the certificate file''s path and restart the component.' 78 | responsible-roles: 79 | - role-id: customer 80 | - uuid: 5227daf8-7a4b-4fe0-aea9-3547b7de2603 81 | control-id: sa-4.9 82 | description: Must ensure that MongoDB only listens for network connections on authorized interfaces by configuring the MongoDB configuration file to limit the services exposure to only the network interfaces on which MongoDB instances should listen for incoming connections. 83 | back-matter: 84 | resources: 85 | - uuid: ba047e56-faef-430c-bafb-c54e9a87c6e8 86 | description: 'NIST Special Publication 800-53 Revision 5: Moderate Baseline Profile' 87 | rlinks: 88 | - href: ../../../nist.gov/SP800-53/rev5/xml/NIST_SP-800-53_rev5_MODERATE-baseline_profile.xml 89 | media-type: application/oscal.catalog+xml 90 | - href: ../../../nist.gov/SP800-53/rev5/json/NIST_SP-800-53_rev5_MODERATE-baseline_profile.json 91 | media-type: application/oscal.catalog+json 92 | - href: ../../../nist.gov/SP800-53/rev5/yaml/NIST_SP-800-53_rev5_MODERATE-baseline_profile.yaml 93 | media-type: application/oscal.catalog+yaml -------------------------------------------------------------------------------- /roscal_lib/tests/component-definition/yaml/example-component-definition.yaml: -------------------------------------------------------------------------------- 1 | component-definition: 2 | uuid: a7ba800c-a432-44cd-9075-0862cd66da6b 3 | metadata: 4 | title: MongoDB Component Definition Example 5 | last-modified: "2024-02-01T13:57:28.355446-04:00" 6 | version: "20231012" 7 | oscal-version: 1.1.2 8 | roles: 9 | - id: provider 10 | title: Provider 11 | parties: 12 | - uuid: ef7c799a-c50e-49ab-83e0-515e989e6df1 13 | type: organization 14 | name: MongoDB 15 | links: 16 | - href: https://www.mongodb.com 17 | rel: website 18 | components: 19 | - uuid: 91f646c5-b1b6-4786-9ec3-2305a044e217 20 | type: service 21 | title: MongoDB 22 | description: MongoDB is a source-available, cross-platform document-oriented database program. Classified as a NoSQL database program, MongoDB uses JSON-like documents with optional schemas. 23 | purpose: Provides a NoSQL database service 24 | responsible-roles: 25 | - role-id: provider 26 | party-uuids: 27 | - ef7c799a-c50e-49ab-83e0-515e989e6df1 28 | - role-id: customer 29 | protocols: 30 | - uuid: 2b4a1b3a-cbc5-4cc8-bde6-7437c28c4e54 31 | name: mongodb 32 | title: Primary daemon process for the MongoDB system. 33 | port-ranges: 34 | - start: 27017 35 | end: 27017 36 | transport: TCP 37 | - uuid: 99d8d4e5-e734-4e05-a2f9-7353097b8b61 38 | name: mongodb-shardsrv 39 | title: MongoDB protocol for sharding with shardsrv option. 40 | port-ranges: 41 | - start: 27018 42 | end: 27018 43 | transport: TCP 44 | - uuid: 6fa762f1-09ca-44d5-a94c-cfceb57debd5 45 | name: mongodb-configsvr 46 | title: MongoDB protocol for configsrv operation. 47 | port-ranges: 48 | - start: 27019 49 | end: 27019 50 | transport: TCP 51 | control-implementations: 52 | - uuid: 49f0b690-ed9f-4f32-aae0-625b77aa6d27 53 | source: '#ba047e56-faef-430c-bafb-c54e9a87c6e8' 54 | description: MongoDB control implementations for NIST SP 800-53 revision 5. 55 | implemented-requirements: 56 | - uuid: cf8338c5-fb6e-4593-a4a8-b3c4946ee080 57 | control-id: sc-8 58 | description: MongoDB's implementation of SC-8 control. The details of the implementation are provided at the statement level. 59 | set-parameters: 60 | - param-id: sc-8_prm_1 61 | values: 62 | - confidentiality 63 | statements: 64 | - statement-id: sc-8_smt 65 | uuid: bb9219b1-e51c-4680-abb0-616a43bbfbb1 66 | description: 'MongoDB implements TLS 1.x to protect the {{ insert: param, sc-8_prm_1 }} of transmitted data by encrypting data in transit, preventing unauthorized disclosure or changes to information during transmission.' 67 | - uuid: cf8338c5-fb6e-4593-a4a8-b3c4946ee081 68 | control-id: sc-8.1 69 | description: MongoDB implements cryptographic mechanisms (TLS 1.x) to provide cryptographic protection for data in transit. 70 | set-parameters: 71 | - param-id: sc-8.1_prm_1 72 | values: 73 | - prevent unauthorized disclosure of information 74 | statements: 75 | - statement-id: sc-8.1_smt 76 | uuid: bb9219b1-e51c-4680-abb0-616a43bbfbb1 77 | description: 'To implement cryptographic mechanisms (aka enable TLS 1.x) to {{ insert: param, sc-8.1_prm_1 }}, customers need to set the `PEMKeyFile` option in the configuration file `/etc/mongod.conf` to the certificate file''s path and restart the component.' 78 | responsible-roles: 79 | - role-id: customer 80 | - uuid: 5227daf8-7a4b-4fe0-aea9-3547b7de2603 81 | control-id: sa-4.9 82 | description: Must ensure that MongoDB only listens for network connections on authorized interfaces by configuring the MongoDB configuration file to limit the services exposure to only the network interfaces on which MongoDB instances should listen for incoming connections. 83 | back-matter: 84 | resources: 85 | - uuid: ba047e56-faef-430c-bafb-c54e9a87c6e8 86 | description: 'NIST Special Publication 800-53 Revision 5: Moderate Baseline Profile' 87 | rlinks: 88 | - href: ../../../nist.gov/SP800-53/rev5/xml/NIST_SP-800-53_rev5_MODERATE-baseline_profile.xml 89 | media-type: application/oscal.catalog+xml 90 | - href: ../../../nist.gov/SP800-53/rev5/json/NIST_SP-800-53_rev5_MODERATE-baseline_profile.json 91 | media-type: application/oscal.catalog+json 92 | - href: ../../../nist.gov/SP800-53/rev5/yaml/NIST_SP-800-53_rev5_MODERATE-baseline_profile.yaml 93 | media-type: application/oscal.catalog+yaml 94 | -------------------------------------------------------------------------------- /roscal_cli/tests/data/ap.yaml: -------------------------------------------------------------------------------- 1 | assessment-plan: 2 | uuid: 60077e84-e62f-4375-8c6c-b0e0d4560c5f 3 | metadata: 4 | title: IFA GoodRead Assessment Plan 5 | last-modified: "2024-02-01T13:57:28.355446-04:00" 6 | version: "1.0" 7 | oscal-version: 1.1.2 8 | roles: 9 | - id: assessor 10 | title: IFA Security Control Assessor 11 | parties: 12 | - uuid: e7730080-71ce-4b20-bec4-84f33136fd58 13 | type: person 14 | name: Amy Assessor 15 | member-of-organizations: 16 | - 3a675986-b4ff-4030-b178-e953c2e55d64 17 | - uuid: 3a675986-b4ff-4030-b178-e953c2e55d64 18 | type: organization 19 | name: Important Federal Agency 20 | short-name: IFA 21 | links: 22 | - href: https://www.ifa.gov 23 | rel: website 24 | responsible-parties: 25 | - role-id: assessor 26 | party-uuids: 27 | - e7730080-71ce-4b20-bec4-84f33136fd58 28 | import-ssp: 29 | href: ../3-implementation/ssp.oscal.xml 30 | local-definitions: 31 | activities: 32 | - uuid: 52277182-1ba3-4cb6-8d96-b1b97aaf9d6b 33 | title: Examine System Elements for Least Privilege Design and Implementation 34 | description: 'The activity and it steps will be performed by the assessor and facilitated by owner, ISSO, and product team for the IFA GoodRead system with necessary information and access about least privilege design and implementation of the system''s elements: the application, web framework, server, and cloud account infrastructure.' 35 | props: 36 | - name: method 37 | value: EXAMINE 38 | steps: 39 | - uuid: 733e3cbf-e398-46b6-9c02-a2cb534c341e 40 | title: Obtain Network Access via VPN to IFA GoodRead Environment 41 | description: The assessor will obtain network access with appropriately configured VPN account to see admin frontend to the application for PAO staff, which is only accessible via VPN with an appropriately configured role for PAO staff accounts. 42 | - uuid: 4ce7e0b4-d69e-4b80-a700-8600b4d4d933 43 | title: Obtain Credentials and Access to AwesomeCloud Account for IFA GoodRead System 44 | description: The assessor will obtain access to the GoodRead Product Team's AwesomeCloud account with their single sign-on credentials to a read-only assessor role. 45 | - uuid: 3d0297de-e47b-4360-b9c3-cf5c425f86cd 46 | title: Obtain Applcation Access Provided by Product Team 47 | description: The assessor will obtain non-privileged account credentials with the PAO staff role to test this role in the application does not permit excessive administrative operations. 48 | - uuid: 64ca1ef6-3ad4-4747-97c6-40890222463f 49 | title: Confirm Load Balancer Blocks Access to Admin Frontend from Internet 50 | description: The assessor will confirm that the load balancer for public access does not allow access to Admin Frontend of the application from the Internet. 51 | - uuid: 715f0592-166f-44f6-bb66-d99623e035dc 52 | title: Confirm GoodRead's PAO Role Cannot Manage Users 53 | description: The assessor will confirm that user's logged into the GoodRead Application with the PAO staff role cannot add, modify, or disable users from the system. 54 | - uuid: 4641957b-a0fa-4c61-af1a-d3e9101efe40 55 | title: Confirm Django Admin Panel Not Available 56 | description: The assessor will confirm with web-based interface and API methods users with the PAO Staff role cannot access the Django admin panel functions and interactively change application's database records. 57 | related-controls: 58 | control-selections: 59 | - include-controls: 60 | - control-id: ac-6.1 61 | responsible-roles: 62 | - role-id: assessor 63 | party-uuids: 64 | - e7730080-71ce-4b20-bec4-84f33136fd58 65 | reviewed-controls: 66 | control-selections: 67 | - include-controls: 68 | - control-id: ac-6.1 69 | control-objective-selections: 70 | - include-all: {} 71 | assessment-subjects: 72 | - type: component 73 | description: The assessor for the IFA GoodRead Project, including the application and infrastructure for this information system, are within scope of this assessment. 74 | include-all: {} 75 | tasks: 76 | - uuid: b3504d22-0e75-4dd7-9247-618661beba4e 77 | type: action 78 | title: Examine Least Privilege Design and Implementation 79 | associated-activities: 80 | - activity-uuid: 0d243b23-a889-478f-9716-6d4870e56209 81 | subjects: 82 | - type: component 83 | include-all: {} 84 | responsible-roles: 85 | - role-id: assessor 86 | remarks: | 87 | Per IFA's use of NIST SP-800 53A, the assessor, with the support of the owner, information system security officer, and product team for the IFA GoodRead project, will examine least privilege design and implementation with the following: 88 | 89 | * list of security functions (deployed in hardware, software, and firmware) and security-relevant information for which access must be explicitly authorized; 90 | * system configuration settings and associated documentation; -------------------------------------------------------------------------------- /roscal_lib/tests/ap/yaml/ifa_assessment-plan-example.yaml: -------------------------------------------------------------------------------- 1 | assessment-plan: 2 | uuid: 60077e84-e62f-4375-8c6c-b0e0d4560c5f 3 | metadata: 4 | title: IFA GoodRead Assessment Plan 5 | last-modified: "2024-02-01T13:57:28.355446-04:00" 6 | version: "1.0" 7 | oscal-version: 1.1.2 8 | roles: 9 | - id: assessor 10 | title: IFA Security Control Assessor 11 | parties: 12 | - uuid: e7730080-71ce-4b20-bec4-84f33136fd58 13 | type: person 14 | name: Amy Assessor 15 | member-of-organizations: 16 | - 3a675986-b4ff-4030-b178-e953c2e55d64 17 | - uuid: 3a675986-b4ff-4030-b178-e953c2e55d64 18 | type: organization 19 | name: Important Federal Agency 20 | short-name: IFA 21 | links: 22 | - href: https://www.ifa.gov 23 | rel: website 24 | responsible-parties: 25 | - role-id: assessor 26 | party-uuids: 27 | - e7730080-71ce-4b20-bec4-84f33136fd58 28 | import-ssp: 29 | href: ../3-implementation/ssp.oscal.xml 30 | local-definitions: 31 | activities: 32 | - uuid: 52277182-1ba3-4cb6-8d96-b1b97aaf9d6b 33 | title: Examine System Elements for Least Privilege Design and Implementation 34 | description: 'The activity and it steps will be performed by the assessor and facilitated by owner, ISSO, and product team for the IFA GoodRead system with necessary information and access about least privilege design and implementation of the system''s elements: the application, web framework, server, and cloud account infrastructure.' 35 | props: 36 | - name: method 37 | value: EXAMINE 38 | steps: 39 | - uuid: 733e3cbf-e398-46b6-9c02-a2cb534c341e 40 | title: Obtain Network Access via VPN to IFA GoodRead Environment 41 | description: The assessor will obtain network access with appropriately configured VPN account to see admin frontend to the application for PAO staff, which is only accessible via VPN with an appropriately configured role for PAO staff accounts. 42 | - uuid: 4ce7e0b4-d69e-4b80-a700-8600b4d4d933 43 | title: Obtain Credentials and Access to AwesomeCloud Account for IFA GoodRead System 44 | description: The assessor will obtain access to the GoodRead Product Team's AwesomeCloud account with their single sign-on credentials to a read-only assessor role. 45 | - uuid: 3d0297de-e47b-4360-b9c3-cf5c425f86cd 46 | title: Obtain Applcation Access Provided by Product Team 47 | description: The assessor will obtain non-privileged account credentials with the PAO staff role to test this role in the application does not permit excessive administrative operations. 48 | - uuid: 64ca1ef6-3ad4-4747-97c6-40890222463f 49 | title: Confirm Load Balancer Blocks Access to Admin Frontend from Internet 50 | description: The assessor will confirm that the load balancer for public access does not allow access to Admin Frontend of the application from the Internet. 51 | - uuid: 715f0592-166f-44f6-bb66-d99623e035dc 52 | title: Confirm GoodRead's PAO Role Cannot Manage Users 53 | description: The assessor will confirm that user's logged into the GoodRead Application with the PAO staff role cannot add, modify, or disable users from the system. 54 | - uuid: 4641957b-a0fa-4c61-af1a-d3e9101efe40 55 | title: Confirm Django Admin Panel Not Available 56 | description: The assessor will confirm with web-based interface and API methods users with the PAO Staff role cannot access the Django admin panel functions and interactively change application's database records. 57 | related-controls: 58 | control-selections: 59 | - include-controls: 60 | - control-id: ac-6.1 61 | responsible-roles: 62 | - role-id: assessor 63 | party-uuids: 64 | - e7730080-71ce-4b20-bec4-84f33136fd58 65 | reviewed-controls: 66 | control-selections: 67 | - include-controls: 68 | - control-id: ac-6.1 69 | control-objective-selections: 70 | - include-all: {} 71 | assessment-subjects: 72 | - type: component 73 | description: The assessor for the IFA GoodRead Project, including the application and infrastructure for this information system, are within scope of this assessment. 74 | include-all: {} 75 | tasks: 76 | - uuid: b3504d22-0e75-4dd7-9247-618661beba4e 77 | type: action 78 | title: Examine Least Privilege Design and Implementation 79 | associated-activities: 80 | - activity-uuid: 0d243b23-a889-478f-9716-6d4870e56209 81 | subjects: 82 | - type: component 83 | include-all: {} 84 | responsible-roles: 85 | - role-id: assessor 86 | remarks: | 87 | Per IFA's use of NIST SP-800 53A, the assessor, with the support of the owner, information system security officer, and product team for the IFA GoodRead project, will examine least privilege design and implementation with the following: 88 | 89 | * list of security functions (deployed in hardware, software, and firmware) and security-relevant information for which access must be explicitly authorized; 90 | * system configuration settings and associated documentation; 91 | -------------------------------------------------------------------------------- /roscal_cli/tests/dissect.rs: -------------------------------------------------------------------------------- 1 | use assert_cmd::Command; 2 | use tempfile::tempdir; 3 | 4 | #[test] 5 | fn cli_dissect_single_block() { 6 | let dir = tempdir().unwrap(); 7 | let dir_arg = dir.as_ref().to_str().unwrap(); 8 | let mut cmd = Command::cargo_bin("roscal").unwrap(); 9 | let assert = cmd 10 | .args(&[ 11 | "dissect", 12 | "--file", 13 | "tests/data/catalog.yaml", 14 | "--model", 15 | "Catalog", 16 | "--blocks", 17 | "uuid", 18 | "--output-dir", 19 | dir_arg, 20 | ]) 21 | .assert(); 22 | assert.success(); 23 | dir.close().unwrap() 24 | } 25 | 26 | #[test] 27 | fn cli_dissect_all_block() { 28 | let dir = tempdir().unwrap(); 29 | let dir_arg = dir.as_ref().to_str().unwrap(); 30 | let mut cmd = Command::cargo_bin("roscal").unwrap(); 31 | let assert = cmd 32 | .args(&[ 33 | "dissect", 34 | "--file", 35 | "tests/data/catalog.yaml", 36 | "--model", 37 | "Catalog", 38 | "--blocks", 39 | "all", 40 | "--output-dir", 41 | dir_arg, 42 | ]) 43 | .assert(); 44 | assert.success(); 45 | dir.close().unwrap() 46 | } 47 | 48 | #[test] 49 | fn cli_dissect_multiple_blocks() { 50 | let dir = tempdir().unwrap(); 51 | let dir_arg = dir.as_ref().to_str().unwrap(); 52 | let mut cmd = Command::cargo_bin("roscal").unwrap(); 53 | let assert = cmd 54 | .args(&[ 55 | "dissect", 56 | "--file", 57 | "tests/data/catalog.yaml", 58 | "--model", 59 | "Catalog", 60 | "--blocks", 61 | "uuid,metadata", 62 | "--output-dir", 63 | dir_arg, 64 | ]) 65 | .assert(); 66 | assert.success(); 67 | dir.close().unwrap() 68 | } 69 | 70 | #[test] 71 | fn cli_dissect_multiple_dup_blocks() { 72 | let dir = tempdir().unwrap(); 73 | let dir_arg = dir.as_ref().to_str().unwrap(); 74 | let mut cmd = Command::cargo_bin("roscal").unwrap(); 75 | let assert = cmd 76 | .args(&[ 77 | "dissect", 78 | "--file", 79 | "tests/data/catalog.yaml", 80 | "--model", 81 | "Catalog", 82 | "--blocks", 83 | "uuid,uuid", 84 | "--output-dir", 85 | dir_arg, 86 | ]) 87 | .assert(); 88 | assert.success(); 89 | dir.close().unwrap() 90 | } 91 | 92 | #[test] 93 | fn cli_dissect_malformed() { 94 | let dir = tempdir().unwrap(); 95 | let dir_arg = dir.as_ref().to_str().unwrap(); 96 | let mut cmd = Command::cargo_bin("roscal").unwrap(); 97 | let assert = cmd 98 | .args(&[ 99 | "dissect", 100 | "--file", 101 | "tests/data/malformed", 102 | "--model", 103 | "Catalog", 104 | "--blocks", 105 | "all", 106 | "--output-dir", 107 | dir_arg, 108 | ]) 109 | .assert(); 110 | assert.failure(); 111 | dir.close().unwrap() 112 | } 113 | 114 | #[test] 115 | fn cli_wrong_file_loc() { 116 | let dir = tempdir().unwrap(); 117 | let dir_arg = dir.as_ref().to_str().unwrap(); 118 | let mut cmd = Command::cargo_bin("roscal").unwrap(); 119 | let assert = cmd 120 | .args(&[ 121 | "dissect", 122 | "--file", 123 | "tests/data/not", 124 | "--model", 125 | "catalog", 126 | "--blocks", 127 | "all", 128 | "--output-dir", 129 | dir_arg, 130 | ]) 131 | .assert(); 132 | assert.stderr("Error: Could not determine the full path of the OSCAL model file: `tests/data/not`\n\nCaused by:\n No such file or directory (os error 2)\n"); 133 | dir.close().unwrap() 134 | } 135 | 136 | #[test] 137 | fn cli_wrong_dissect_model() { 138 | let dir = tempdir().unwrap(); 139 | let dir_arg = dir.as_ref().to_str().unwrap(); 140 | let mut cmd = Command::cargo_bin("roscal").unwrap(); 141 | let assert = cmd 142 | .args(&[ 143 | "dissect", 144 | "--file", 145 | "tests/data/catalog.yaml", 146 | "--model", 147 | "invalid", 148 | "--blocks", 149 | "all", 150 | "--output-dir", 151 | dir_arg, 152 | ]) 153 | .assert(); 154 | assert.stderr("Invalid model provided: invalid\n"); 155 | dir.close().unwrap() 156 | } 157 | 158 | #[test] 159 | fn cli_wrong_dissect_block() { 160 | let dir = tempdir().unwrap(); 161 | let dir_arg = dir.as_ref().to_str().unwrap(); 162 | let mut cmd = Command::cargo_bin("roscal").unwrap(); 163 | let assert = cmd 164 | .args(&[ 165 | "dissect", 166 | "--file", 167 | "tests/data/catalog.yaml", 168 | "--model", 169 | "Catalog", 170 | "--blocks", 171 | "uuid,not", 172 | "--output-dir", 173 | dir_arg, 174 | ]) 175 | .assert(); 176 | assert.stderr("Invalid catalog block provided: [\"uuid\", \"not\"]\n"); 177 | dir.close().unwrap() 178 | } 179 | 180 | #[test] 181 | fn cli_wrong_dissect_block_multiple_with_all() { 182 | let dir = tempdir().unwrap(); 183 | let dir_arg = dir.as_ref().to_str().unwrap(); 184 | let mut cmd = Command::cargo_bin("roscal").unwrap(); 185 | let assert = cmd 186 | .args(&[ 187 | "dissect", 188 | "--file", 189 | "tests/data/catalog.yaml", 190 | "--model", 191 | "Catalog", 192 | "--blocks", 193 | "all,uuid", 194 | "--output-dir", 195 | dir_arg, 196 | ]) 197 | .assert(); 198 | assert.stderr("Multiple block cannot include `all` option\n"); 199 | dir.close().unwrap() 200 | } 201 | -------------------------------------------------------------------------------- /roscal_lib/tests/ap/json/ifa_assessment-plan-example-min.json: -------------------------------------------------------------------------------- 1 | { 2 | "assessment-plan": { 3 | "uuid": "60077e84-e62f-4375-8c6c-b0e0d4560c5f", 4 | "metadata": { 5 | "title": "IFA GoodRead Assessment Plan", 6 | "last-modified": "2024-02-01T13:57:28.355446-04:00", 7 | "version": "1.0", 8 | "oscal-version": "1.1.2", 9 | "roles": [{ "id": "assessor", "title": "IFA Security Control Assessor" }], 10 | "parties": [ 11 | { 12 | "uuid": "e7730080-71ce-4b20-bec4-84f33136fd58", 13 | "type": "person", 14 | "name": "Amy Assessor", 15 | "member-of-organizations": ["3a675986-b4ff-4030-b178-e953c2e55d64"] 16 | }, 17 | { 18 | "uuid": "3a675986-b4ff-4030-b178-e953c2e55d64", 19 | "type": "organization", 20 | "name": "Important Federal Agency", 21 | "short-name": "IFA", 22 | "links": [{ "href": "https://www.ifa.gov", "rel": "website" }] 23 | } 24 | ], 25 | "responsible-parties": [ 26 | { 27 | "role-id": "assessor", 28 | "party-uuids": ["e7730080-71ce-4b20-bec4-84f33136fd58"] 29 | } 30 | ] 31 | }, 32 | "import-ssp": { "href": "../3-implementation/ssp.oscal.xml" }, 33 | "local-definitions": { 34 | "activities": [ 35 | { 36 | "uuid": "52277182-1ba3-4cb6-8d96-b1b97aaf9d6b", 37 | "title": "Examine System Elements for Least Privilege Design and Implementation", 38 | "description": "The activity and it steps will be performed by the assessor and facilitated by owner, ISSO, and product team for the IFA GoodRead system with necessary information and access about least privilege design and implementation of the system's elements: the application, web framework, server, and cloud account infrastructure.", 39 | "props": [{ "name": "method", "value": "EXAMINE" }], 40 | "steps": [ 41 | { 42 | "uuid": "733e3cbf-e398-46b6-9c02-a2cb534c341e", 43 | "title": "Obtain Network Access via VPN to IFA GoodRead Environment", 44 | "description": "The assessor will obtain network access with appropriately configured VPN account to see admin frontend to the application for PAO staff, which is only accessible via VPN with an appropriately configured role for PAO staff accounts." 45 | }, 46 | { 47 | "uuid": "4ce7e0b4-d69e-4b80-a700-8600b4d4d933", 48 | "title": "Obtain Credentials and Access to AwesomeCloud Account for IFA GoodRead System", 49 | "description": "The assessor will obtain access to the GoodRead Product Team's AwesomeCloud account with their single sign-on credentials to a read-only assessor role." 50 | }, 51 | { 52 | "uuid": "3d0297de-e47b-4360-b9c3-cf5c425f86cd", 53 | "title": "Obtain Applcation Access Provided by Product Team", 54 | "description": "The assessor will obtain non-privileged account credentials with the PAO staff role to test this role in the application does not permit excessive administrative operations." 55 | }, 56 | { 57 | "uuid": "64ca1ef6-3ad4-4747-97c6-40890222463f", 58 | "title": "Confirm Load Balancer Blocks Access to Admin Frontend from Internet", 59 | "description": "The assessor will confirm that the load balancer for public access does not allow access to Admin Frontend of the application from the Internet." 60 | }, 61 | { 62 | "uuid": "715f0592-166f-44f6-bb66-d99623e035dc", 63 | "title": "Confirm GoodRead's PAO Role Cannot Manage Users", 64 | "description": "The assessor will confirm that user's logged into the GoodRead Application with the PAO staff role cannot add, modify, or disable users from the system." 65 | }, 66 | { 67 | "uuid": "4641957b-a0fa-4c61-af1a-d3e9101efe40", 68 | "title": "Confirm Django Admin Panel Not Available", 69 | "description": "The assessor will confirm with web-based interface and API methods users with the PAO Staff role cannot access the Django admin panel functions and interactively change application's database records." 70 | } 71 | ], 72 | "related-controls": { 73 | "control-selections": [ 74 | { "include-controls": [{ "control-id": "ac-6.1" }] } 75 | ] 76 | }, 77 | "responsible-roles": [ 78 | { 79 | "role-id": "assessor", 80 | "party-uuids": ["e7730080-71ce-4b20-bec4-84f33136fd58"] 81 | } 82 | ] 83 | } 84 | ] 85 | }, 86 | "reviewed-controls": { 87 | "control-selections": [ 88 | { "include-controls": [{ "control-id": "ac-6.1" }] } 89 | ], 90 | "control-objective-selections": [{ "include-all": {} }] 91 | }, 92 | "assessment-subjects": [ 93 | { 94 | "type": "component", 95 | "description": "The assessor for the IFA GoodRead Project, including the application and infrastructure for this information system, are within scope of this assessment.", 96 | "include-all": {} 97 | } 98 | ], 99 | "tasks": [ 100 | { 101 | "uuid": "b3504d22-0e75-4dd7-9247-618661beba4e", 102 | "type": "action", 103 | "title": "Examine Least Privilege Design and Implementation", 104 | "associated-activities": [ 105 | { 106 | "activity-uuid": "0d243b23-a889-478f-9716-6d4870e56209", 107 | "subjects": [{ "type": "component", "include-all": {} }] 108 | } 109 | ], 110 | "responsible-roles": [{ "role-id": "assessor" }], 111 | "remarks": "Per IFA's use of NIST SP-800 53A, the assessor, with the support of the owner, information system security officer, and product team for the IFA GoodRead project, will examine least privilege design and implementation with the following:\n\n* list of security functions (deployed in hardware, software, and firmware) and security-relevant information for which access must be explicitly authorized;\n* system configuration settings and associated documentation;\n" 112 | } 113 | ] 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /roscal_lib/tests/component-definition/json/example-component-definition-min.json: -------------------------------------------------------------------------------- 1 | { 2 | "component-definition": { 3 | "uuid": "a7ba800c-a432-44cd-9075-0862cd66da6b", 4 | "metadata": { 5 | "title": "MongoDB Component Definition Example", 6 | "last-modified": "2024-02-01T13:57:28.355446-04:00", 7 | "version": "20231012", 8 | "oscal-version": "1.1.2", 9 | "roles": [{ "id": "provider", "title": "Provider" }], 10 | "parties": [ 11 | { 12 | "uuid": "ef7c799a-c50e-49ab-83e0-515e989e6df1", 13 | "type": "organization", 14 | "name": "MongoDB", 15 | "links": [{ "href": "https://www.mongodb.com", "rel": "website" }] 16 | } 17 | ] 18 | }, 19 | "components": [ 20 | { 21 | "uuid": "91f646c5-b1b6-4786-9ec3-2305a044e217", 22 | "type": "service", 23 | "title": "MongoDB", 24 | "description": "MongoDB is a source-available, cross-platform document-oriented database program. Classified as a NoSQL database program, MongoDB uses JSON-like documents with optional schemas.", 25 | "purpose": "Provides a NoSQL database service", 26 | "responsible-roles": [ 27 | { 28 | "role-id": "provider", 29 | "party-uuids": ["ef7c799a-c50e-49ab-83e0-515e989e6df1"] 30 | }, 31 | { "role-id": "customer" } 32 | ], 33 | "protocols": [ 34 | { 35 | "uuid": "2b4a1b3a-cbc5-4cc8-bde6-7437c28c4e54", 36 | "name": "mongodb", 37 | "title": "Primary daemon process for the MongoDB system.", 38 | "port-ranges": [ 39 | { "start": 27017, "end": 27017, "transport": "TCP" } 40 | ] 41 | }, 42 | { 43 | "uuid": "99d8d4e5-e734-4e05-a2f9-7353097b8b61", 44 | "name": "mongodb-shardsrv", 45 | "title": "MongoDB protocol for sharding with shardsrv option.", 46 | "port-ranges": [ 47 | { "start": 27018, "end": 27018, "transport": "TCP" } 48 | ] 49 | }, 50 | { 51 | "uuid": "6fa762f1-09ca-44d5-a94c-cfceb57debd5", 52 | "name": "mongodb-configsvr", 53 | "title": "MongoDB protocol for configsrv operation.", 54 | "port-ranges": [ 55 | { "start": 27019, "end": 27019, "transport": "TCP" } 56 | ] 57 | } 58 | ], 59 | "control-implementations": [ 60 | { 61 | "uuid": "49f0b690-ed9f-4f32-aae0-625b77aa6d27", 62 | "source": "#ba047e56-faef-430c-bafb-c54e9a87c6e8", 63 | "description": "MongoDB control implementations for NIST SP 800-53 revision 5.", 64 | "implemented-requirements": [ 65 | { 66 | "uuid": "cf8338c5-fb6e-4593-a4a8-b3c4946ee080", 67 | "control-id": "sc-8", 68 | "description": "MongoDB's implementation of SC-8 control. The details of the implementation are provided at the statement level.", 69 | "set-parameters": [ 70 | { "param-id": "sc-8_prm_1", "values": ["confidentiality"] } 71 | ], 72 | "statements": [ 73 | { 74 | "statement-id": "sc-8_smt", 75 | "uuid": "bb9219b1-e51c-4680-abb0-616a43bbfbb1", 76 | "description": "MongoDB implements TLS 1.x to protect the {{ insert: param, sc-8_prm_1 }} of transmitted data by encrypting data in transit, preventing unauthorized disclosure or changes to information during transmission." 77 | } 78 | ] 79 | }, 80 | { 81 | "uuid": "cf8338c5-fb6e-4593-a4a8-b3c4946ee081", 82 | "control-id": "sc-8.1", 83 | "description": "MongoDB implements cryptographic mechanisms (TLS 1.x) to provide cryptographic protection for data in transit.", 84 | "set-parameters": [ 85 | { 86 | "param-id": "sc-8.1_prm_1", 87 | "values": ["prevent unauthorized disclosure of information"] 88 | } 89 | ], 90 | "statements": [ 91 | { 92 | "statement-id": "sc-8.1_smt", 93 | "uuid": "bb9219b1-e51c-4680-abb0-616a43bbfbb1", 94 | "description": "To implement cryptographic mechanisms (aka enable TLS 1.x) to {{ insert: param, sc-8.1_prm_1 }}, customers need to set the `PEMKeyFile` option in the configuration file `/etc/mongod.conf` to the certificate file's path and restart the component.", 95 | "responsible-roles": [{ "role-id": "customer" }] 96 | } 97 | ] 98 | }, 99 | { 100 | "uuid": "5227daf8-7a4b-4fe0-aea9-3547b7de2603", 101 | "control-id": "sa-4.9", 102 | "description": "Must ensure that MongoDB only listens for network connections on authorized interfaces by configuring the MongoDB configuration file to limit the services exposure to only the network interfaces on which MongoDB instances should listen for incoming connections." 103 | } 104 | ] 105 | } 106 | ] 107 | } 108 | ], 109 | "back-matter": { 110 | "resources": [ 111 | { 112 | "uuid": "ba047e56-faef-430c-bafb-c54e9a87c6e8", 113 | "description": "NIST Special Publication 800-53 Revision 5: Moderate Baseline Profile", 114 | "rlinks": [ 115 | { 116 | "href": "../../../nist.gov/SP800-53/rev5/xml/NIST_SP-800-53_rev5_MODERATE-baseline_profile.xml", 117 | "media-type": "application/oscal.catalog+xml" 118 | }, 119 | { 120 | "href": "../../../nist.gov/SP800-53/rev5/json/NIST_SP-800-53_rev5_MODERATE-baseline_profile.json", 121 | "media-type": "application/oscal.catalog+json" 122 | }, 123 | { 124 | "href": "../../../nist.gov/SP800-53/rev5/yaml/NIST_SP-800-53_rev5_MODERATE-baseline_profile.yaml", 125 | "media-type": "application/oscal.catalog+yaml" 126 | } 127 | ] 128 | } 129 | ] 130 | } 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /roscal_lib/tests/parse_test.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | fs::{read_dir, File}, 3 | io::BufReader, 4 | }; 5 | 6 | use roscal_lib::{ 7 | assessment::{ 8 | assessment_plan::AssessmentPlan, assessment_results::AssessmentResults, 9 | poam::PlanOfActionAndMilestones, 10 | }, 11 | control::{catalog::Catalog, profile::Profile}, 12 | implementation::{ 13 | component_definition::ComponentDefinition, ssp::SystemSecurityPlan, 14 | }, 15 | }; 16 | 17 | #[test] 18 | fn parse_json_ap() { 19 | for e in read_dir("tests/ap/json").unwrap() { 20 | let entry = e.unwrap(); 21 | let path = entry.path(); 22 | let file = File::open(path).unwrap(); 23 | let reader = BufReader::new(file); 24 | let res: Result = 25 | serde_json::from_reader(reader); 26 | assert_eq!(true, res.is_ok()) 27 | } 28 | } 29 | 30 | #[test] 31 | fn parse_yaml_ap() { 32 | for e in read_dir("tests/ap/yaml").unwrap() { 33 | let entry = e.unwrap(); 34 | let path = entry.path(); 35 | let file = File::open(path).unwrap(); 36 | let reader = BufReader::new(file); 37 | let res: Result = 38 | serde_yaml::from_reader(reader); 39 | assert_eq!(true, res.is_ok()) 40 | } 41 | } 42 | 43 | #[test] 44 | fn parse_json_ar() { 45 | for e in read_dir("tests/ar/json").unwrap() { 46 | let entry = e.unwrap(); 47 | let path = entry.path(); 48 | let file = File::open(path).unwrap(); 49 | let reader = BufReader::new(file); 50 | let res: Result = 51 | serde_json::from_reader(reader); 52 | assert_eq!(true, res.is_ok()) 53 | } 54 | } 55 | 56 | #[test] 57 | fn parse_yaml_ar() { 58 | for e in read_dir("tests/ar/yaml").unwrap() { 59 | let entry = e.unwrap(); 60 | let path = entry.path(); 61 | let file = File::open(path).unwrap(); 62 | let reader = BufReader::new(file); 63 | let res: Result = 64 | serde_yaml::from_reader(reader); 65 | assert_eq!(true, res.is_ok()) 66 | } 67 | } 68 | 69 | #[test] 70 | fn parse_json_catalog() { 71 | for e in read_dir("tests/catalog/json").unwrap() { 72 | let entry = e.unwrap(); 73 | let path = entry.path(); 74 | let file = File::open(path).unwrap(); 75 | let reader = BufReader::new(file); 76 | let res: Result = 77 | serde_json::from_reader(reader); 78 | assert_eq!(true, res.is_ok()) 79 | } 80 | } 81 | 82 | #[test] 83 | fn parse_yaml_catalog() { 84 | for e in read_dir("tests/catalog/yaml").unwrap() { 85 | let entry = e.unwrap(); 86 | let path = entry.path(); 87 | let file = File::open(path).unwrap(); 88 | let reader = BufReader::new(file); 89 | let res: Result = 90 | serde_yaml::from_reader(reader); 91 | assert_eq!(true, res.is_ok()) 92 | } 93 | } 94 | 95 | #[test] 96 | fn parse_json_component_def() { 97 | for e in read_dir("tests/component-definition/json").unwrap() { 98 | let entry = e.unwrap(); 99 | let path = entry.path(); 100 | let file = File::open(path).unwrap(); 101 | let reader = BufReader::new(file); 102 | let res: Result = 103 | serde_json::from_reader(reader); 104 | assert_eq!(true, res.is_ok()) 105 | } 106 | } 107 | 108 | #[test] 109 | fn parse_yaml_component_def() { 110 | for e in read_dir("tests/component-definition/yaml").unwrap() { 111 | let entry = e.unwrap(); 112 | let path = entry.path(); 113 | let file = File::open(path).unwrap(); 114 | let reader = BufReader::new(file); 115 | let res: Result = 116 | serde_yaml::from_reader(reader); 117 | assert_eq!(true, res.is_ok()) 118 | } 119 | } 120 | 121 | #[test] 122 | fn parse_json_poam() { 123 | for e in read_dir("tests/poam/json").unwrap() { 124 | let entry = e.unwrap(); 125 | let path = entry.path(); 126 | let file = File::open(path).unwrap(); 127 | let reader = BufReader::new(file); 128 | let res: Result = 129 | serde_json::from_reader(reader); 130 | assert_eq!(true, res.is_ok()) 131 | } 132 | } 133 | 134 | #[test] 135 | fn parse_yaml_poam() { 136 | for e in read_dir("tests/poam/yaml").unwrap() { 137 | let entry = e.unwrap(); 138 | let path = entry.path(); 139 | let file = File::open(path).unwrap(); 140 | let reader = BufReader::new(file); 141 | let res: Result = 142 | serde_yaml::from_reader(reader); 143 | assert_eq!(true, res.is_ok()) 144 | } 145 | } 146 | 147 | #[test] 148 | fn parse_json_profile() { 149 | for e in read_dir("tests/profile/json").unwrap() { 150 | let entry = e.unwrap(); 151 | let path = entry.path(); 152 | let file = File::open(path).unwrap(); 153 | let reader = BufReader::new(file); 154 | let res: Result = 155 | serde_json::from_reader(reader); 156 | assert_eq!(true, res.is_ok()) 157 | } 158 | } 159 | 160 | #[test] 161 | fn parse_yaml_profile() { 162 | for e in read_dir("tests/profile/yaml").unwrap() { 163 | let entry = e.unwrap(); 164 | let path = entry.path(); 165 | let file = File::open(path).unwrap(); 166 | let reader = BufReader::new(file); 167 | let res: Result = 168 | serde_yaml::from_reader(reader); 169 | assert_eq!(true, res.is_ok()) 170 | } 171 | } 172 | 173 | #[test] 174 | fn parse_json_ssp() { 175 | for e in read_dir("tests/ssp/json").unwrap() { 176 | let entry = e.unwrap(); 177 | let path = entry.path(); 178 | let file = File::open(path).unwrap(); 179 | let reader = BufReader::new(file); 180 | let res: Result = 181 | serde_json::from_reader(reader); 182 | assert_eq!(true, res.is_ok()) 183 | } 184 | } 185 | 186 | #[test] 187 | fn parse_yaml_ssp() { 188 | for e in read_dir("tests/ssp/yaml").unwrap() { 189 | let entry = e.unwrap(); 190 | let path = entry.path(); 191 | let file = File::open(path.clone()).unwrap(); 192 | let reader = BufReader::new(file); 193 | let res: Result = 194 | serde_yaml::from_reader(reader); 195 | let a = res.map_err(|e| eprintln!("{}:::{}", e, path.display())); 196 | assert_eq!(true, a.is_ok()) 197 | } 198 | } 199 | -------------------------------------------------------------------------------- /roscal_lib/tests/component-definition/json/example-component-definition.json: -------------------------------------------------------------------------------- 1 | { 2 | "component-definition": { 3 | "uuid": "a7ba800c-a432-44cd-9075-0862cd66da6b", 4 | "metadata": { 5 | "title": "MongoDB Component Definition Example", 6 | "last-modified": "2024-02-01T13:57:28.355446-04:00", 7 | "version": "20231012", 8 | "oscal-version": "1.1.2", 9 | "roles": [ 10 | { 11 | "id": "provider", 12 | "title": "Provider" 13 | } 14 | ], 15 | "parties": [ 16 | { 17 | "uuid": "ef7c799a-c50e-49ab-83e0-515e989e6df1", 18 | "type": "organization", 19 | "name": "MongoDB", 20 | "links": [ 21 | { 22 | "href": "https://www.mongodb.com", 23 | "rel": "website" 24 | } 25 | ] 26 | } 27 | ] 28 | }, 29 | "components": [ 30 | { 31 | "uuid": "91f646c5-b1b6-4786-9ec3-2305a044e217", 32 | "type": "service", 33 | "title": "MongoDB", 34 | "description": "MongoDB is a source-available, cross-platform document-oriented database program. Classified as a NoSQL database program, MongoDB uses JSON-like documents with optional schemas.", 35 | "purpose": "Provides a NoSQL database service", 36 | "responsible-roles": [ 37 | { 38 | "role-id": "provider", 39 | "party-uuids": ["ef7c799a-c50e-49ab-83e0-515e989e6df1"] 40 | }, 41 | { 42 | "role-id": "customer" 43 | } 44 | ], 45 | "protocols": [ 46 | { 47 | "uuid": "2b4a1b3a-cbc5-4cc8-bde6-7437c28c4e54", 48 | "name": "mongodb", 49 | "title": "Primary daemon process for the MongoDB system.", 50 | "port-ranges": [ 51 | { 52 | "start": 27017, 53 | "end": 27017, 54 | "transport": "TCP" 55 | } 56 | ] 57 | }, 58 | { 59 | "uuid": "99d8d4e5-e734-4e05-a2f9-7353097b8b61", 60 | "name": "mongodb-shardsrv", 61 | "title": "MongoDB protocol for sharding with shardsrv option.", 62 | "port-ranges": [ 63 | { 64 | "start": 27018, 65 | "end": 27018, 66 | "transport": "TCP" 67 | } 68 | ] 69 | }, 70 | { 71 | "uuid": "6fa762f1-09ca-44d5-a94c-cfceb57debd5", 72 | "name": "mongodb-configsvr", 73 | "title": "MongoDB protocol for configsrv operation.", 74 | "port-ranges": [ 75 | { 76 | "start": 27019, 77 | "end": 27019, 78 | "transport": "TCP" 79 | } 80 | ] 81 | } 82 | ], 83 | "control-implementations": [ 84 | { 85 | "uuid": "49f0b690-ed9f-4f32-aae0-625b77aa6d27", 86 | "source": "#ba047e56-faef-430c-bafb-c54e9a87c6e8", 87 | "description": "MongoDB control implementations for NIST SP 800-53 revision 5.", 88 | "implemented-requirements": [ 89 | { 90 | "uuid": "cf8338c5-fb6e-4593-a4a8-b3c4946ee080", 91 | "control-id": "sc-8", 92 | "description": "MongoDB's implementation of SC-8 control. The details of the implementation are provided at the statement level.", 93 | "set-parameters": [ 94 | { 95 | "param-id": "sc-8_prm_1", 96 | "values": ["confidentiality"] 97 | } 98 | ], 99 | "statements": [ 100 | { 101 | "statement-id": "sc-8_smt", 102 | "uuid": "bb9219b1-e51c-4680-abb0-616a43bbfbb1", 103 | "description": "MongoDB implements TLS 1.x to protect the {{ insert: param, sc-8_prm_1 }} of transmitted data by encrypting data in transit, preventing unauthorized disclosure or changes to information during transmission." 104 | } 105 | ] 106 | }, 107 | { 108 | "uuid": "cf8338c5-fb6e-4593-a4a8-b3c4946ee081", 109 | "control-id": "sc-8.1", 110 | "description": "MongoDB implements cryptographic mechanisms (TLS 1.x) to provide cryptographic protection for data in transit.", 111 | "set-parameters": [ 112 | { 113 | "param-id": "sc-8.1_prm_1", 114 | "values": ["prevent unauthorized disclosure of information"] 115 | } 116 | ], 117 | "statements": [ 118 | { 119 | "statement-id": "sc-8.1_smt", 120 | "uuid": "bb9219b1-e51c-4680-abb0-616a43bbfbb1", 121 | "description": "To implement cryptographic mechanisms (aka enable TLS 1.x) to {{ insert: param, sc-8.1_prm_1 }}, customers need to set the `PEMKeyFile` option in the configuration file `/etc/mongod.conf` to the certificate file's path and restart the component.", 122 | "responsible-roles": [ 123 | { 124 | "role-id": "customer" 125 | } 126 | ] 127 | } 128 | ] 129 | }, 130 | { 131 | "uuid": "5227daf8-7a4b-4fe0-aea9-3547b7de2603", 132 | "control-id": "sa-4.9", 133 | "description": "Must ensure that MongoDB only listens for network connections on authorized interfaces by configuring the MongoDB configuration file to limit the services exposure to only the network interfaces on which MongoDB instances should listen for incoming connections." 134 | } 135 | ] 136 | } 137 | ] 138 | } 139 | ], 140 | "back-matter": { 141 | "resources": [ 142 | { 143 | "uuid": "ba047e56-faef-430c-bafb-c54e9a87c6e8", 144 | "description": "NIST Special Publication 800-53 Revision 5: Moderate Baseline Profile", 145 | "rlinks": [ 146 | { 147 | "href": "../../../nist.gov/SP800-53/rev5/xml/NIST_SP-800-53_rev5_MODERATE-baseline_profile.xml", 148 | "media-type": "application/oscal.catalog+xml" 149 | }, 150 | { 151 | "href": "../../../nist.gov/SP800-53/rev5/json/NIST_SP-800-53_rev5_MODERATE-baseline_profile.json", 152 | "media-type": "application/oscal.catalog+json" 153 | }, 154 | { 155 | "href": "../../../nist.gov/SP800-53/rev5/yaml/NIST_SP-800-53_rev5_MODERATE-baseline_profile.yaml", 156 | "media-type": "application/oscal.catalog+yaml" 157 | } 158 | ] 159 | } 160 | ] 161 | } 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /roscal_lib/tests/ap/json/ifa_assessment-plan-example.json: -------------------------------------------------------------------------------- 1 | { 2 | "assessment-plan": { 3 | "uuid": "60077e84-e62f-4375-8c6c-b0e0d4560c5f", 4 | "metadata": { 5 | "title": "IFA GoodRead Assessment Plan", 6 | "last-modified": "2024-02-01T13:57:28.355446-04:00", 7 | "version": "1.0", 8 | "oscal-version": "1.1.2", 9 | "roles": [ 10 | { 11 | "id": "assessor", 12 | "title": "IFA Security Control Assessor" 13 | } 14 | ], 15 | "parties": [ 16 | { 17 | "uuid": "e7730080-71ce-4b20-bec4-84f33136fd58", 18 | "type": "person", 19 | "name": "Amy Assessor", 20 | "member-of-organizations": ["3a675986-b4ff-4030-b178-e953c2e55d64"] 21 | }, 22 | { 23 | "uuid": "3a675986-b4ff-4030-b178-e953c2e55d64", 24 | "type": "organization", 25 | "name": "Important Federal Agency", 26 | "short-name": "IFA", 27 | "links": [ 28 | { 29 | "href": "https://www.ifa.gov", 30 | "rel": "website" 31 | } 32 | ] 33 | } 34 | ], 35 | "responsible-parties": [ 36 | { 37 | "role-id": "assessor", 38 | "party-uuids": ["e7730080-71ce-4b20-bec4-84f33136fd58"] 39 | } 40 | ] 41 | }, 42 | "import-ssp": { 43 | "href": "../3-implementation/ssp.oscal.xml" 44 | }, 45 | "local-definitions": { 46 | "activities": [ 47 | { 48 | "uuid": "52277182-1ba3-4cb6-8d96-b1b97aaf9d6b", 49 | "title": "Examine System Elements for Least Privilege Design and Implementation", 50 | "description": "The activity and it steps will be performed by the assessor and facilitated by owner, ISSO, and product team for the IFA GoodRead system with necessary information and access about least privilege design and implementation of the system's elements: the application, web framework, server, and cloud account infrastructure.", 51 | "props": [ 52 | { 53 | "name": "method", 54 | "value": "EXAMINE" 55 | } 56 | ], 57 | "steps": [ 58 | { 59 | "uuid": "733e3cbf-e398-46b6-9c02-a2cb534c341e", 60 | "title": "Obtain Network Access via VPN to IFA GoodRead Environment", 61 | "description": "The assessor will obtain network access with appropriately configured VPN account to see admin frontend to the application for PAO staff, which is only accessible via VPN with an appropriately configured role for PAO staff accounts." 62 | }, 63 | { 64 | "uuid": "4ce7e0b4-d69e-4b80-a700-8600b4d4d933", 65 | "title": "Obtain Credentials and Access to AwesomeCloud Account for IFA GoodRead System", 66 | "description": "The assessor will obtain access to the GoodRead Product Team's AwesomeCloud account with their single sign-on credentials to a read-only assessor role." 67 | }, 68 | { 69 | "uuid": "3d0297de-e47b-4360-b9c3-cf5c425f86cd", 70 | "title": "Obtain Applcation Access Provided by Product Team", 71 | "description": "The assessor will obtain non-privileged account credentials with the PAO staff role to test this role in the application does not permit excessive administrative operations." 72 | }, 73 | { 74 | "uuid": "64ca1ef6-3ad4-4747-97c6-40890222463f", 75 | "title": "Confirm Load Balancer Blocks Access to Admin Frontend from Internet", 76 | "description": "The assessor will confirm that the load balancer for public access does not allow access to Admin Frontend of the application from the Internet." 77 | }, 78 | { 79 | "uuid": "715f0592-166f-44f6-bb66-d99623e035dc", 80 | "title": "Confirm GoodRead's PAO Role Cannot Manage Users", 81 | "description": "The assessor will confirm that user's logged into the GoodRead Application with the PAO staff role cannot add, modify, or disable users from the system." 82 | }, 83 | { 84 | "uuid": "4641957b-a0fa-4c61-af1a-d3e9101efe40", 85 | "title": "Confirm Django Admin Panel Not Available", 86 | "description": "The assessor will confirm with web-based interface and API methods users with the PAO Staff role cannot access the Django admin panel functions and interactively change application's database records." 87 | } 88 | ], 89 | "related-controls": { 90 | "control-selections": [ 91 | { 92 | "include-controls": [ 93 | { 94 | "control-id": "ac-6.1" 95 | } 96 | ] 97 | } 98 | ] 99 | }, 100 | "responsible-roles": [ 101 | { 102 | "role-id": "assessor", 103 | "party-uuids": ["e7730080-71ce-4b20-bec4-84f33136fd58"] 104 | } 105 | ] 106 | } 107 | ] 108 | }, 109 | "reviewed-controls": { 110 | "control-selections": [ 111 | { 112 | "include-controls": [ 113 | { 114 | "control-id": "ac-6.1" 115 | } 116 | ] 117 | } 118 | ], 119 | "control-objective-selections": [ 120 | { 121 | "include-all": {} 122 | } 123 | ] 124 | }, 125 | "assessment-subjects": [ 126 | { 127 | "type": "component", 128 | "description": "The assessor for the IFA GoodRead Project, including the application and infrastructure for this information system, are within scope of this assessment.", 129 | "include-all": {} 130 | } 131 | ], 132 | "tasks": [ 133 | { 134 | "uuid": "b3504d22-0e75-4dd7-9247-618661beba4e", 135 | "type": "action", 136 | "title": "Examine Least Privilege Design and Implementation", 137 | "associated-activities": [ 138 | { 139 | "activity-uuid": "0d243b23-a889-478f-9716-6d4870e56209", 140 | "subjects": [ 141 | { 142 | "type": "component", 143 | "include-all": {} 144 | } 145 | ] 146 | } 147 | ], 148 | "responsible-roles": [ 149 | { 150 | "role-id": "assessor" 151 | } 152 | ], 153 | "remarks": "Per IFA's use of NIST SP-800 53A, the assessor, with the support of the owner, information system security officer, and product team for the IFA GoodRead project, will examine least privilege design and implementation with the following:\n\n* list of security functions (deployed in hardware, software, and firmware) and security-relevant information for which access must be explicitly authorized;\n* system configuration settings and associated documentation;\n" 154 | } 155 | ] 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /roscal_cli/tests/merge.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | fs::{self, read_to_string, File}, 3 | io::BufReader, 4 | }; 5 | 6 | use assert_cmd::Command; 7 | use roscal_lib::control::catalog::Catalog; 8 | use tempfile::tempdir; 9 | use walkdir::WalkDir; 10 | 11 | #[test] 12 | fn cli_merge_update_uuid() { 13 | let dir = tempdir().unwrap(); 14 | let dir_arg = dir.as_ref().to_str().unwrap(); 15 | let dissect_dir = format!( 16 | "{}/tests/data/catalog.yaml", 17 | std::env::current_dir().unwrap().to_string_lossy() 18 | ); 19 | 20 | let mut cmd_dissect = Command::cargo_bin("roscal").unwrap(); 21 | let assert_dissect = cmd_dissect 22 | .args(&[ 23 | "dissect", 24 | "--file", 25 | &dissect_dir, 26 | "--model", 27 | "Catalog", 28 | "--blocks", 29 | "all", 30 | "--output-dir", 31 | dir_arg, 32 | ]) 33 | .assert(); 34 | assert_dissect.success(); 35 | 36 | for entry in WalkDir::new(dir_arg).min_depth(1).max_depth(1) { 37 | let entry = entry.unwrap(); 38 | let path = entry.path().to_str().unwrap(); 39 | 40 | let mut cmd = Command::cargo_bin("roscal").unwrap(); 41 | let assert_v4 = cmd 42 | .args(&[ 43 | "merge", 44 | "--dir", 45 | path, 46 | "--output-format", 47 | "yaml", 48 | "--output-dir", 49 | path, 50 | "--update-uuid", 51 | "v4", 52 | ]) 53 | .assert(); 54 | assert_v4.success(); 55 | 56 | let mut cmd = Command::cargo_bin("roscal").unwrap(); 57 | let assert_v5 = cmd 58 | .args(&[ 59 | "merge", 60 | "--dir", 61 | path, 62 | "--output-format", 63 | "yaml", 64 | "--output-dir", 65 | path, 66 | "--update-uuid", 67 | "v5", 68 | ]) 69 | .assert(); 70 | assert_v5.success(); 71 | } 72 | dir.close().unwrap() 73 | } 74 | 75 | #[test] 76 | fn cli_merge_modify_content() { 77 | let dir = tempdir().unwrap(); 78 | let dir_arg = dir.as_ref().to_str().unwrap(); 79 | let dissect_dir = format!( 80 | "{}/tests/data/catalog.yaml", 81 | std::env::current_dir().unwrap().to_string_lossy() 82 | ); 83 | let uuid_dir = format!( 84 | "{}/tests/data/edit_uuid", 85 | std::env::current_dir().unwrap().to_string_lossy() 86 | ); 87 | let back_matter_dir = format!( 88 | "{}/tests/data/edit_back_matter", 89 | std::env::current_dir().unwrap().to_string_lossy() 90 | ); 91 | let uuid = read_to_string(uuid_dir).unwrap(); 92 | let back_matter = read_to_string(back_matter_dir).unwrap(); 93 | 94 | let mut cmd_dissect = Command::cargo_bin("roscal").unwrap(); 95 | let assert_dissect = cmd_dissect 96 | .args(&[ 97 | "dissect", 98 | "--file", 99 | &dissect_dir, 100 | "--model", 101 | "Catalog", 102 | "--blocks", 103 | "all", 104 | "--output-dir", 105 | dir_arg, 106 | ]) 107 | .assert(); 108 | assert_dissect.success(); 109 | 110 | for entry in WalkDir::new(dir_arg).min_depth(1).max_depth(1) { 111 | let entry = entry.unwrap(); 112 | let path = entry.path().to_str().unwrap(); 113 | 114 | fs::write(format!("{}/modifiable/uuid.yaml", path), &uuid).unwrap(); 115 | fs::write( 116 | format!("{}/modifiable/back_matter.yaml", path), 117 | &back_matter, 118 | ) 119 | .unwrap(); 120 | 121 | let mut cmd = Command::cargo_bin("roscal").unwrap(); 122 | let assert = cmd 123 | .args(&[ 124 | "merge", 125 | "--dir", 126 | path, 127 | "--output-format", 128 | "yaml", 129 | "--output-dir", 130 | path, 131 | ]) 132 | .assert(); 133 | assert.success(); 134 | 135 | let file = File::open(format!("{}/merged.yaml", path)).unwrap(); 136 | let reader = BufReader::new(file); 137 | let res: Catalog = serde_yaml::from_reader(reader).unwrap(); 138 | assert_eq!( 139 | "84cbf061-eb87-4ec1-8112-1f529232e907", 140 | res.catalog.back_matter.unwrap().resources.unwrap()[0].uuid 141 | ); 142 | assert_eq!("74c8ba1e-5cd4-4ad1-bbfd-d888e2f6c721", res.catalog.uuid); 143 | } 144 | dir.close().unwrap() 145 | } 146 | 147 | #[test] 148 | fn cli_merge_wrong_dir() { 149 | let dir = tempdir().unwrap(); 150 | let dir_arg = dir.as_ref().to_str().unwrap(); 151 | 152 | let mut cmd = Command::cargo_bin("roscal").unwrap(); 153 | let assert = cmd 154 | .args(&[ 155 | "merge", 156 | "--dir", 157 | "tests/data/not", 158 | "--output-format", 159 | "yaml", 160 | "--output-dir", 161 | dir_arg, 162 | ]) 163 | .assert(); 164 | assert.stderr("Invalid directory provided: tests/data/not\n"); 165 | dir.close().unwrap() 166 | } 167 | 168 | #[test] 169 | fn cli_merge_wrong_output_format() { 170 | let dir = tempdir().unwrap(); 171 | let dir_arg = dir.as_ref().to_str().unwrap(); 172 | let dissect_dir = format!( 173 | "{}/tests/data/catalog.yaml", 174 | std::env::current_dir().unwrap().to_string_lossy() 175 | ); 176 | 177 | let mut cmd_dissect = Command::cargo_bin("roscal").unwrap(); 178 | let assert_dissect = cmd_dissect 179 | .args(&[ 180 | "dissect", 181 | "--file", 182 | &dissect_dir, 183 | "--model", 184 | "Catalog", 185 | "--blocks", 186 | "all", 187 | "--output-dir", 188 | dir_arg, 189 | ]) 190 | .assert(); 191 | assert_dissect.success(); 192 | 193 | for entry in WalkDir::new(dir_arg).min_depth(1).max_depth(1) { 194 | let entry = entry.unwrap(); 195 | let path = entry.path().to_str().unwrap(); 196 | 197 | let mut cmd = Command::cargo_bin("roscal").unwrap(); 198 | let assert = cmd 199 | .args(&[ 200 | "merge", 201 | "--dir", 202 | path, 203 | "--output-format", 204 | "ron", 205 | "--output-dir", 206 | path, 207 | ]) 208 | .assert(); 209 | assert.stderr("Error: Unknown output format. Use json or yaml\n"); 210 | } 211 | dir.close().unwrap() 212 | } 213 | 214 | #[test] 215 | fn cli_merge_wrong_uuid() { 216 | let dir = tempdir().unwrap(); 217 | let dir_arg = dir.as_ref().to_str().unwrap(); 218 | let dissect_dir = format!( 219 | "{}/tests/data/catalog.yaml", 220 | std::env::current_dir().unwrap().to_string_lossy() 221 | ); 222 | 223 | let mut cmd_dissect = Command::cargo_bin("roscal").unwrap(); 224 | let assert_dissect = cmd_dissect 225 | .args(&[ 226 | "dissect", 227 | "--file", 228 | &dissect_dir, 229 | "--model", 230 | "Catalog", 231 | "--blocks", 232 | "all", 233 | "--output-dir", 234 | dir_arg, 235 | ]) 236 | .assert(); 237 | assert_dissect.success(); 238 | 239 | for entry in WalkDir::new(dir_arg).min_depth(1).max_depth(1) { 240 | let entry = entry.unwrap(); 241 | let path = entry.path().to_str().unwrap(); 242 | 243 | let mut cmd = Command::cargo_bin("roscal").unwrap(); 244 | let assert = cmd 245 | .args(&[ 246 | "merge", 247 | "--dir", 248 | path, 249 | "--output-format", 250 | "yaml", 251 | "--output-dir", 252 | path, 253 | "--update-uuid", 254 | "v8", 255 | ]) 256 | .assert(); 257 | assert.stderr("Error: Unknown uuid version. Use v4 or v5\n"); 258 | } 259 | dir.close().unwrap() 260 | } 261 | -------------------------------------------------------------------------------- /roscal_cli/tests/roundtrip.rs: -------------------------------------------------------------------------------- 1 | use assert_cmd::Command; 2 | use tempfile::tempdir; 3 | use walkdir::WalkDir; 4 | 5 | #[test] 6 | fn cli_roundtrip_ap() { 7 | let dir = tempdir().unwrap(); 8 | let dir_arg = dir.as_ref().to_str().unwrap(); 9 | let dissect_dir = format!( 10 | "{}/tests/data/ap.yaml", 11 | std::env::current_dir().unwrap().to_string_lossy() 12 | ); 13 | 14 | let mut cmd_dissect = Command::cargo_bin("roscal").unwrap(); 15 | let assert_dissect = cmd_dissect 16 | .args(&[ 17 | "dissect", 18 | "--file", 19 | &dissect_dir, 20 | "--model", 21 | "AssessmentPlan", 22 | "--blocks", 23 | "all", 24 | "--output-dir", 25 | dir_arg, 26 | ]) 27 | .assert(); 28 | assert_dissect.success(); 29 | 30 | for entry in WalkDir::new(dir_arg).min_depth(1).max_depth(1) { 31 | let entry = entry.unwrap(); 32 | let path = entry.path().to_str().unwrap(); 33 | 34 | let mut cmd = Command::cargo_bin("roscal").unwrap(); 35 | let assert = cmd 36 | .args(&[ 37 | "merge", 38 | "--dir", 39 | path, 40 | "--output-format", 41 | "yaml", 42 | "--output-dir", 43 | path, 44 | ]) 45 | .assert(); 46 | assert.success(); 47 | } 48 | dir.close().unwrap() 49 | } 50 | 51 | #[test] 52 | fn cli_roundtrip_ar() { 53 | let dir = tempdir().unwrap(); 54 | let dir_arg = dir.as_ref().to_str().unwrap(); 55 | let dissect_dir = format!( 56 | "{}/tests/data/ar.yaml", 57 | std::env::current_dir().unwrap().to_string_lossy() 58 | ); 59 | 60 | let mut cmd_dissect = Command::cargo_bin("roscal").unwrap(); 61 | let assert_dissect = cmd_dissect 62 | .args(&[ 63 | "dissect", 64 | "--file", 65 | &dissect_dir, 66 | "--model", 67 | "AssessmentResults", 68 | "--blocks", 69 | "all", 70 | "--output-dir", 71 | dir_arg, 72 | ]) 73 | .assert(); 74 | assert_dissect.success(); 75 | 76 | for entry in WalkDir::new(dir_arg).min_depth(1).max_depth(1) { 77 | let entry = entry.unwrap(); 78 | let path = entry.path().to_str().unwrap(); 79 | 80 | let mut cmd = Command::cargo_bin("roscal").unwrap(); 81 | let assert = cmd 82 | .args(&[ 83 | "merge", 84 | "--dir", 85 | path, 86 | "--output-format", 87 | "yaml", 88 | "--output-dir", 89 | path, 90 | ]) 91 | .assert(); 92 | assert.success(); 93 | } 94 | dir.close().unwrap() 95 | } 96 | 97 | #[test] 98 | fn cli_roundtrip_comp_def() { 99 | let dir = tempdir().unwrap(); 100 | let dir_arg = dir.as_ref().to_str().unwrap(); 101 | let dissect_dir = format!( 102 | "{}/tests/data/compdef.yaml", 103 | std::env::current_dir().unwrap().to_string_lossy() 104 | ); 105 | 106 | let mut cmd_dissect = Command::cargo_bin("roscal").unwrap(); 107 | let assert_dissect = cmd_dissect 108 | .args(&[ 109 | "dissect", 110 | "--file", 111 | &dissect_dir, 112 | "--model", 113 | "ComponentDefinition", 114 | "--blocks", 115 | "all", 116 | "--output-dir", 117 | dir_arg, 118 | ]) 119 | .assert(); 120 | assert_dissect.success(); 121 | 122 | for entry in WalkDir::new(dir_arg).min_depth(1).max_depth(1) { 123 | let entry = entry.unwrap(); 124 | let path = entry.path().to_str().unwrap(); 125 | 126 | let mut cmd = Command::cargo_bin("roscal").unwrap(); 127 | let assert = cmd 128 | .args(&[ 129 | "merge", 130 | "--dir", 131 | path, 132 | "--output-format", 133 | "yaml", 134 | "--output-dir", 135 | path, 136 | ]) 137 | .assert(); 138 | assert.success(); 139 | } 140 | dir.close().unwrap() 141 | } 142 | 143 | #[test] 144 | fn cli_roundtrip_poam() { 145 | let dir = tempdir().unwrap(); 146 | let dir_arg = dir.as_ref().to_str().unwrap(); 147 | let dissect_dir = format!( 148 | "{}/tests/data/poam.yaml", 149 | std::env::current_dir().unwrap().to_string_lossy() 150 | ); 151 | 152 | let mut cmd_dissect = Command::cargo_bin("roscal").unwrap(); 153 | let assert_dissect = cmd_dissect 154 | .args(&[ 155 | "dissect", 156 | "--file", 157 | &dissect_dir, 158 | "--model", 159 | "Poam", 160 | "--blocks", 161 | "all", 162 | "--output-dir", 163 | dir_arg, 164 | ]) 165 | .assert(); 166 | assert_dissect.success(); 167 | 168 | for entry in WalkDir::new(dir_arg).min_depth(1).max_depth(1) { 169 | let entry = entry.unwrap(); 170 | let path = entry.path().to_str().unwrap(); 171 | 172 | let mut cmd = Command::cargo_bin("roscal").unwrap(); 173 | let assert = cmd 174 | .args(&[ 175 | "merge", 176 | "--dir", 177 | path, 178 | "--output-format", 179 | "yaml", 180 | "--output-dir", 181 | path, 182 | ]) 183 | .assert(); 184 | assert.success(); 185 | } 186 | dir.close().unwrap() 187 | } 188 | 189 | #[test] 190 | fn cli_roundtrip_profile() { 191 | let dir = tempdir().unwrap(); 192 | let dir_arg = dir.as_ref().to_str().unwrap(); 193 | let dissect_dir = format!( 194 | "{}/tests/data/profile.yaml", 195 | std::env::current_dir().unwrap().to_string_lossy() 196 | ); 197 | 198 | let mut cmd_dissect = Command::cargo_bin("roscal").unwrap(); 199 | let assert_dissect = cmd_dissect 200 | .args(&[ 201 | "dissect", 202 | "--file", 203 | &dissect_dir, 204 | "--model", 205 | "Profile", 206 | "--blocks", 207 | "all", 208 | "--output-dir", 209 | dir_arg, 210 | ]) 211 | .assert(); 212 | assert_dissect.success(); 213 | 214 | for entry in WalkDir::new(dir_arg).min_depth(1).max_depth(1) { 215 | let entry = entry.unwrap(); 216 | let path = entry.path().to_str().unwrap(); 217 | 218 | let mut cmd = Command::cargo_bin("roscal").unwrap(); 219 | let assert = cmd 220 | .args(&[ 221 | "merge", 222 | "--dir", 223 | path, 224 | "--output-format", 225 | "yaml", 226 | "--output-dir", 227 | path, 228 | ]) 229 | .assert(); 230 | assert.success(); 231 | } 232 | dir.close().unwrap() 233 | } 234 | 235 | #[test] 236 | fn cli_roundtrip_ssp() { 237 | let dir = tempdir().unwrap(); 238 | let dir_arg = dir.as_ref().to_str().unwrap(); 239 | let dissect_dir = format!( 240 | "{}/tests/data/ssp.yaml", 241 | std::env::current_dir().unwrap().to_string_lossy() 242 | ); 243 | 244 | let mut cmd_dissect = Command::cargo_bin("roscal").unwrap(); 245 | let assert_dissect = cmd_dissect 246 | .args(&[ 247 | "dissect", 248 | "--file", 249 | &dissect_dir, 250 | "--model", 251 | "Ssp", 252 | "--blocks", 253 | "all", 254 | "--output-dir", 255 | dir_arg, 256 | ]) 257 | .assert(); 258 | assert_dissect.success(); 259 | 260 | for entry in WalkDir::new(dir_arg).min_depth(1).max_depth(1) { 261 | let entry = entry.unwrap(); 262 | let path = entry.path().to_str().unwrap(); 263 | 264 | let mut cmd = Command::cargo_bin("roscal").unwrap(); 265 | let assert = cmd 266 | .args(&[ 267 | "merge", 268 | "--dir", 269 | path, 270 | "--output-format", 271 | "yaml", 272 | "--output-dir", 273 | path, 274 | ]) 275 | .assert(); 276 | assert.success(); 277 | } 278 | dir.close().unwrap() 279 | } 280 | -------------------------------------------------------------------------------- /roscal_cli/tests/data/ar.yaml: -------------------------------------------------------------------------------- 1 | assessment-results: 2 | uuid: ec0dad37-54e0-40fd-a925-6d0bdea94c0d 3 | metadata: 4 | title: IFA GoodRead Continuous Monitoring Assessment Results June 2023 5 | last-modified: "2024-02-01T13:57:28.355446-04:00" 6 | version: 202306-002 7 | oscal-version: 1.1.2 8 | roles: 9 | - id: assessor 10 | title: IFA Security Controls Assessor 11 | parties: 12 | - uuid: e7730080-71ce-4b20-bec4-84f33136fd58 13 | type: person 14 | name: Amy Assessor 15 | member-of-organizations: 16 | - 3a675986-b4ff-4030-b178-e953c2e55d64 17 | - uuid: 3a675986-b4ff-4030-b178-e953c2e55d64 18 | type: organization 19 | name: Important Federal Agency 20 | short-name: IFA 21 | links: 22 | - href: https://www.ifa.gov 23 | rel: website 24 | responsible-parties: 25 | - role-id: assessor 26 | party-uuids: 27 | - e7730080-71ce-4b20-bec4-84f33136fd58 28 | import-ap: 29 | href: ./ap.oscal.xml 30 | local-definitions: 31 | activities: 32 | - uuid: cf5d53fe-6043-4c68-9ed6-6b258909febf 33 | title: Test System Elements for Least Privilege Design and Implementation 34 | description: The activity and it steps will be performed by the assessor via their security automation platform to test least privilege design and implementation of the system's elements, specifically the cloud account infrastructure, as part of continuous monitoring. 35 | props: 36 | - name: method 37 | value: TEST 38 | steps: 39 | - uuid: 57f8cfb8-fc3f-41d3-b938-6ab421c92574 40 | title: Configure Cross-Account IAM Role Trust for GoodRead and Assessor AwesomeCloud Accounts 41 | description: The GoodRead system engineer will coordinate with the assessor's engineering support staff to configure an IAM role trust. A service account for automation with its own role with the assessor's AwesomeCloud account can assume the role for read-only assessor operations within the GoodRead Product Team's AwesomeCloud account for continuous monitoring of least privilege. 42 | remarks: |- 43 | This step is complete. 44 | 45 | GoodRead Product Team and SCA Engineering Support configured the latter's cross-account role trust and authentication and authorization in to the former's account on May 29, 2023. 46 | - uuid: 976aadad-b1ce-475b-aa6c-e082537e7902 47 | title: Automate Cross-Account Login to GoodRead AwesomeCloud Account 48 | description: The assessor's security automation platform will create a session from their dedicated will obtain access to the GoodRead Product Team's AwesomeCloud account with their single sign-on credentials to a read-only assessor role. 49 | remarks: |- 50 | This step is complete. 51 | 52 | GoodRead Product Team and SCA Engineering Support tested scripts from the security automation platform interactively on May 30, 2023, to confirm they work ahead of June 2023 continuous monitoring cycle. 53 | - uuid: 18ce4e19-7432-4484-8e75-2dd8f05668cf 54 | title: Analyze GoodRead Developer and System Engineer Roles for Least Privilege 55 | description: | 56 | Once authenticated and authorized with a cross-account session, the security automation pipeline will execute scripts developed and maintained by the assessor's engineering support staff. It will analyze the permitted actions for the developer and system engineer roles in the GoodRead Product Team's AwesomeCloud account to confirm they are designed and implement to facilitate only least privilege operation. Examples are included below. 57 | 58 | * For the GoodRead developer role in their AwesomeCloud account, the developer role may only permit the user with this role to check the IP addresses and status of the Awesome Compute Service server instances. This role will not permit the user to create, change, or delete the instances. Similarly, the developer will permit a user to perform actions to see IP addresses of an Awesome Load Balancer instance, but not add, change, or delete the instances. 59 | * For the GoodRead system engineer role in their AwesomeCloud account, the system engineer role may only permit actions where the user can add, change, or delete instances for approved services (i.e. Awesome Compute Service, Awesome Load Balancer, et cetera). The role may not permit actions by the user for any other service. 60 | related-controls: 61 | control-selections: 62 | - include-controls: 63 | - control-id: ac-6.1 64 | responsible-roles: 65 | - role-id: assessor 66 | party-uuids: 67 | - e7730080-71ce-4b20-bec4-84f33136fd58 68 | results: 69 | - uuid: a1d20136-37e0-42aa-9834-4e9d8c36d798 70 | title: IFA GoodRead Continous Monitoring Results June 2023 71 | description: Automated monthly continuous monitoring of the GoodRead information system's cloud infrastructure recorded observations below. Additionally, contingent upon the confidence level of the observations and possible risks, confirmed findings may be opened. 72 | start: "2023-06-02T08:31:20-04:00" 73 | end: "2023-06-02T08:46:51-04:00" 74 | local-definitions: 75 | tasks: 76 | - uuid: 35876484-aa4b-494d-95a2-0d1cc04eb47e 77 | type: action 78 | title: Test System Elements for Least Privilege Design and Implementation 79 | description: The activity and it steps will be performed by the assessor via their security automation platform to test least privilege design and implementation of the system's elements, specifically the cloud account infrastructure, as part of continuous monitoring. 80 | associated-activities: 81 | - activity-uuid: cf5d53fe-6043-4c68-9ed6-6b258909febf 82 | subjects: 83 | - type: component 84 | include-all: {} 85 | reviewed-controls: 86 | control-selections: 87 | - include-controls: 88 | - control-id: ac-6.1 89 | observations: 90 | - uuid: 8807eb6e-0c05-43bc-8438-799739615e34 91 | title: AwesomeCloud IAM Roles Test - GoodRead System Engineer Role 92 | description: Test AwesomeCloud IAM Roles for least privilege design and implementation. 93 | methods: 94 | - TEST 95 | types: 96 | - finding 97 | subjects: 98 | - subject-uuid: 551b9706-d6a4-4d25-8207-f2ccec548b89 99 | type: component 100 | collected: "2023-06-02T08:31:20-04:00" 101 | expires: "2023-07-01T00:00:00-04:00" 102 | remarks: |- 103 | The assessor's security automation platform analyzed all roles specific to the GoodRead Product Team, not those managed by the Office of Information Technology. The `IFA-GoodRead-SystemEnginer` role in their respective AwesomeCloud account permitted use of the following high-risk actions. 104 | 105 | * awesomecloud:auditlog:DeleteAccountAuditLog 106 | * awesomecloud:secmon:AdministerConfigurations 107 | 108 | 109 | Both of these actions are overly permissive and not appropriate for the business function of the staff member assigned this role. 110 | - uuid: 4a2fb32e-9be9-43cf-b717-e9e47de061bd 111 | title: AwesomeCloud IAM Roles Test - GoodRead Developer Role 112 | description: Test AwesomeCloud IAM Roles for least privilege design and implementation. 113 | methods: 114 | - TEST 115 | types: 116 | - finding 117 | subjects: 118 | - subject-uuid: 551b9706-d6a4-4d25-8207-f2ccec548b89 119 | type: component 120 | collected: "2023-06-02T08:31:20-04:00" 121 | expires: "2023-07-01T00:00:00-04:00" 122 | remarks: The assessor's security automation platform detected that the developer's role is permitted to perform only permissible actions in the GoodRead AwesomeCloud account in accordance with the agency's least privilege policy and procedures. 123 | risks: 124 | - uuid: 0cfa750e-3553-47ba-a7ba-cf84a884d261 125 | title: GoodRead System Engineers Have Over-Privileged Access to Cloud Infrastructure Account 126 | description: A user in the GoodRead cloud environment with the privileges of a system engineer can exceed the intended privileges for their related business function. They can delete all historical audit records and remove important security monitoring functions for the IFA Security Operations Center staff. 127 | statement: |- 128 | An account without proper least privilege design and implementation can be used to surreptitiously add, change, or delete cloud infrastructure to the too managing all links to IFA's communication to public citizens, potentially causing significant harm with no forensic evidence to recover the system. Regardless of the extent and duration of a potential incident, such a configuration greatly increases the risk of an insider threat if there were likely to a potential insider threat in the GoodRead Product Team. 129 | 130 | If such an insider threat existed and acted with this misconfigruatio, the resulting event could cause significant financial and reputational risk to IFA's Administrator, executive staff, and the agency overall. 131 | status: investigating 132 | findings: 133 | - uuid: 45d8a6c2-1368-4bad-9ba0-7141f0a32889 134 | title: GoodRead AwesomeCloud Account's System Engineer Role Permits High Risk Actions 135 | description: |- 136 | The assessor's security automation platform detected that the system engineer's role is permitted to perform the following actions in the GoodRead AwesomeCloud account. 137 | 138 | * Delete and reset account audit logs. 139 | * Add, change, or delete security monitoring configurations in the Awesome Security Monitor service used by the IFA Security Operations Center. 140 | 141 | 142 | The system engineer is not permitted to modify these services and their role was incorrectly configured. 143 | target: 144 | type: objective-id 145 | target-id: ac-6.1_obj 146 | description: This is a finding. 147 | status: 148 | state: not-satisfied 149 | implementation-statement-uuid: d5f9b263-965d-440b-99e7-77f5df670a11 150 | related-observations: 151 | - observation-uuid: 8807eb6e-0c05-43bc-8438-799739615e34 152 | related-risks: 153 | - risk-uuid: 0cfa750e-3553-47ba-a7ba-cf84a884d261 -------------------------------------------------------------------------------- /roscal_cli/tests/data/poam.yaml: -------------------------------------------------------------------------------- 1 | plan-of-action-and-milestones: 2 | uuid: 714210d2-f8df-448c-be3e-e2213816cf79 3 | metadata: 4 | title: IFA GoodRead Plan of Action and Milestones 5 | last-modified: "2024-02-01T13:57:28.355446-04:00" 6 | version: "1.1" 7 | oscal-version: 1.1.2 8 | import-ssp: 9 | href: ../5-authorize/ssp.oscal.xml 10 | system-id: 11 | identifier-type: http://ietf.org/rfc/rfc4122 12 | id: 8101e04d-8305-4e73-bb95-6b59f645b143 13 | observations: 14 | - uuid: 0c4de4fc-9bde-46af-b6fe-3b5e78194dcf 15 | title: Django Framework Examination 16 | description: Examine Django Framework for least privilege design and implementation. 17 | methods: 18 | - EXAMINE 19 | types: 20 | - control-objective 21 | subjects: 22 | - subject-uuid: 551b9706-d6a4-4d25-8207-f2ccec548b89 23 | type: component 24 | collected: "2023-05-19T12:14:16-04:00" 25 | remarks: The assessor attempted to access the admin panel while logged into the GoodRead application as a PAO staff user. They were able to see the admin panel and directly edit database records for the application using the Django Framework's admin panel. 26 | - uuid: 8807eb6e-0c05-43bc-8438-799739615e34 27 | title: AwesomeCloud IAM Roles Test - GoodRead System Engineer Role 28 | description: Test AwesomeCloud IAM Roles for least privilege design and implementation. 29 | methods: 30 | - TEST 31 | types: 32 | - finding 33 | subjects: 34 | - subject-uuid: 551b9706-d6a4-4d25-8207-f2ccec548b89 35 | type: component 36 | collected: "2023-06-02T08:31:20-04:00" 37 | expires: "2023-07-01T00:00:00-04:00" 38 | remarks: |- 39 | The assessor's security automation platform analyzed all roles specific to the GoodRead Product Team, not those managed by the Office of Information Technology. The `IFA-GoodRead-SystemEnginer` role in their respective AwesomeCloud account permitted use of the following high-risk actions. 40 | 41 | * awesomecloud:auditlog:DeleteAccountAuditLog 42 | * awesomecloud:secmon:AdministerConfigurations 43 | 44 | 45 | Both of these actions are overly permissive and not appropriate for the business function of the staff member assigned this role. 46 | risks: 47 | - uuid: 8b8bae66-b28c-4fa5-9a20-b79e7322fc00 48 | title: 'IFA-GOODREAD-RISK-1: PAO Staff Have Over-Privileged Access to GoodRead System' 49 | description: A user with the privileges of a PAO staff user can exceed the intended privileges for their related business function and directly edit the database for the GoodRead application. 50 | statement: |- 51 | An account without proper least privilege design and implementation can be used to significantly damage links created by the tool for use by public citizens, potentially causing a national outage. If an outage were to occur, IFA and Government policy will require the CIO of the agency to notify the Department of Homeland Security and the public. 52 | 53 | Such an event will cause significant financial and reputational risk to IFA's Administrator, executive staff, and the agency overall. 54 | status: deviation-approved 55 | characterizations: 56 | - origin: 57 | actors: 58 | - type: party 59 | actor-uuid: e7730080-71ce-4b20-bec4-84f33136fd58 60 | facets: 61 | - name: likelihood 62 | system: https://ifa.gov/division/ociso/sca 63 | value: low 64 | - name: impact 65 | system: https://ifa.gov/division/ociso/sca 66 | value: high 67 | mitigating-factors: 68 | - uuid: 401c15c9-ad6b-4d4a-a591-7d53a3abb3b6 69 | description: The GoodRead application is designed and implemented to only allow access to the administrative functions for those with PAO staff fole via the VPN via network configuration between the IFA Enterprise Support Systems and the GoodRead AwesomeCloud account. Additionally, the load balanacer configuration only allows access to view shortlinks from the public internet. 70 | deadline: "2024-01-01T05:00:00-04:00" 71 | remediations: 72 | - uuid: d28873f7-0a45-476d-9cd3-1d2ec0b8bca1 73 | lifecycle: planned 74 | title: 'IFA-GOODREAD-RISK1-RESPONSE: IFA GoodRead Prouct Team Response' 75 | description: The GoodRead Product Team does not have sufficient personnel and budget to implement the required changes in their use of the Django Framework and its configuration in this quarter. With the consultation of the ISSO and the assessor, the owner of the GoodRead system has decided to accept this risk until the end of December 2023. From September to December, budget will be available for the Good Read Product Team's developer and system engineer to completely disable the functionality that is the source of the risk and its originating finding. 76 | props: 77 | - name: type 78 | value: accept 79 | tasks: 80 | - uuid: f8b1d4cb-d1a9-4932-9859-2e93b325f287 81 | type: milestone 82 | title: End of Year Project Management Report of Developed Remediations 83 | description: The owner, ISSO, and product team of the GoodRead Project intend to complete the necessary development between September 2023 and December 2023. Whether or not the necessary development for remedation is complete, the product team's project manager will submit the final annual report. They will identify this work item and whether it has been completed. 84 | timing: 85 | within-date-range: 86 | start: "2023-09-29T09:00:00-04:00" 87 | end: "2024-01-01T05:00:00-04:00" 88 | related-observations: 89 | - observation-uuid: 0c4de4fc-9bde-46af-b6fe-3b5e78194dcf 90 | - uuid: 1c65d2d3-7735-47fa-8f68-a236744beab7 91 | title: 'IFA-GOODREAD-RISK-2: GoodRead System Engineers Have Over-Privileged Access to Cloud Infrastructure Account' 92 | description: A user in the GoodRead cloud environment with the privileges of a system engineer can exceed the intended privileges for their related business function. They can delete all historical audit records and remove important security monitoring functions for the IFA Security Operations Center staff. 93 | statement: |- 94 | An account without proper least privilege design and implementation can be used to surreptitiously add, change, or delete cloud infrastructure to the too managing all links to IFA's communication to public citizens, potentially causing significant harm with no forensic evidence to recover the system. Regardless of the extent and duration of a potential incident, such a configuration greatly increases the risk of an insider threat if there were likely to a potential insider threat in the GoodRead Product Team. 95 | 96 | If such an insider threat existed and acted with this misconfigruatio, the resulting event could cause significant financial and reputational risk to IFA's Administrator, executive staff, and the agency overall. 97 | status: open 98 | characterizations: 99 | - origin: 100 | actors: 101 | - type: party 102 | actor-uuid: e7730080-71ce-4b20-bec4-84f33136fd58 103 | facets: 104 | - name: likelihood 105 | system: https://ifa.gov/division/ociso/sca 106 | value: low 107 | - name: impact 108 | system: https://ifa.gov/division/ociso/sca 109 | value: high 110 | deadline: "2023-06-23T17:00:00-04:00" 111 | remediations: 112 | - uuid: 4676b126-ba6d-40cc-9dc8-f2aa677b03ee 113 | lifecycle: planned 114 | title: 'IFA-GOODREAD-RISK1-RESPONSE: IFA GoodRead Prouct Team Response' 115 | description: The GoodRead Product Team does not have siginficant mitigations or compensating controls to counter this risk, even if likelihood is low. The IFA CISO has cited ongoing guidance that potential insider threat risks be prioritized above alternative categories of risk for this quarter. Additionally, there is sufficient budget and unallocated time for the GoodRead and Office of Information Technology system engineers to modify AwesomeCloud IAM roles on or before the next continuous monitoring cycle beginning in July 2023. The planned completion data is June 23, 2023. 116 | props: 117 | - name: type 118 | value: mitigate 119 | tasks: 120 | - uuid: a0bb457d-0d14-4a74-801a-ffc9bc4cd636 121 | type: milestone 122 | title: Completion of GoodRead Sprint Ending June 23, 2023 123 | description: The owner, ISSO, and product team of the GoodRead Project intend to complete the necessary development by June 23. 2023, the last day of the coinciding sprint. Whether or not the necessary development for mitigation is complete, the product team's project manager will write a brief at the end of the sprint to thw owner and ISSO of this system with the final status and determination of this work item in this sprint. 124 | timing: 125 | within-date-range: 126 | start: "2023-06-03T00:00:00-04:00" 127 | end: "2024-06-23T17:00:00-04:00" 128 | related-observations: 129 | - observation-uuid: 8807eb6e-0c05-43bc-8438-799739615e34 130 | poam-items: 131 | - uuid: e174dfb9-0ae3-4a8f-8e7c-081527b84337 132 | title: Update Django Framework Configuration to Disable Default Admin Panel 133 | description: Budget and technical staff are needed to re-design and re-implement a part of the GoodRead application's use of a web appplication programming framework to mitigate the risk of low privilege users directly modifying the database of this application. This application is a high-visibility service and integral to future operations of the IFA Office of Public Affairs and its staff. 134 | related-observations: 135 | - observation-uuid: 0c4de4fc-9bde-46af-b6fe-3b5e78194dcf 136 | related-risks: 137 | - risk-uuid: 401c15c9-ad6b-4d4a-a591-7d53a3abb3b6 138 | - uuid: 48c8368d-43ff-4736-9b28-64b1b1284c03 139 | title: GoodRead System Engineers Have Over-Privileged Access to Cloud Infrastructure Account 140 | description: Budget and technical staff allocation are available and designated to fix a misconfiguration of the IAM roles for members of the GoodRead Product Team in their AwesomeCloud account to implement least privilege as designed. 141 | related-observations: 142 | - observation-uuid: 8807eb6e-0c05-43bc-8438-799739615e34 143 | related-risks: 144 | - risk-uuid: 1c65d2d3-7735-47fa-8f68-a236744beab7 -------------------------------------------------------------------------------- /roscal_lib/tests/ar/yaml/ifa_assessment-results-example.yaml: -------------------------------------------------------------------------------- 1 | assessment-results: 2 | uuid: ec0dad37-54e0-40fd-a925-6d0bdea94c0d 3 | metadata: 4 | title: IFA GoodRead Continuous Monitoring Assessment Results June 2023 5 | last-modified: "2024-02-01T13:57:28.355446-04:00" 6 | version: 202306-002 7 | oscal-version: 1.1.2 8 | roles: 9 | - id: assessor 10 | title: IFA Security Controls Assessor 11 | parties: 12 | - uuid: e7730080-71ce-4b20-bec4-84f33136fd58 13 | type: person 14 | name: Amy Assessor 15 | member-of-organizations: 16 | - 3a675986-b4ff-4030-b178-e953c2e55d64 17 | - uuid: 3a675986-b4ff-4030-b178-e953c2e55d64 18 | type: organization 19 | name: Important Federal Agency 20 | short-name: IFA 21 | links: 22 | - href: https://www.ifa.gov 23 | rel: website 24 | responsible-parties: 25 | - role-id: assessor 26 | party-uuids: 27 | - e7730080-71ce-4b20-bec4-84f33136fd58 28 | import-ap: 29 | href: ./ap.oscal.xml 30 | local-definitions: 31 | activities: 32 | - uuid: cf5d53fe-6043-4c68-9ed6-6b258909febf 33 | title: Test System Elements for Least Privilege Design and Implementation 34 | description: The activity and it steps will be performed by the assessor via their security automation platform to test least privilege design and implementation of the system's elements, specifically the cloud account infrastructure, as part of continuous monitoring. 35 | props: 36 | - name: method 37 | value: TEST 38 | steps: 39 | - uuid: 57f8cfb8-fc3f-41d3-b938-6ab421c92574 40 | title: Configure Cross-Account IAM Role Trust for GoodRead and Assessor AwesomeCloud Accounts 41 | description: The GoodRead system engineer will coordinate with the assessor's engineering support staff to configure an IAM role trust. A service account for automation with its own role with the assessor's AwesomeCloud account can assume the role for read-only assessor operations within the GoodRead Product Team's AwesomeCloud account for continuous monitoring of least privilege. 42 | remarks: |- 43 | This step is complete. 44 | 45 | GoodRead Product Team and SCA Engineering Support configured the latter's cross-account role trust and authentication and authorization in to the former's account on May 29, 2023. 46 | - uuid: 976aadad-b1ce-475b-aa6c-e082537e7902 47 | title: Automate Cross-Account Login to GoodRead AwesomeCloud Account 48 | description: The assessor's security automation platform will create a session from their dedicated will obtain access to the GoodRead Product Team's AwesomeCloud account with their single sign-on credentials to a read-only assessor role. 49 | remarks: |- 50 | This step is complete. 51 | 52 | GoodRead Product Team and SCA Engineering Support tested scripts from the security automation platform interactively on May 30, 2023, to confirm they work ahead of June 2023 continuous monitoring cycle. 53 | - uuid: 18ce4e19-7432-4484-8e75-2dd8f05668cf 54 | title: Analyze GoodRead Developer and System Engineer Roles for Least Privilege 55 | description: | 56 | Once authenticated and authorized with a cross-account session, the security automation pipeline will execute scripts developed and maintained by the assessor's engineering support staff. It will analyze the permitted actions for the developer and system engineer roles in the GoodRead Product Team's AwesomeCloud account to confirm they are designed and implement to facilitate only least privilege operation. Examples are included below. 57 | 58 | * For the GoodRead developer role in their AwesomeCloud account, the developer role may only permit the user with this role to check the IP addresses and status of the Awesome Compute Service server instances. This role will not permit the user to create, change, or delete the instances. Similarly, the developer will permit a user to perform actions to see IP addresses of an Awesome Load Balancer instance, but not add, change, or delete the instances. 59 | * For the GoodRead system engineer role in their AwesomeCloud account, the system engineer role may only permit actions where the user can add, change, or delete instances for approved services (i.e. Awesome Compute Service, Awesome Load Balancer, et cetera). The role may not permit actions by the user for any other service. 60 | related-controls: 61 | control-selections: 62 | - include-controls: 63 | - control-id: ac-6.1 64 | responsible-roles: 65 | - role-id: assessor 66 | party-uuids: 67 | - e7730080-71ce-4b20-bec4-84f33136fd58 68 | results: 69 | - uuid: a1d20136-37e0-42aa-9834-4e9d8c36d798 70 | title: IFA GoodRead Continous Monitoring Results June 2023 71 | description: Automated monthly continuous monitoring of the GoodRead information system's cloud infrastructure recorded observations below. Additionally, contingent upon the confidence level of the observations and possible risks, confirmed findings may be opened. 72 | start: "2023-06-02T08:31:20-04:00" 73 | end: "2023-06-02T08:46:51-04:00" 74 | local-definitions: 75 | tasks: 76 | - uuid: 35876484-aa4b-494d-95a2-0d1cc04eb47e 77 | type: action 78 | title: Test System Elements for Least Privilege Design and Implementation 79 | description: The activity and it steps will be performed by the assessor via their security automation platform to test least privilege design and implementation of the system's elements, specifically the cloud account infrastructure, as part of continuous monitoring. 80 | associated-activities: 81 | - activity-uuid: cf5d53fe-6043-4c68-9ed6-6b258909febf 82 | subjects: 83 | - type: component 84 | include-all: {} 85 | reviewed-controls: 86 | control-selections: 87 | - include-controls: 88 | - control-id: ac-6.1 89 | observations: 90 | - uuid: 8807eb6e-0c05-43bc-8438-799739615e34 91 | title: AwesomeCloud IAM Roles Test - GoodRead System Engineer Role 92 | description: Test AwesomeCloud IAM Roles for least privilege design and implementation. 93 | methods: 94 | - TEST 95 | types: 96 | - finding 97 | subjects: 98 | - subject-uuid: 551b9706-d6a4-4d25-8207-f2ccec548b89 99 | type: component 100 | collected: "2023-06-02T08:31:20-04:00" 101 | expires: "2023-07-01T00:00:00-04:00" 102 | remarks: |- 103 | The assessor's security automation platform analyzed all roles specific to the GoodRead Product Team, not those managed by the Office of Information Technology. The `IFA-GoodRead-SystemEnginer` role in their respective AwesomeCloud account permitted use of the following high-risk actions. 104 | 105 | * awesomecloud:auditlog:DeleteAccountAuditLog 106 | * awesomecloud:secmon:AdministerConfigurations 107 | 108 | 109 | Both of these actions are overly permissive and not appropriate for the business function of the staff member assigned this role. 110 | - uuid: 4a2fb32e-9be9-43cf-b717-e9e47de061bd 111 | title: AwesomeCloud IAM Roles Test - GoodRead Developer Role 112 | description: Test AwesomeCloud IAM Roles for least privilege design and implementation. 113 | methods: 114 | - TEST 115 | types: 116 | - finding 117 | subjects: 118 | - subject-uuid: 551b9706-d6a4-4d25-8207-f2ccec548b89 119 | type: component 120 | collected: "2023-06-02T08:31:20-04:00" 121 | expires: "2023-07-01T00:00:00-04:00" 122 | remarks: The assessor's security automation platform detected that the developer's role is permitted to perform only permissible actions in the GoodRead AwesomeCloud account in accordance with the agency's least privilege policy and procedures. 123 | risks: 124 | - uuid: 0cfa750e-3553-47ba-a7ba-cf84a884d261 125 | title: GoodRead System Engineers Have Over-Privileged Access to Cloud Infrastructure Account 126 | description: A user in the GoodRead cloud environment with the privileges of a system engineer can exceed the intended privileges for their related business function. They can delete all historical audit records and remove important security monitoring functions for the IFA Security Operations Center staff. 127 | statement: |- 128 | An account without proper least privilege design and implementation can be used to surreptitiously add, change, or delete cloud infrastructure to the too managing all links to IFA's communication to public citizens, potentially causing significant harm with no forensic evidence to recover the system. Regardless of the extent and duration of a potential incident, such a configuration greatly increases the risk of an insider threat if there were likely to a potential insider threat in the GoodRead Product Team. 129 | 130 | If such an insider threat existed and acted with this misconfigruatio, the resulting event could cause significant financial and reputational risk to IFA's Administrator, executive staff, and the agency overall. 131 | status: investigating 132 | findings: 133 | - uuid: 45d8a6c2-1368-4bad-9ba0-7141f0a32889 134 | title: GoodRead AwesomeCloud Account's System Engineer Role Permits High Risk Actions 135 | description: |- 136 | The assessor's security automation platform detected that the system engineer's role is permitted to perform the following actions in the GoodRead AwesomeCloud account. 137 | 138 | * Delete and reset account audit logs. 139 | * Add, change, or delete security monitoring configurations in the Awesome Security Monitor service used by the IFA Security Operations Center. 140 | 141 | 142 | The system engineer is not permitted to modify these services and their role was incorrectly configured. 143 | target: 144 | type: objective-id 145 | target-id: ac-6.1_obj 146 | description: This is a finding. 147 | status: 148 | state: not-satisfied 149 | implementation-statement-uuid: d5f9b263-965d-440b-99e7-77f5df670a11 150 | related-observations: 151 | - observation-uuid: 8807eb6e-0c05-43bc-8438-799739615e34 152 | related-risks: 153 | - risk-uuid: 0cfa750e-3553-47ba-a7ba-cf84a884d261 154 | -------------------------------------------------------------------------------- /roscal_lib/tests/poam/yaml/ifa_plan-of-action-and-milestones.yaml: -------------------------------------------------------------------------------- 1 | plan-of-action-and-milestones: 2 | uuid: 714210d2-f8df-448c-be3e-e2213816cf79 3 | metadata: 4 | title: IFA GoodRead Plan of Action and Milestones 5 | last-modified: "2024-02-01T13:57:28.355446-04:00" 6 | version: "1.1" 7 | oscal-version: 1.1.2 8 | import-ssp: 9 | href: ../5-authorize/ssp.oscal.xml 10 | system-id: 11 | identifier-type: http://ietf.org/rfc/rfc4122 12 | id: 8101e04d-8305-4e73-bb95-6b59f645b143 13 | observations: 14 | - uuid: 0c4de4fc-9bde-46af-b6fe-3b5e78194dcf 15 | title: Django Framework Examination 16 | description: Examine Django Framework for least privilege design and implementation. 17 | methods: 18 | - EXAMINE 19 | types: 20 | - control-objective 21 | subjects: 22 | - subject-uuid: 551b9706-d6a4-4d25-8207-f2ccec548b89 23 | type: component 24 | collected: "2023-05-19T12:14:16-04:00" 25 | remarks: The assessor attempted to access the admin panel while logged into the GoodRead application as a PAO staff user. They were able to see the admin panel and directly edit database records for the application using the Django Framework's admin panel. 26 | - uuid: 8807eb6e-0c05-43bc-8438-799739615e34 27 | title: AwesomeCloud IAM Roles Test - GoodRead System Engineer Role 28 | description: Test AwesomeCloud IAM Roles for least privilege design and implementation. 29 | methods: 30 | - TEST 31 | types: 32 | - finding 33 | subjects: 34 | - subject-uuid: 551b9706-d6a4-4d25-8207-f2ccec548b89 35 | type: component 36 | collected: "2023-06-02T08:31:20-04:00" 37 | expires: "2023-07-01T00:00:00-04:00" 38 | remarks: |- 39 | The assessor's security automation platform analyzed all roles specific to the GoodRead Product Team, not those managed by the Office of Information Technology. The `IFA-GoodRead-SystemEnginer` role in their respective AwesomeCloud account permitted use of the following high-risk actions. 40 | 41 | * awesomecloud:auditlog:DeleteAccountAuditLog 42 | * awesomecloud:secmon:AdministerConfigurations 43 | 44 | 45 | Both of these actions are overly permissive and not appropriate for the business function of the staff member assigned this role. 46 | risks: 47 | - uuid: 8b8bae66-b28c-4fa5-9a20-b79e7322fc00 48 | title: 'IFA-GOODREAD-RISK-1: PAO Staff Have Over-Privileged Access to GoodRead System' 49 | description: A user with the privileges of a PAO staff user can exceed the intended privileges for their related business function and directly edit the database for the GoodRead application. 50 | statement: |- 51 | An account without proper least privilege design and implementation can be used to significantly damage links created by the tool for use by public citizens, potentially causing a national outage. If an outage were to occur, IFA and Government policy will require the CIO of the agency to notify the Department of Homeland Security and the public. 52 | 53 | Such an event will cause significant financial and reputational risk to IFA's Administrator, executive staff, and the agency overall. 54 | status: deviation-approved 55 | characterizations: 56 | - origin: 57 | actors: 58 | - type: party 59 | actor-uuid: e7730080-71ce-4b20-bec4-84f33136fd58 60 | facets: 61 | - name: likelihood 62 | system: https://ifa.gov/division/ociso/sca 63 | value: low 64 | - name: impact 65 | system: https://ifa.gov/division/ociso/sca 66 | value: high 67 | mitigating-factors: 68 | - uuid: 401c15c9-ad6b-4d4a-a591-7d53a3abb3b6 69 | description: The GoodRead application is designed and implemented to only allow access to the administrative functions for those with PAO staff fole via the VPN via network configuration between the IFA Enterprise Support Systems and the GoodRead AwesomeCloud account. Additionally, the load balanacer configuration only allows access to view shortlinks from the public internet. 70 | deadline: "2024-01-01T05:00:00-04:00" 71 | remediations: 72 | - uuid: d28873f7-0a45-476d-9cd3-1d2ec0b8bca1 73 | lifecycle: planned 74 | title: 'IFA-GOODREAD-RISK1-RESPONSE: IFA GoodRead Prouct Team Response' 75 | description: The GoodRead Product Team does not have sufficient personnel and budget to implement the required changes in their use of the Django Framework and its configuration in this quarter. With the consultation of the ISSO and the assessor, the owner of the GoodRead system has decided to accept this risk until the end of December 2023. From September to December, budget will be available for the Good Read Product Team's developer and system engineer to completely disable the functionality that is the source of the risk and its originating finding. 76 | props: 77 | - name: type 78 | value: accept 79 | tasks: 80 | - uuid: f8b1d4cb-d1a9-4932-9859-2e93b325f287 81 | type: milestone 82 | title: End of Year Project Management Report of Developed Remediations 83 | description: The owner, ISSO, and product team of the GoodRead Project intend to complete the necessary development between September 2023 and December 2023. Whether or not the necessary development for remedation is complete, the product team's project manager will submit the final annual report. They will identify this work item and whether it has been completed. 84 | timing: 85 | within-date-range: 86 | start: "2023-09-29T09:00:00-04:00" 87 | end: "2024-01-01T05:00:00-04:00" 88 | related-observations: 89 | - observation-uuid: 0c4de4fc-9bde-46af-b6fe-3b5e78194dcf 90 | - uuid: 1c65d2d3-7735-47fa-8f68-a236744beab7 91 | title: 'IFA-GOODREAD-RISK-2: GoodRead System Engineers Have Over-Privileged Access to Cloud Infrastructure Account' 92 | description: A user in the GoodRead cloud environment with the privileges of a system engineer can exceed the intended privileges for their related business function. They can delete all historical audit records and remove important security monitoring functions for the IFA Security Operations Center staff. 93 | statement: |- 94 | An account without proper least privilege design and implementation can be used to surreptitiously add, change, or delete cloud infrastructure to the too managing all links to IFA's communication to public citizens, potentially causing significant harm with no forensic evidence to recover the system. Regardless of the extent and duration of a potential incident, such a configuration greatly increases the risk of an insider threat if there were likely to a potential insider threat in the GoodRead Product Team. 95 | 96 | If such an insider threat existed and acted with this misconfigruatio, the resulting event could cause significant financial and reputational risk to IFA's Administrator, executive staff, and the agency overall. 97 | status: open 98 | characterizations: 99 | - origin: 100 | actors: 101 | - type: party 102 | actor-uuid: e7730080-71ce-4b20-bec4-84f33136fd58 103 | facets: 104 | - name: likelihood 105 | system: https://ifa.gov/division/ociso/sca 106 | value: low 107 | - name: impact 108 | system: https://ifa.gov/division/ociso/sca 109 | value: high 110 | deadline: "2023-06-23T17:00:00-04:00" 111 | remediations: 112 | - uuid: 4676b126-ba6d-40cc-9dc8-f2aa677b03ee 113 | lifecycle: planned 114 | title: 'IFA-GOODREAD-RISK1-RESPONSE: IFA GoodRead Prouct Team Response' 115 | description: The GoodRead Product Team does not have siginficant mitigations or compensating controls to counter this risk, even if likelihood is low. The IFA CISO has cited ongoing guidance that potential insider threat risks be prioritized above alternative categories of risk for this quarter. Additionally, there is sufficient budget and unallocated time for the GoodRead and Office of Information Technology system engineers to modify AwesomeCloud IAM roles on or before the next continuous monitoring cycle beginning in July 2023. The planned completion data is June 23, 2023. 116 | props: 117 | - name: type 118 | value: mitigate 119 | tasks: 120 | - uuid: a0bb457d-0d14-4a74-801a-ffc9bc4cd636 121 | type: milestone 122 | title: Completion of GoodRead Sprint Ending June 23, 2023 123 | description: The owner, ISSO, and product team of the GoodRead Project intend to complete the necessary development by June 23. 2023, the last day of the coinciding sprint. Whether or not the necessary development for mitigation is complete, the product team's project manager will write a brief at the end of the sprint to thw owner and ISSO of this system with the final status and determination of this work item in this sprint. 124 | timing: 125 | within-date-range: 126 | start: "2023-06-03T00:00:00-04:00" 127 | end: "2024-06-23T17:00:00-04:00" 128 | related-observations: 129 | - observation-uuid: 8807eb6e-0c05-43bc-8438-799739615e34 130 | poam-items: 131 | - uuid: e174dfb9-0ae3-4a8f-8e7c-081527b84337 132 | title: Update Django Framework Configuration to Disable Default Admin Panel 133 | description: Budget and technical staff are needed to re-design and re-implement a part of the GoodRead application's use of a web appplication programming framework to mitigate the risk of low privilege users directly modifying the database of this application. This application is a high-visibility service and integral to future operations of the IFA Office of Public Affairs and its staff. 134 | related-observations: 135 | - observation-uuid: 0c4de4fc-9bde-46af-b6fe-3b5e78194dcf 136 | related-risks: 137 | - risk-uuid: 401c15c9-ad6b-4d4a-a591-7d53a3abb3b6 138 | - uuid: 48c8368d-43ff-4736-9b28-64b1b1284c03 139 | title: GoodRead System Engineers Have Over-Privileged Access to Cloud Infrastructure Account 140 | description: Budget and technical staff allocation are available and designated to fix a misconfiguration of the IAM roles for members of the GoodRead Product Team in their AwesomeCloud account to implement least privilege as designed. 141 | related-observations: 142 | - observation-uuid: 8807eb6e-0c05-43bc-8438-799739615e34 143 | related-risks: 144 | - risk-uuid: 1c65d2d3-7735-47fa-8f68-a236744beab7 145 | -------------------------------------------------------------------------------- /roscal_lib/tests/ssp/yaml/oscal_leveraged-example_ssp.yaml: -------------------------------------------------------------------------------- 1 | system-security-plan: 2 | uuid: d197545f-353f-407b-9166-ebf959774c5a 3 | metadata: 4 | title: CSP IaaS System Security Plan 5 | last-modified: "2024-02-01T13:57:28.355446-04:00" 6 | version: "0.3" 7 | oscal-version: 1.1.2 8 | roles: 9 | - id: admin 10 | title: Administrator 11 | - id: customer 12 | title: External Customer 13 | - id: poc-for-customers 14 | title: Internal POC for Customers 15 | parties: 16 | - uuid: 11111111-0000-4000-9000-100000000001 17 | type: person 18 | remarks: Leveraged Authorization POC 19 | - uuid: 11111111-0000-4000-9000-100000000002 20 | type: person 21 | import-profile: 22 | href: '#6b45e2a5-b238-4752-ba12-cfd6ef2a83df' 23 | system-characteristics: 24 | system-ids: 25 | - id: csp_iaas_system 26 | system-name: Leveraged IaaS System 27 | description: "An example of three customers leveraging an authorized SaaS, which is running on an authorized IaaS.\n\n```\n\nCust-A Cust-B Cust-C\n | | |\n +---------+---------+\n |\n +-------------------+\n | Leveraging SaaS |\n +-------------------+\n |\n |\n +-------------------+\n | Leveraged IaaS |\n | this file |\n +-------------------+\n \n```\n\nIn this example, the IaaS SSP specifies customer responsibilities for certain controls.\n\nThe SaaS must address these for the control to be fully satisfied.\n\nThe SaaS provider may either implement these directly or pass the responsibility on to their customers. Both may be necessary.\n\nFor any given control, the Leveraged IaaS SSP must describe:\n\n1. HOW the IaaS is directly satisfying the control\n1. WHAT responsibilities are left for the Leveraging SaaS (or their customers) to implement.\n\n\nFor any given control, the Leveraging SaaS SSP must describe:\n\n1. WHAT is being inherited from the underlying IaaS\n1. HOW the SaaS is directly satisfying the control.\n1. WHAT responsibilities are left for the SaaS customers to implement. (The SaaS customers are Cust-A, B and C)\n" 28 | security-sensitivity-level: low 29 | system-information: 30 | information-types: 31 | - uuid: 11111111-0000-4000-9000-200000000000 32 | title: System and Network Monitoring 33 | description: This IaaS system handles information pertaining to audit events. 34 | categorizations: 35 | - system: https://doi.org/10.6028/NIST.SP.800-60v2r1 36 | information-type-ids: 37 | - C.3.5.8 38 | confidentiality-impact: 39 | base: fips-199-moderate 40 | selected: fips-199-low 41 | adjustment-justification: This impact has been adjusted to low as an example of how to perform this type of adjustment. 42 | integrity-impact: 43 | base: fips-199-moderate 44 | selected: fips-199-low 45 | adjustment-justification: This impact has been adjusted to low as an example of how to perform this type of adjustment. 46 | availability-impact: 47 | base: fips-199-moderate 48 | selected: fips-199-low 49 | adjustment-justification: This impact has been adjusted to low as an example of how to perform this type of adjustment. 50 | security-impact-level: 51 | security-objective-confidentiality: fips-199-low 52 | security-objective-integrity: fips-199-low 53 | security-objective-availability: fips-199-low 54 | status: 55 | state: operational 56 | authorization-boundary: 57 | description: The hardware and software supporting the virtualized infrastructure supporting the IaaS. 58 | remarks: Most system-characteristics content does not support the example, and is included to meet the minimum SSP syntax requirements. 59 | system-implementation: 60 | users: 61 | - uuid: 11111111-0000-4000-9000-200000000001 62 | role-ids: 63 | - admin 64 | authorized-privileges: 65 | - title: Administrator 66 | functions-performed: 67 | - Manages the components within the IaaS. 68 | components: 69 | - uuid: 11111111-0000-4000-9001-000000000001 70 | type: this-system 71 | title: This System 72 | description: |- 73 | This Leveraged IaaS. 74 | 75 | The entire system as depicted in the system authorization boundary 76 | status: 77 | state: operational 78 | - uuid: 11111111-0000-4000-9001-000000000002 79 | type: software 80 | title: Application 81 | description: |- 82 | An application within the IaaS, exposed to SaaS customers and their downstream customers. 83 | 84 | This Leveraged IaaS maintains aspects of the application. 85 | 86 | The Leveraging SaaS maintains aspects of their assigned portion of the application. 87 | 88 | The customers of the Leveraging SaaS maintain aspects of their sub-assigned portions of the application. 89 | props: 90 | - name: implementation-point 91 | value: internal 92 | status: 93 | state: operational 94 | responsible-roles: 95 | - role-id: admin 96 | party-uuids: 97 | - 11111111-0000-4000-9000-100000000001 98 | control-implementation: 99 | description: This is a collection of control responses. 100 | implemented-requirements: 101 | - uuid: 11111111-0000-4000-9009-002000000000 102 | control-id: ac-2 103 | set-parameters: 104 | - param-id: ac-2_prm_1 105 | values: 106 | - privileged and non-privileged 107 | statements: 108 | - statement-id: ac-2_stmt.a 109 | uuid: 11111111-0000-4000-9009-002001000000 110 | by-components: 111 | - component-uuid: 11111111-0000-4000-9001-000000000001 112 | uuid: 11111111-0000-4000-9009-002001001000 113 | description: |- 114 | Response for the \"This System\" component. 115 | 116 | Overall description of how \"This System\" satisfies AC-2, Part a. 117 | 118 | Response for the \"This System\" component. 119 | 120 | Overall description of how \"This System\" satisfies AC-2, Part a. 121 | 122 | Response for the \"This System\" component. 123 | 124 | Overall description of how \"This System\" satisfies AC-2, Part a. 125 | 126 | Response for the \"This System\" component. 127 | 128 | Overall description of how \"This System\" satisfies AC-2, Part a. 129 | export: 130 | description: Optional description about what is being exported. 131 | provided: 132 | - uuid: 11111111-0000-4000-9009-002001001001 133 | description: Consumer-appropriate description of what a leveraging system may inherite from THIS SYSTEM in the context of satisfying satisfaction of AC-2, part a. 134 | responsible-roles: 135 | - role-id: poc-for-customers 136 | party-uuids: 137 | - 11111111-0000-4000-9000-100000000001 138 | responsibilities: 139 | - uuid: 11111111-0000-4000-9009-002001001002 140 | provided-uuid: 11111111-0000-4000-9009-002001001001 141 | description: |- 142 | Leveraging system's responsibilities with respect to inheriting this capability. 143 | 144 | In the context of the application component in satisfaction of AC-2, part a. 145 | responsible-roles: 146 | - role-id: customer 147 | party-uuids: 148 | - 11111111-0000-4000-9000-100000000002 149 | - component-uuid: 11111111-0000-4000-9001-000000000002 150 | uuid: 11111111-0000-4000-9009-002001002000 151 | description: Describes how the application satisfies AC-2, Part a. 152 | export: 153 | description: Optional description about what is being exported. 154 | provided: 155 | - uuid: 11111111-0000-4000-9009-002001002001 156 | description: |- 157 | Consumer-appropriate description of what may be inherited. 158 | 159 | In the context of the application component in satisfaction of AC-2, part a. 160 | responsible-roles: 161 | - role-id: poc-for-customers 162 | party-uuids: 163 | - 11111111-0000-4000-9000-100000000001 164 | responsibilities: 165 | - uuid: 11111111-0000-4000-9009-002001002002 166 | provided-uuid: 11111111-0000-4000-9009-002001002001 167 | description: |- 168 | Leveraging system's responsibilities with respect to inheriting this capability. 169 | 170 | In the context of the application component in satisfaction of AC-2, part a. 171 | responsible-roles: 172 | - role-id: customer 173 | party-uuids: 174 | - 11111111-0000-4000-9000-100000000002 175 | remarks: 'a. Identifies and selects the following types of information system accounts to support organizational missions/business functions: [Assignment: privileged and non-privileged];' 176 | remarks: |- 177 | The organization: 178 | 179 | a. Identifies and selects the following types of information system accounts to support organizational missions/business functions: [Assignment: organization-defined information system account types]; 180 | 181 | b. Assigns account managers for information system accounts; 182 | 183 | c. Establishes conditions for group and role membership; 184 | 185 | d. through j. omitted 186 | back-matter: 187 | resources: 188 | - uuid: 11111111-0000-4000-9999-000000000001 189 | rlinks: 190 | - href: ./attachments/IaaS_ac_proc.docx 191 | - uuid: 6b45e2a5-b238-4752-ba12-cfd6ef2a83df 192 | description: 'NIST Special Publication 800-53 Revision 4: Low Baseline Profile' 193 | rlinks: 194 | - href: ../../../nist.gov/SP800-53/rev4/xml/NIST_SP-800-53_rev4_LOW-baseline_profile.xml 195 | media-type: application/oscal.catalog+xml 196 | - href: ../../../nist.gov/SP800-53/rev4/json/NIST_SP-800-53_rev4_LOW-baseline_profile.json 197 | media-type: application/oscal.catalog+json 198 | - href: ../../../nist.gov/SP800-53/rev4/yaml/NIST_SP-800-53_rev4_LOW-baseline_profile.yaml 199 | media-type: application/oscal.catalog+yaml 200 | -------------------------------------------------------------------------------- /roscal_lib/tests/malformed/uuid.yaml: -------------------------------------------------------------------------------- 1 | profile: 2 | uuid: wrong 3 | metadata: 4 | title: NIST Special Publication 800-53 Revision 5.1.1 HIGH IMPACT BASELINE 5 | last-modified: "2023-12-04T14:55:00.000000-04:00" 6 | version: 5.1.1+u2 7 | oscal-version: 1.1.1 8 | roles: 9 | - id: creator 10 | title: Document Creator 11 | - id: contact 12 | title: Contact 13 | parties: 14 | - uuid: c748c806-1d77-4695-bb40-e117b2afa82e 15 | type: organization 16 | name: Joint Task Force, Transformation Initiative 17 | email-addresses: 18 | - sec-cert@nist.gov 19 | addresses: 20 | - addr-lines: 21 | - National Institute of Standards and Technology 22 | - 'Attn: Computer Security Division' 23 | - Information Technology Laboratory 24 | - 100 Bureau Drive (Mail Stop 8930) 25 | city: Gaithersburg 26 | state: MD 27 | postal-code: 20899-8930 28 | responsible-parties: 29 | - role-id: creator 30 | party-uuids: 31 | - c748c806-1d77-4695-bb40-e117b2afa82e 32 | - role-id: contact 33 | party-uuids: 34 | - c748c806-1d77-4695-bb40-e117b2afa82e 35 | imports: 36 | - href: '#84cbf061-eb87-4ec1-8112-1f529232e907' 37 | include-controls: 38 | - with-ids: 39 | - ac-1 40 | - ac-2 41 | - ac-2.1 42 | - ac-2.2 43 | - ac-2.3 44 | - ac-2.4 45 | - ac-2.5 46 | - ac-2.11 47 | - ac-2.12 48 | - ac-2.13 49 | - ac-3 50 | - ac-4 51 | - ac-4.4 52 | - ac-5 53 | - ac-6 54 | - ac-6.1 55 | - ac-6.2 56 | - ac-6.3 57 | - ac-6.5 58 | - ac-6.7 59 | - ac-6.9 60 | - ac-6.10 61 | - ac-7 62 | - ac-8 63 | - ac-10 64 | - ac-11 65 | - ac-11.1 66 | - ac-12 67 | - ac-14 68 | - ac-17 69 | - ac-17.1 70 | - ac-17.2 71 | - ac-17.3 72 | - ac-17.4 73 | - ac-18 74 | - ac-18.1 75 | - ac-18.3 76 | - ac-18.4 77 | - ac-18.5 78 | - ac-19 79 | - ac-19.5 80 | - ac-20 81 | - ac-20.1 82 | - ac-20.2 83 | - ac-21 84 | - ac-22 85 | - at-1 86 | - at-2 87 | - at-2.2 88 | - at-2.3 89 | - at-3 90 | - at-4 91 | - au-1 92 | - au-2 93 | - au-3 94 | - au-3.1 95 | - au-4 96 | - au-5 97 | - au-5.1 98 | - au-5.2 99 | - au-6 100 | - au-6.1 101 | - au-6.3 102 | - au-6.5 103 | - au-6.6 104 | - au-7 105 | - au-7.1 106 | - au-8 107 | - au-9 108 | - au-9.2 109 | - au-9.3 110 | - au-9.4 111 | - au-10 112 | - au-11 113 | - au-12 114 | - au-12.1 115 | - au-12.3 116 | - ca-1 117 | - ca-2 118 | - ca-2.1 119 | - ca-2.2 120 | - ca-3 121 | - ca-3.6 122 | - ca-5 123 | - ca-6 124 | - ca-7 125 | - ca-7.1 126 | - ca-7.4 127 | - ca-8 128 | - ca-8.1 129 | - ca-9 130 | - cm-1 131 | - cm-2 132 | - cm-2.2 133 | - cm-2.3 134 | - cm-2.7 135 | - cm-3 136 | - cm-3.1 137 | - cm-3.2 138 | - cm-3.4 139 | - cm-3.6 140 | - cm-4 141 | - cm-4.1 142 | - cm-4.2 143 | - cm-5 144 | - cm-5.1 145 | - cm-6 146 | - cm-6.1 147 | - cm-6.2 148 | - cm-7 149 | - cm-7.1 150 | - cm-7.2 151 | - cm-7.5 152 | - cm-8 153 | - cm-8.1 154 | - cm-8.2 155 | - cm-8.3 156 | - cm-8.4 157 | - cm-9 158 | - cm-10 159 | - cm-11 160 | - cm-12 161 | - cm-12.1 162 | - cp-1 163 | - cp-2 164 | - cp-2.1 165 | - cp-2.2 166 | - cp-2.3 167 | - cp-2.5 168 | - cp-2.8 169 | - cp-3 170 | - cp-3.1 171 | - cp-4 172 | - cp-4.1 173 | - cp-4.2 174 | - cp-6 175 | - cp-6.1 176 | - cp-6.2 177 | - cp-6.3 178 | - cp-7 179 | - cp-7.1 180 | - cp-7.2 181 | - cp-7.3 182 | - cp-7.4 183 | - cp-8 184 | - cp-8.1 185 | - cp-8.2 186 | - cp-8.3 187 | - cp-8.4 188 | - cp-9 189 | - cp-9.1 190 | - cp-9.2 191 | - cp-9.3 192 | - cp-9.5 193 | - cp-9.8 194 | - cp-10 195 | - cp-10.2 196 | - cp-10.4 197 | - ia-1 198 | - ia-2 199 | - ia-2.1 200 | - ia-2.2 201 | - ia-2.5 202 | - ia-2.8 203 | - ia-2.12 204 | - ia-3 205 | - ia-4 206 | - ia-4.4 207 | - ia-5 208 | - ia-5.1 209 | - ia-5.2 210 | - ia-5.6 211 | - ia-6 212 | - ia-7 213 | - ia-8 214 | - ia-8.1 215 | - ia-8.2 216 | - ia-8.4 217 | - ia-11 218 | - ia-12 219 | - ia-12.2 220 | - ia-12.3 221 | - ia-12.4 222 | - ia-12.5 223 | - ir-1 224 | - ir-2 225 | - ir-2.1 226 | - ir-2.2 227 | - ir-3 228 | - ir-3.2 229 | - ir-4 230 | - ir-4.1 231 | - ir-4.4 232 | - ir-4.11 233 | - ir-5 234 | - ir-5.1 235 | - ir-6 236 | - ir-6.1 237 | - ir-6.3 238 | - ir-7 239 | - ir-7.1 240 | - ir-8 241 | - ma-1 242 | - ma-2 243 | - ma-2.2 244 | - ma-3 245 | - ma-3.1 246 | - ma-3.2 247 | - ma-3.3 248 | - ma-4 249 | - ma-4.3 250 | - ma-5 251 | - ma-5.1 252 | - ma-6 253 | - mp-1 254 | - mp-2 255 | - mp-3 256 | - mp-4 257 | - mp-5 258 | - mp-6 259 | - mp-6.1 260 | - mp-6.2 261 | - mp-6.3 262 | - mp-7 263 | - pe-1 264 | - pe-2 265 | - pe-3 266 | - pe-3.1 267 | - pe-4 268 | - pe-5 269 | - pe-6 270 | - pe-6.1 271 | - pe-6.4 272 | - pe-8 273 | - pe-8.1 274 | - pe-9 275 | - pe-10 276 | - pe-11 277 | - pe-11.1 278 | - pe-12 279 | - pe-13 280 | - pe-13.1 281 | - pe-13.2 282 | - pe-14 283 | - pe-15 284 | - pe-15.1 285 | - pe-16 286 | - pe-17 287 | - pe-18 288 | - pl-1 289 | - pl-2 290 | - pl-4 291 | - pl-4.1 292 | - pl-8 293 | - pl-10 294 | - pl-11 295 | - ps-1 296 | - ps-2 297 | - ps-3 298 | - ps-4 299 | - ps-4.2 300 | - ps-5 301 | - ps-6 302 | - ps-7 303 | - ps-8 304 | - ps-9 305 | - ra-1 306 | - ra-2 307 | - ra-3 308 | - ra-3.1 309 | - ra-5 310 | - ra-5.2 311 | - ra-5.4 312 | - ra-5.5 313 | - ra-5.11 314 | - ra-7 315 | - ra-9 316 | - sa-1 317 | - sa-2 318 | - sa-3 319 | - sa-4 320 | - sa-4.1 321 | - sa-4.2 322 | - sa-4.5 323 | - sa-4.9 324 | - sa-4.10 325 | - sa-5 326 | - sa-8 327 | - sa-9 328 | - sa-9.2 329 | - sa-10 330 | - sa-11 331 | - sa-15 332 | - sa-15.3 333 | - sa-16 334 | - sa-17 335 | - sa-21 336 | - sa-22 337 | - sc-1 338 | - sc-2 339 | - sc-3 340 | - sc-4 341 | - sc-5 342 | - sc-7 343 | - sc-7.3 344 | - sc-7.4 345 | - sc-7.5 346 | - sc-7.7 347 | - sc-7.8 348 | - sc-7.18 349 | - sc-7.21 350 | - sc-8 351 | - sc-8.1 352 | - sc-10 353 | - sc-12 354 | - sc-12.1 355 | - sc-13 356 | - sc-15 357 | - sc-17 358 | - sc-18 359 | - sc-20 360 | - sc-21 361 | - sc-22 362 | - sc-23 363 | - sc-24 364 | - sc-28 365 | - sc-28.1 366 | - sc-39 367 | - si-1 368 | - si-2 369 | - si-2.2 370 | - si-3 371 | - si-4 372 | - si-4.2 373 | - si-4.4 374 | - si-4.5 375 | - si-4.10 376 | - si-4.12 377 | - si-4.14 378 | - si-4.20 379 | - si-4.22 380 | - si-5 381 | - si-5.1 382 | - si-6 383 | - si-7 384 | - si-7.1 385 | - si-7.2 386 | - si-7.5 387 | - si-7.7 388 | - si-7.15 389 | - si-8 390 | - si-8.2 391 | - si-10 392 | - si-11 393 | - si-12 394 | - si-16 395 | - sr-1 396 | - sr-2 397 | - sr-2.1 398 | - sr-3 399 | - sr-5 400 | - sr-6 401 | - sr-8 402 | - sr-9 403 | - sr-9.1 404 | - sr-10 405 | - sr-11 406 | - sr-11.1 407 | - sr-11.2 408 | - sr-12 409 | merge: 410 | as-is: true 411 | back-matter: 412 | resources: 413 | - uuid: 84cbf061-eb87-4ec1-8112-1f529232e907 414 | description: 'NIST Special Publication 800-53 Revision 5: Security and Privacy Controls for Federal Information Systems and Organizations' 415 | rlinks: 416 | - href: ../../../../nist.gov/SP800-53/rev5/xml/NIST_SP-800-53_rev5_catalog.xml 417 | media-type: application/oscal.catalog+xml 418 | - href: ../../../../nist.gov/SP800-53/rev5/json/NIST_SP-800-53_rev5_catalog.json 419 | media-type: application/oscal.catalog+json 420 | - href: ../../../../nist.gov/SP800-53/rev5/yaml/NIST_SP-800-53_rev5_catalog.yaml 421 | media-type: application/oscal.catalog+yaml -------------------------------------------------------------------------------- /roscal_lib/tests/malformed/datetime.yaml: -------------------------------------------------------------------------------- 1 | profile: 2 | uuid: cd073316-7c58-4c34-9f5c-9eb5aa722683 3 | metadata: 4 | title: NIST Special Publication 800-53 Revision 5.1.1 HIGH IMPACT BASELINE 5 | last-modified: "2023-12-04T14:55:00" 6 | version: 5.1.1+u2 7 | oscal-version: 1.1.1 8 | roles: 9 | - id: creator 10 | title: Document Creator 11 | - id: contact 12 | title: Contact 13 | parties: 14 | - uuid: c748c806-1d77-4695-bb40-e117b2afa82e 15 | type: organization 16 | name: Joint Task Force, Transformation Initiative 17 | email-addresses: 18 | - sec-cert@nist.gov 19 | addresses: 20 | - addr-lines: 21 | - National Institute of Standards and Technology 22 | - 'Attn: Computer Security Division' 23 | - Information Technology Laboratory 24 | - 100 Bureau Drive (Mail Stop 8930) 25 | city: Gaithersburg 26 | state: MD 27 | postal-code: 20899-8930 28 | responsible-parties: 29 | - role-id: creator 30 | party-uuids: 31 | - c748c806-1d77-4695-bb40-e117b2afa82e 32 | - role-id: contact 33 | party-uuids: 34 | - c748c806-1d77-4695-bb40-e117b2afa82e 35 | imports: 36 | - href: '#84cbf061-eb87-4ec1-8112-1f529232e907' 37 | include-controls: 38 | - with-ids: 39 | - ac-1 40 | - ac-2 41 | - ac-2.1 42 | - ac-2.2 43 | - ac-2.3 44 | - ac-2.4 45 | - ac-2.5 46 | - ac-2.11 47 | - ac-2.12 48 | - ac-2.13 49 | - ac-3 50 | - ac-4 51 | - ac-4.4 52 | - ac-5 53 | - ac-6 54 | - ac-6.1 55 | - ac-6.2 56 | - ac-6.3 57 | - ac-6.5 58 | - ac-6.7 59 | - ac-6.9 60 | - ac-6.10 61 | - ac-7 62 | - ac-8 63 | - ac-10 64 | - ac-11 65 | - ac-11.1 66 | - ac-12 67 | - ac-14 68 | - ac-17 69 | - ac-17.1 70 | - ac-17.2 71 | - ac-17.3 72 | - ac-17.4 73 | - ac-18 74 | - ac-18.1 75 | - ac-18.3 76 | - ac-18.4 77 | - ac-18.5 78 | - ac-19 79 | - ac-19.5 80 | - ac-20 81 | - ac-20.1 82 | - ac-20.2 83 | - ac-21 84 | - ac-22 85 | - at-1 86 | - at-2 87 | - at-2.2 88 | - at-2.3 89 | - at-3 90 | - at-4 91 | - au-1 92 | - au-2 93 | - au-3 94 | - au-3.1 95 | - au-4 96 | - au-5 97 | - au-5.1 98 | - au-5.2 99 | - au-6 100 | - au-6.1 101 | - au-6.3 102 | - au-6.5 103 | - au-6.6 104 | - au-7 105 | - au-7.1 106 | - au-8 107 | - au-9 108 | - au-9.2 109 | - au-9.3 110 | - au-9.4 111 | - au-10 112 | - au-11 113 | - au-12 114 | - au-12.1 115 | - au-12.3 116 | - ca-1 117 | - ca-2 118 | - ca-2.1 119 | - ca-2.2 120 | - ca-3 121 | - ca-3.6 122 | - ca-5 123 | - ca-6 124 | - ca-7 125 | - ca-7.1 126 | - ca-7.4 127 | - ca-8 128 | - ca-8.1 129 | - ca-9 130 | - cm-1 131 | - cm-2 132 | - cm-2.2 133 | - cm-2.3 134 | - cm-2.7 135 | - cm-3 136 | - cm-3.1 137 | - cm-3.2 138 | - cm-3.4 139 | - cm-3.6 140 | - cm-4 141 | - cm-4.1 142 | - cm-4.2 143 | - cm-5 144 | - cm-5.1 145 | - cm-6 146 | - cm-6.1 147 | - cm-6.2 148 | - cm-7 149 | - cm-7.1 150 | - cm-7.2 151 | - cm-7.5 152 | - cm-8 153 | - cm-8.1 154 | - cm-8.2 155 | - cm-8.3 156 | - cm-8.4 157 | - cm-9 158 | - cm-10 159 | - cm-11 160 | - cm-12 161 | - cm-12.1 162 | - cp-1 163 | - cp-2 164 | - cp-2.1 165 | - cp-2.2 166 | - cp-2.3 167 | - cp-2.5 168 | - cp-2.8 169 | - cp-3 170 | - cp-3.1 171 | - cp-4 172 | - cp-4.1 173 | - cp-4.2 174 | - cp-6 175 | - cp-6.1 176 | - cp-6.2 177 | - cp-6.3 178 | - cp-7 179 | - cp-7.1 180 | - cp-7.2 181 | - cp-7.3 182 | - cp-7.4 183 | - cp-8 184 | - cp-8.1 185 | - cp-8.2 186 | - cp-8.3 187 | - cp-8.4 188 | - cp-9 189 | - cp-9.1 190 | - cp-9.2 191 | - cp-9.3 192 | - cp-9.5 193 | - cp-9.8 194 | - cp-10 195 | - cp-10.2 196 | - cp-10.4 197 | - ia-1 198 | - ia-2 199 | - ia-2.1 200 | - ia-2.2 201 | - ia-2.5 202 | - ia-2.8 203 | - ia-2.12 204 | - ia-3 205 | - ia-4 206 | - ia-4.4 207 | - ia-5 208 | - ia-5.1 209 | - ia-5.2 210 | - ia-5.6 211 | - ia-6 212 | - ia-7 213 | - ia-8 214 | - ia-8.1 215 | - ia-8.2 216 | - ia-8.4 217 | - ia-11 218 | - ia-12 219 | - ia-12.2 220 | - ia-12.3 221 | - ia-12.4 222 | - ia-12.5 223 | - ir-1 224 | - ir-2 225 | - ir-2.1 226 | - ir-2.2 227 | - ir-3 228 | - ir-3.2 229 | - ir-4 230 | - ir-4.1 231 | - ir-4.4 232 | - ir-4.11 233 | - ir-5 234 | - ir-5.1 235 | - ir-6 236 | - ir-6.1 237 | - ir-6.3 238 | - ir-7 239 | - ir-7.1 240 | - ir-8 241 | - ma-1 242 | - ma-2 243 | - ma-2.2 244 | - ma-3 245 | - ma-3.1 246 | - ma-3.2 247 | - ma-3.3 248 | - ma-4 249 | - ma-4.3 250 | - ma-5 251 | - ma-5.1 252 | - ma-6 253 | - mp-1 254 | - mp-2 255 | - mp-3 256 | - mp-4 257 | - mp-5 258 | - mp-6 259 | - mp-6.1 260 | - mp-6.2 261 | - mp-6.3 262 | - mp-7 263 | - pe-1 264 | - pe-2 265 | - pe-3 266 | - pe-3.1 267 | - pe-4 268 | - pe-5 269 | - pe-6 270 | - pe-6.1 271 | - pe-6.4 272 | - pe-8 273 | - pe-8.1 274 | - pe-9 275 | - pe-10 276 | - pe-11 277 | - pe-11.1 278 | - pe-12 279 | - pe-13 280 | - pe-13.1 281 | - pe-13.2 282 | - pe-14 283 | - pe-15 284 | - pe-15.1 285 | - pe-16 286 | - pe-17 287 | - pe-18 288 | - pl-1 289 | - pl-2 290 | - pl-4 291 | - pl-4.1 292 | - pl-8 293 | - pl-10 294 | - pl-11 295 | - ps-1 296 | - ps-2 297 | - ps-3 298 | - ps-4 299 | - ps-4.2 300 | - ps-5 301 | - ps-6 302 | - ps-7 303 | - ps-8 304 | - ps-9 305 | - ra-1 306 | - ra-2 307 | - ra-3 308 | - ra-3.1 309 | - ra-5 310 | - ra-5.2 311 | - ra-5.4 312 | - ra-5.5 313 | - ra-5.11 314 | - ra-7 315 | - ra-9 316 | - sa-1 317 | - sa-2 318 | - sa-3 319 | - sa-4 320 | - sa-4.1 321 | - sa-4.2 322 | - sa-4.5 323 | - sa-4.9 324 | - sa-4.10 325 | - sa-5 326 | - sa-8 327 | - sa-9 328 | - sa-9.2 329 | - sa-10 330 | - sa-11 331 | - sa-15 332 | - sa-15.3 333 | - sa-16 334 | - sa-17 335 | - sa-21 336 | - sa-22 337 | - sc-1 338 | - sc-2 339 | - sc-3 340 | - sc-4 341 | - sc-5 342 | - sc-7 343 | - sc-7.3 344 | - sc-7.4 345 | - sc-7.5 346 | - sc-7.7 347 | - sc-7.8 348 | - sc-7.18 349 | - sc-7.21 350 | - sc-8 351 | - sc-8.1 352 | - sc-10 353 | - sc-12 354 | - sc-12.1 355 | - sc-13 356 | - sc-15 357 | - sc-17 358 | - sc-18 359 | - sc-20 360 | - sc-21 361 | - sc-22 362 | - sc-23 363 | - sc-24 364 | - sc-28 365 | - sc-28.1 366 | - sc-39 367 | - si-1 368 | - si-2 369 | - si-2.2 370 | - si-3 371 | - si-4 372 | - si-4.2 373 | - si-4.4 374 | - si-4.5 375 | - si-4.10 376 | - si-4.12 377 | - si-4.14 378 | - si-4.20 379 | - si-4.22 380 | - si-5 381 | - si-5.1 382 | - si-6 383 | - si-7 384 | - si-7.1 385 | - si-7.2 386 | - si-7.5 387 | - si-7.7 388 | - si-7.15 389 | - si-8 390 | - si-8.2 391 | - si-10 392 | - si-11 393 | - si-12 394 | - si-16 395 | - sr-1 396 | - sr-2 397 | - sr-2.1 398 | - sr-3 399 | - sr-5 400 | - sr-6 401 | - sr-8 402 | - sr-9 403 | - sr-9.1 404 | - sr-10 405 | - sr-11 406 | - sr-11.1 407 | - sr-11.2 408 | - sr-12 409 | merge: 410 | as-is: true 411 | back-matter: 412 | resources: 413 | - uuid: 84cbf061-eb87-4ec1-8112-1f529232e907 414 | description: 'NIST Special Publication 800-53 Revision 5: Security and Privacy Controls for Federal Information Systems and Organizations' 415 | rlinks: 416 | - href: ../../../../nist.gov/SP800-53/rev5/xml/NIST_SP-800-53_rev5_catalog.xml 417 | media-type: application/oscal.catalog+xml 418 | - href: ../../../../nist.gov/SP800-53/rev5/json/NIST_SP-800-53_rev5_catalog.json 419 | media-type: application/oscal.catalog+json 420 | - href: ../../../../nist.gov/SP800-53/rev5/yaml/NIST_SP-800-53_rev5_catalog.yaml 421 | media-type: application/oscal.catalog+yaml --------------------------------------------------------------------------------