LeChatP/RootAsRole

Maintaining and/or Deprecating XML to switch to modern config file.

Closed this issue · 3 comments

Is your feature request related to a problem? Please describe.
Config file could be manually problematic.

Describe the solution you'd like
A JSON5 file configuration. and being schema validated through

Describe alternatives you've considered
Yaml and JSON does not really solve usability issue, so JSON5 may be a good answer. KDL is promising but maybe less compatible than json5.

Additional context
This is following many conversations in reddit and on linuxFR.

To see what it could look like between two configuration in XML and JSON5, admitting that schema validation is externalized...

<?xml version="1.0" encoding="UTF-8"?>
<rootasrole version="3.0.0-alpha.3" timestamp-type="Global" timestamp-timeout="300">
  <options>
    <path>/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin</path>
    <env-keep>HOME,USER,LOGNAME,COLORS,DISPLAY,HOSTNAME,KRB5CCNAME,LS_COLORS,PS1,PS2,XAUTHORY,XAUTHORIZATION,XDG_CURRENT_DESKTOP</env-keep>
    <env-check>COLORTERM,LANG,LANGUAGE,LC_*,LINGUAS,TERM,TZ</env-check>
    <allow-root enforce="false" />
    <allow-bounding enforce="false" />
    <wildcard-denied>;&amp;|</wildcard-denied>
  </options>
  <roles>
    <role name="r_test_A">
      <actors>
        <user name="userA" />
        <group names="groupA,groupB" />
      </actors>
      <task id="rA_t1" setuser="root" setgroups="root,groupA" capabilities="CAP_SYS_ADMIN,CAP_NET_RAW">
        <command>/bin/ls</command>
        <purpose>do a command</purpose>
        <options>
          <path>/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin</path>
          <env-keep>HOME,USER,LOGNAME,COLORS,DISPLAY,HOSTNAME,KRB5CCNAME,LS_COLORS,PS1,PS2,XAUTHORY,XAUTHORIZATION,XDG_CURRENT_DESKTOP</env-keep>
          <env-check>COLORTERM,LANG,LANGUAGE,LC_*,LINGUAS,TERM,TZ</env-check>
          <allow-root enforce="false" />
          <allow-bounding enforce="false" />
          <wildcard-denied>;&amp;|</wildcard-denied>
        </options>
      </task>
      <options>
        <path>/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin</path>
        <env-keep>HOME,USER,LOGNAME,COLORS,DISPLAY,HOSTNAME,KRB5CCNAME,LS_COLORS,PS1,PS2,XAUTHORY,XAUTHORIZATION,XDG_CURRENT_DESKTOP</env-keep>
        <env-check>COLORTERM,LANG,LANGUAGE,LC_*,LINGUAS,TERM,TZ</env-check>
        <allow-root enforce="false" />
        <allow-bounding enforce="false" />
        <wildcard-denied>;&amp;|</wildcard-denied>
      </options>
    </role>

  </roles>
</rootasrole>
{
  version: "3.0.0-alpha.3",
  timestamp: {
    type: "Global",
    timestamp: 300
  },
  options: { // global options
    path: "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin",
    env_whitelist: "HOME,USER,LOGNAME,COLORS,DISPLAY,HOSTNAME,KRB5CCNAME,LS_COLORS,PS1,PS2,XAUTHORY,XAUTHORIZATION,XDG_CURRENT_DESKTOP",
    env_checklist: "COLORTERM,LANG,LANGUAGE,LC_*,LINGUAS,TERM,TZ",
    wildcard_denied: ";&|",
    allow_root: true,
    disable_bounding: false
  },
  roles: [
    {
      incompatible_with: [
        "r_test_C"
      ],
      denied_capabilities: "CAP_SYS_ADMIN,CAP_NET_BIND_SERVICE",
      parents_roles: [
        "r_test_B"
      ],
      name: "r_test_A",
      actors: {
        users: [
          "userA"
        ],
        groups: [
          "groupA,groupB",
          "groupC"
        ]
      },
      tasks: [
        {
          id: "rA_t1",
          purpose: "do a command",
          setuid: "root",
          setgid: "root,groupA",
          capabilities: "CAP_SYS_ADMIN,CAP_NET_RAW",
          commands: [
            "/bin/ls"
          ],
          options: { // task options
            path: "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin",
            env_whitelist: "HOME,USER,LOGNAME,COLORS,DISPLAY,HOSTNAME,KRB5CCNAME,LS_COLORS,PS1,PS2,XAUTHORY,XAUTHORIZATION,XDG_CURRENT_DESKTOP",
            env_checklist: "COLORTERM,LANG,LANGUAGE,LC_*,LINGUAS,TERM,TZ",
            wildcard_denied: ";&|",
            allow_root: true,
            disable_bounding: false
          }
        }
      ],
      options: { //role options
        path: "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin",
        env_whitelist: "HOME,USER,LOGNAME,COLORS,DISPLAY,HOSTNAME,KRB5CCNAME,LS_COLORS,PS1,PS2,XAUTHORY,XAUTHORIZATION,XDG_CURRENT_DESKTOP",
        env_checklist: "COLORTERM,LANG,LANGUAGE,LC_*,LINGUAS,TERM,TZ",
        wildcard_denied: ";&|",
        allow_root: true,
        disable_bounding: false
      }
    }
  ]
}

