1 # bend-osdev-apparmor: examples, for the laws' witnesses, check.bend and 2 # users: a profile built directly from the types, and a small policy in 3 # the profile language (the example of apparmor.d(5), cut down, with an 4 # abstraction and a tunable in a file map). 5 import Base 6 import bend-osdev-bytes@0.1.0.0/bytes.bend as B 7 import ./text.bend as X 8 import ./glob.bend as G 9 import ./perm.bend as P 10 import ./options.bend as O 11 import ./profile.bend as PR 12 import ./rule_file.bend as F 13 import ./error.bend as E 14 import ./eval.bend as V 15 import ./transitions.bend as TR 16 import ./apparmor.bend as A 17 18 def AaExample.qual(audit: Bool, deny: Bool) -> P.AaQual: 19 P.AaQual{audit, deny, False{}} 20 21 # a file rule on a literal path 22 def AaExample.rule(+path: String, q: P.AaQual, perms: String) -> F.AaFileRule: 23 F.AaFileRule{q, X.AaText.of_string(path), G.AaGlob.literal(X.AaText.of_string(path)), F.AaFile.perms(perms), None{}, None{}} 24 25 # profile ex: /etc/x rw, deny /etc/x w, audit /var/log/x w, /lib/** (built 26 # as a literal-free pattern) r; no x rule anywhere 27 def AaExample.rules() -> PR.AaRules: 28 PR.AaRules.with_files(PR.AaRules.empty(), [AaExample.rule("/etc/x", AaExample.qual(False{}, False{}), "rw"), AaExample.rule("/etc/x", AaExample.qual(False{}, True{}), "w"), AaExample.rule("/var/log/x", AaExample.qual(True{}, False{}), "w"), F.AaFileRule{AaExample.qual(False{}, False{}), X.AaText.of_string("/lib/**"), G.AaGlob{[[G.AaGChar{47}, G.AaGChar{108}, G.AaGChar{105}, G.AaGChar{98}, G.AaGChar{47}, G.AaGAny{}, G.AaGStar2{}]], False{}}, F.AaFile.perms("r"), None{}, None{}}]) 29 30 def AaExample.profile(m: PR.AaMode) -> PR.AaProfile: 31 PR.AaProfile.include(PR.AaProfile.new(X.AaText.of_string("ex"), None{}, PR.AaFlags{m, False{}}), AaExample.rules()) 32 33 def AaExample.policy() -> PR.AaPolicy: 34 PR.AaPolicy{[AaExample.profile(PR.AaModeEnforce{})]} 35 36 def AaExample.query(+path: String, perms: String) -> F.AaFileQuery: 37 F.AaFileQuery{X.AaText.of_string(path), False{}, F.AaFile.perms(perms)} 38 39 # The policy text 40 41 def AaExample.source(n: String, t: String) -> A.AaSource: 42 A.AaSource{B.Octets.of_string(n), B.Octets.of_string(t)} 43 44 def AaExample.files() -> List<&2, A.AaSource>: 45 [AaExample.source("tunables/home", "@{HOMEDIRS} = /home/\n@{HOME} = @{HOMEDIRS}/*/ /root/\n"), AaExample.source("abstractions/base", "/etc/ld.so.cache r,\n/{usr/,}lib{,32,64}/** mr,\n"), AaExample.source("main", "include \n# a cut-down version of the example in apparmor.d(5)\n/usr/bin/foo {\n include \n include \n /bin/mount ux,\n /dev/{,u}random r,\n /etc/foo/* r,\n /tmp/foo.* lrw,\n @{HOME}/.foo_file rw,\n deny /etc/shadow rw,\n audit /var/log/foo w,\n owner /proc/[0-9]*/stat r,\n /usr/bin/baz Cx -> baz,\n /usr/bin/bar px,\n /usr/bin/** pix,\n capability setuid,\n network inet stream,\n signal (send) set=(term, kill) peer=/usr/bin/bar,\n ^hat {\n /var/spool/* rwl,\n }\n profile baz {\n /bin/bash ixr,\n }\n}\nprofile bar /usr/bin/bar flags=(complain) {\n /etc/bar r,\n deny /etc/secret r,\n}\n")] 46 47 def AaExample.loaded() -> Result<&2, &2, E.AaError, PR.AaPolicy>: 48 A.Aa.load(O.AaOptions.default(), AaExample.files(), B.Octets.of_string("main")) 49 50 def AaExample.pol() -> PR.AaPolicy: 51 Result.default(&2, &2, E.AaError, PR.AaPolicy, AaExample.loaded(), PR.AaPolicy{Nil{}}) 52 53 def AaExample.file(prof: String, path: String, perms: String) -> Maybe<&2, V.AaDecision>: 54 A.Aa.file(O.AaOptions.default(), AaExample.pol(), B.Octets.of_string(prof), B.Octets.of_string(path), False{}, F.AaFile.perms(perms)) 55 56 def AaExample.exec(prof: String, path: String) -> String: 57 TR.AaExecResult.show(A.Aa.exec(O.AaOptions.default(), AaExample.pol(), B.Octets.of_string(prof), B.Octets.of_string(path), False{})) 58 59 # A smaller policy, for the laws' vectors (the checker's kernel evaluates 60 # them, so they are kept short) 61 def AaExample.small_files() -> List<&2, A.AaSource>: 62 [AaExample.source("t", "@{H} = /home/*/ /root/\n"), AaExample.source("a", "/lib/** mr,\n"), AaExample.source("m", "include \n/usr/bin/foo {\n include \n include \n deny /etc/shadow r,\n @{H}/f rw,\n /bin/x px,\n}\nprofile bar /bin/x flags=(complain) {\n}\n")] 63 64 def AaExample.small() -> PR.AaPolicy: 65 Result.default(&2, &2, E.AaError, PR.AaPolicy, A.Aa.load(O.AaOptions.default(), AaExample.small_files(), B.Octets.of_string("m")), PR.AaPolicy{Nil{}}) 66 67 def AaExample.small_file(prof: String, path: String, perms: String) -> Maybe<&2, V.AaDecision>: 68 A.Aa.file(O.AaOptions.default(), AaExample.small(), B.Octets.of_string(prof), B.Octets.of_string(path), False{}, F.AaFile.perms(perms)) 69 70 def AaExample.small_exec(prof: String, path: String) -> String: 71 TR.AaExecResult.show(A.Aa.exec(O.AaOptions.default(), AaExample.small(), B.Octets.of_string(prof), B.Octets.of_string(path), False{}))