manage filesystem permissions with configuration files

a configuration file format and evaluator implementation for specifying and setting filesystem permissions

a bit like css for filesystem permissions

view code



programs, copied files and remote users working on a system sometimes create new files with incorrect permissions and modify the permissions of existing files

if there are no regular automatic checks and fixes to keep desired filesystem permissions, the security of the system is at risk and processes that need specific permissions might stop working

for the purpose of ensuring filesystem permissions, writing shell scripts that use the chown, chmod, setfacl, find and similar utilities is much more cumbersome, unclear, error prone and harder to maintain than necessary


nested paths

user/group/other and acl permissions

file-type specific permissions

setting owner and group

automatic executable bit for directories if the read permission is set

globbing with a child selector "*", recursive/descendants selector "**", and ".*" ".**" for including the starting path

path production

dry-run option that displays shell commands

permission specifiers can be shortened, like just "r" or "rw,r::groupname"

list and string support for acl specifiers

no support for octal notation


configuration file with almost all features mixed:

  (file-type regular default-user (nonroot rw) user (testuser rw http r) group (http rw) other r)
  ("temp/documents/*" (acl file-type directory "d:u:1000:rwx"))
  (("modules" "tests") "rwx,rw::git"))

same with comments:

  ;restriction on directories. sets permissions, user and group
  ;acl as a key/value list
  (file-type regular default-user (nonroot rw) user (testuser rw http r) group (http rw) other r)
    ;an alternative acl notation as a key/value list and string as would be used with "setfacl"
    (acl file-type directory "d:u:1000:rwx"))
  ;matches any of the listed file names
  (("modules" "tests") "rwx,rw::git"))

more practical example:

;matches all ".git" directories under "/home/testuser"
("/home/testuser/**/.git" "rw:nonroot:git")

command-line program

$ fs-perm-set --help

  options ... specifier path paths ...
  --help | -h

usage examples

$ cat my-fs-config | fs-perm-set --dry-run
$ fs-perm-set --config-file=my-fs-config
$ fs-perm-set rw,r:testuser testpath testpath/**
$ fs-perm-set --acl u:testuser:rw testpath-1 testpath-2
$ fs-perm-set rwx,rw:nonroot /usr/share/guile/site/2.2/ice-9/* --dry-run
chown 1000:-1 "/usr/share/guile/site/2.2/ice-9/match-phd-lookup.scm"
chmod 760 "/usr/share/guile/site/2.2/ice-9/match-phd-lookup.scm"
chown 1000:-1 "/usr/share/guile/site/2.2/ice-9/match-phd.scm"
chmod 760 "/usr/share/guile/site/2.2/ice-9/match-phd.scm"
chown 1000:-1 "/usr/share/guile/site/2.2/ice-9/set"
chmod 770 "/usr/share/guile/site/2.2/ice-9/set"
chown 1000:-1 "/usr/share/guile/site/2.2/ice-9/vset.scm"
chmod 760 "/usr/share/guile/site/2.2/ice-9/vset.scm"

configuration file syntax

file-name: {valid filesystem file name character} ...

path: ["/"] file-name/*/**/.*/.** ["/" path] ...

perm-name: "r"/"w"/"x"

perm: perm-name [perm-name [perm-name]]

ugo-perm: perm ["," perm ["," perm]]

acl-specifier: ([symbol:key symbol/string:value])/(acl [symbol:key any:value] ... string [symbol:key any:value] ...)

rule: (string:path/(string:path ...) string:ugo-specifier/acl-specifier ... rule ...)


guile >= 2



why no support for octal notation?

if both octal and rwx notation would be supported, it would occur mixed and make usage inconsistent and the configuration slightly more complicated because you need to know/learn the semantics of both.

is any one of those notations better? octal notation is shorter (i usually prefer it on the command-line), but specific to only three permission types where it has to be known which octal value stands for which permission. rwx is more generic and the characters hint at the name of the permission. in this program not all three (user, group, other) parts have to be specified, in short the benefits should be consistencyand clearer (write-once read-often) notation through the use of characters instead of integers




copy or link the directories under modules/ into a path that is in $GUILE_LOAD_PATH

for example "cp -rt /usr/share/guile/site modules/*"

copy or link the files under exe/ into a path that is in $PATH

for example "cp -rt /usr/bin exe/*"

adjust file system permissions eventually

module name

(sph fs-perm config)

module bindings

library description

# example

(fsp-config-apply list-like-in-configuration-file)

# config format

file-name: {valid filesystem character} ...

path: file-name/"*"/"**"/".*"/".**" ["/" path] ...

rule: (string:selector [string:ugo-string] rule ...)

perm-name-string: "r"/"w"/"x"

perm-string: perm-name-string [perm-name-string [perm-name-string]]

ugo-perm-string: perm-string ["," perm-string ["," perm-string]]

acl: (acl [string:setfacl-format] [key:symbol value:([string/integer:user/group string:perm-name-string] ...)] ...)

ugo-string: [file-type-name:][perm-string [perm-string [perm-string]]]

# internal data-structures (roughly)

perm-name: symbol:read/write/execute

perm: (perm-name perm-name perm-name)

ugo-perm: (perm perm perm)

ugo-perm-spec-part: (file-type symbol/false)/(perm ugo-perm)/(user string/false)/(group string/false)

ugo-perm-spec: (symbol:"ugo" ugo-perm-spec-part ...)

acl-perm-spec-part: (symbol:"file-type symbol/false)/(symbol:"string" string)/(symbol:key any:value)

acl-perm-spec: (symbol:"acl" acl-perm-spec-part ...)

perm-spec: (ugo-perm-spec/acl-perm-spec ...)

import name

(sph fs-perm config)







rules #:path-context #:dry-run? ->

(list ...) #:path-context string/(string ...) #:dry-run? boolean -> boolean


evaluates a list of rules. stops if one fails.

path-context is a path selector prefixed to all paths in the rule,

as if the rule was wrapped in another rule which has that path selector




a path-context dry-run? ->

list string/(string ...) boolean -> boolean


path-context is a path selector prefixed to all paths in the rule,

as if the rule was wrapped in another which has that path selector





tags: guile application program start q1 computer filesystem permission command-line fs-perm