I do not see real improvements, except yes, there is no &amp; and no < >
For me it's just a matter of habit, I do not see "pain" by using one or other.
Some cases JSON5 is better, some cases XML is better.
JSON5 shows every information at same level of lisibility while XML struct is focusing on the most important even let other less readable.
In these examples, I decided to write some JSON lists to just comma separated String, because that case would be really unreadable.
Also implementation is not so "smooth", and if I would like real readability focus, it need some customization, that is not provided by json5 library.

KDL is may less popular but seems very gorgeous and matching needs, with a customizable manipulation

rootasrole version="3.0.0-alpha.3" {
    options {
        path "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin"
        env-keep "HOME" "USER" "LOGNAME" "COLORS" "DISPLAY" "HOSTNAME" "KRB5CCNAME" "LS_COLORS" "PS1" "PS2" "XAUTHORY" "XAUTHORIZATION" "XDG_CURRENT_DESKTOP"
        env-check "COLORTERM" "LANG" "LANGUAGE" "LC_*" "LINGUAS" "TERM" "TZ"
        allow-root true
        allow-bounding true
        wildcard-denied ";&|"
    }
    roles {
        role name="r_test_A" {
            parents "r_test_B"
            incompatble-with "r_test_C"
            denied-capabilities "CAP_SYS_ADMIN" "CAP_SYS_MODULE"
            actors {
                user "userA"
                group "groupA" "groupB"
                group "groupC"
            }
            tasks {
                task id="rA_t1" {
                    purpose "do a command"
                    setuid "root"
                    setgid "root" "groupA"
                    capabilities "CAP_NET_RAW" "CAP_NET_BIND_SERVICE"
                    commands {
                        command r#"a super duper command"#
                        command r#"another < super { duper # command $ with [ special £ chars "#
                    }
                    options {
                        path "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin"
                        env-keep "HOME" "USER" "LOGNAME" "COLORS" "DISPLAY" "HOSTNAME" "KRB5CCNAME" "LS_COLORS" "PS1" "PS2" "XAUTHORY" "XAUTHORIZATION" "XDG_CURRENT_DESKTOP"
                        env-check "COLORTERM" "LANG" "LANGUAGE" "LC_*" "LINGUAS" "TERM" "TZ"
                        allow-root true
                        allow-bounding true
                        wildcard-denied ";&|"
                    }
                }
            }
            options {
                path "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin"
                env-keep "HOME" "USER" "LOGNAME" "COLORS" "DISPLAY" "HOSTNAME" "KRB5CCNAME" "LS_COLORS" "PS1" "PS2" "XAUTHORY" "XAUTHORIZATION" "XDG_CURRENT_DESKTOP"
                env-check "COLORTERM" "LANG" "LANGUAGE" "LC_*" "LINGUAS" "TERM" "TZ"
                allow-root true
                allow-bounding true
                wildcard-denied ";&|"
            }
        }
    }
}

JSON would be convenient for generating the config file from Nix