1*0f92bee2SBaptiste Daroussin#!/usr/libexec/flua 2*0f92bee2SBaptiste Daroussin--- 3*0f92bee2SBaptiste Daroussin-- SPDX-License-Identifier: BSD-2-Clause 4*0f92bee2SBaptiste Daroussin-- 5*0f92bee2SBaptiste Daroussin-- Copyright (c) 2026 Baptiste Daroussin <bapt@FreeBSD.org> 6*0f92bee2SBaptiste Daroussin 7*0f92bee2SBaptiste Daroussinlocal n = require("nuage") 8*0f92bee2SBaptiste Daroussin 9*0f92bee2SBaptiste Daroussinlocal root = os.getenv("NUAGE_FAKE_ROOTDIR") 10*0f92bee2SBaptiste Daroussinif not root then 11*0f92bee2SBaptiste Daroussin root = "" 12*0f92bee2SBaptiste Daroussinend 13*0f92bee2SBaptiste Daroussin 14*0f92bee2SBaptiste Daroussinlocal function get_localbase() 15*0f92bee2SBaptiste Daroussin local f = io.popen("sysctl -in user.localbase 2> /dev/null") 16*0f92bee2SBaptiste Daroussin local lb = f:read("*l") 17*0f92bee2SBaptiste Daroussin f:close() 18*0f92bee2SBaptiste Daroussin if lb == nil or lb:len() == 0 then 19*0f92bee2SBaptiste Daroussin lb = "/usr/local" 20*0f92bee2SBaptiste Daroussin end 21*0f92bee2SBaptiste Daroussin return lb 22*0f92bee2SBaptiste Daroussinend 23*0f92bee2SBaptiste Daroussin 24*0f92bee2SBaptiste Daroussinlocal function read_doasconf() 25*0f92bee2SBaptiste Daroussin local path = root .. get_localbase() .. "/etc/doas.conf" 26*0f92bee2SBaptiste Daroussin local f = io.open(path, "r") 27*0f92bee2SBaptiste Daroussin if not f then 28*0f92bee2SBaptiste Daroussin return nil 29*0f92bee2SBaptiste Daroussin end 30*0f92bee2SBaptiste Daroussin local content = f:read("*a") 31*0f92bee2SBaptiste Daroussin f:close() 32*0f92bee2SBaptiste Daroussin return content 33*0f92bee2SBaptiste Daroussinend 34*0f92bee2SBaptiste Daroussin 35*0f92bee2SBaptiste Daroussin-- test with a single string rule with %u substitution 36*0f92bee2SBaptiste Daroussinn.adddoas({ name = "testuser", doas = "permit persist %u as root" }) 37*0f92bee2SBaptiste Daroussinlocal content = read_doasconf() 38*0f92bee2SBaptiste Daroussinif not content then 39*0f92bee2SBaptiste Daroussin n.err("doas.conf not created") 40*0f92bee2SBaptiste Daroussinend 41*0f92bee2SBaptiste Daroussinif content ~= "permit persist testuser as root\n" then 42*0f92bee2SBaptiste Daroussin n.err("unexpected doas.conf content with %u: '" .. content .. "'") 43*0f92bee2SBaptiste Daroussinend 44*0f92bee2SBaptiste Daroussin 45*0f92bee2SBaptiste Daroussin-- remove file for next test 46*0f92bee2SBaptiste Daroussinos.remove(root .. get_localbase() .. "/etc/doas.conf") 47*0f92bee2SBaptiste Daroussin 48*0f92bee2SBaptiste Daroussin-- test with a table of rules 49*0f92bee2SBaptiste Daroussinn.adddoas({ 50*0f92bee2SBaptiste Daroussin name = "testuser", 51*0f92bee2SBaptiste Daroussin doas = { 52*0f92bee2SBaptiste Daroussin "deny %u as foobar", 53*0f92bee2SBaptiste Daroussin "permit persist %u as root cmd whoami" 54*0f92bee2SBaptiste Daroussin } 55*0f92bee2SBaptiste Daroussin}) 56*0f92bee2SBaptiste Daroussincontent = read_doasconf() 57*0f92bee2SBaptiste Daroussinif not content then 58*0f92bee2SBaptiste Daroussin n.err("doas.conf not created for table") 59*0f92bee2SBaptiste Daroussinend 60*0f92bee2SBaptiste Daroussinif content ~= "deny testuser as foobar\npermit persist testuser as root cmd whoami\n" then 61*0f92bee2SBaptiste Daroussin n.err("unexpected doas.conf content for table: '" .. content .. "'") 62*0f92bee2SBaptiste Daroussinend 63*0f92bee2SBaptiste Daroussin 64*0f92bee2SBaptiste Daroussinos.exit(0) 65