Skip to main content

cedar_policy_cli/command/
new.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 std::path::Path;
18
19use clap::Args;
20use miette::{IntoDiagnostic, Result};
21
22use crate::CedarExitCode;
23
24#[derive(Args, Debug)]
25pub struct NewArgs {
26    /// Name of the Cedar project
27    #[arg(short, long, value_name = "DIR")]
28    pub name: String,
29}
30
31pub fn new(args: &NewArgs) -> CedarExitCode {
32    if let Err(err) = new_inner(args) {
33        println!("{err:?}");
34        CedarExitCode::Failure
35    } else {
36        CedarExitCode::Success
37    }
38}
39
40fn new_inner(args: &NewArgs) -> Result<()> {
41    let dir = &std::env::current_dir().into_diagnostic()?.join(&args.name);
42    std::fs::create_dir(dir).into_diagnostic()?;
43    let schema_path = dir.join("schema.cedarschema.json");
44    let policy_path = dir.join("policy.cedar");
45    let entities_path = dir.join("entities.json");
46    generate_schema(&schema_path)?;
47    generate_policy(&policy_path)?;
48    generate_entities(&entities_path)
49}
50
51/// Write a schema (in JSON format) to `path`
52fn generate_schema(path: &Path) -> Result<()> {
53    std::fs::write(
54        path,
55        serde_json::to_string_pretty(&serde_json::json!(
56        {
57            "": {
58                "entityTypes": {
59                    "A": {
60                        "memberOfTypes": [
61                            "B"
62                        ]
63                    },
64                    "B": {
65                        "memberOfTypes": []
66                    },
67                    "C": {
68                        "memberOfTypes": []
69                    }
70                },
71                "actions": {
72                    "action": {
73                        "appliesTo": {
74                            "resourceTypes": [
75                                "C"
76                            ],
77                            "principalTypes": [
78                                "A",
79                                "B"
80                            ]
81                        }
82                    }
83                }
84            }
85        }))
86        .into_diagnostic()?,
87    )
88    .into_diagnostic()
89}
90
91fn generate_policy(path: &Path) -> Result<()> {
92    std::fs::write(
93        path,
94        r#"permit (
95  principal in A::"a",
96  action == Action::"action",
97  resource == C::"c"
98) when { true };
99"#,
100    )
101    .into_diagnostic()
102}
103
104fn generate_entities(path: &Path) -> Result<()> {
105    std::fs::write(
106        path,
107        serde_json::to_string_pretty(&serde_json::json!(
108        [
109            {
110                "uid": { "type": "A", "id": "a"} ,
111                "attrs": {},
112                "parents": [{"type": "B", "id": "b"}]
113            },
114            {
115                "uid": { "type": "B", "id": "b"} ,
116                "attrs": {},
117                "parents": []
118            },
119            {
120                "uid": { "type": "C", "id": "c"} ,
121                "attrs": {},
122                "parents": []
123            }
124        ]))
125        .into_diagnostic()?,
126    )
127    .into_diagnostic()
128}