Skip to main content

cedar_policy_cli/command/
validate.rs

1/*
2 * Copyright Cedar Contributors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      https://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17use crate::{CedarExitCode, PoliciesArgs, SchemaArgs};
18use cedar_policy::Validator;
19use clap::{Args, ValueEnum};
20use miette::Report;
21
22#[derive(Args, Debug)]
23pub struct ValidateArgs {
24    /// Schema args (incorporated by reference)
25    #[command(flatten)]
26    pub schema: SchemaArgs,
27    /// Policies args (incorporated by reference)
28    #[command(flatten)]
29    pub policies: PoliciesArgs,
30    /// Report a validation failure for non-fatal warnings
31    #[arg(long)]
32    pub deny_warnings: bool,
33    /// Validate the policy using this mode.
34    /// The options `permissive` and `partial` are experimental
35    /// and will cause the CLI to exit if it was not built with the
36    /// experimental feature `permissive-validate` and `partial-validate`, respectively, enabled.
37    #[arg(long, value_enum, default_value_t = ValidationMode::Strict)]
38    pub validation_mode: ValidationMode,
39    /// Validate the policy at this level.
40    #[arg(long)]
41    pub level: Option<u32>,
42}
43
44#[derive(Debug, Clone, Copy, ValueEnum)]
45pub enum ValidationMode {
46    /// Strict validation
47    Strict,
48    /// Permissive validation
49    Permissive,
50    /// Partial validation
51    Partial,
52}
53
54pub fn validate(args: &ValidateArgs) -> CedarExitCode {
55    let mode = match args.validation_mode {
56        ValidationMode::Strict => cedar_policy::ValidationMode::Strict,
57        ValidationMode::Permissive => {
58            #[cfg(not(feature = "permissive-validate"))]
59            {
60                eprintln!("Error: arguments include the experimental option `--validation-mode permissive`, but this executable was not built with `permissive-validate` experimental feature enabled");
61                return CedarExitCode::Failure;
62            }
63            #[cfg(feature = "permissive-validate")]
64            cedar_policy::ValidationMode::Permissive
65        }
66        ValidationMode::Partial => {
67            #[cfg(not(feature = "partial-validate"))]
68            {
69                eprintln!("Error: arguments include the experimental option `--validation-mode partial`, but this executable was not built with `partial-validate` experimental feature enabled");
70                return CedarExitCode::Failure;
71            }
72            #[cfg(feature = "partial-validate")]
73            cedar_policy::ValidationMode::Partial
74        }
75    };
76
77    let pset = match args.policies.get_policy_set() {
78        Ok(pset) => pset,
79        Err(e) => {
80            println!("{e:?}");
81            return CedarExitCode::Failure;
82        }
83    };
84
85    let schema = match args.schema.get_schema() {
86        Ok(schema) => schema,
87        Err(e) => {
88            println!("{e:?}");
89            return CedarExitCode::Failure;
90        }
91    };
92
93    let validator = Validator::new(schema);
94
95    let result = if let Some(level) = args.level {
96        validator.validate_with_level(&pset, mode, level)
97    } else {
98        validator.validate(&pset, mode)
99    };
100
101    if !result.validation_passed()
102        || (args.deny_warnings && !result.validation_passed_without_warnings())
103    {
104        println!(
105            "{:?}",
106            Report::new(result).wrap_err("policy set validation failed")
107        );
108        CedarExitCode::ValidationFailure
109    } else {
110        println!(
111            "{:?}",
112            Report::new(result).wrap_err("policy set validation passed")
113        );
114        CedarExitCode::Success
115    }
116}