Skip to content

Commit

Permalink
daemon: verify that the user can set post-build-hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
sandydoo committed Jan 9, 2024
1 parent 67d3814 commit 4386350
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 13 deletions.
66 changes: 60 additions & 6 deletions dist/main/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7814,12 +7814,17 @@ async function setup() {
if (signingKey !== "") {
core.exportVariable('CACHIX_SIGNING_KEY', signingKey);
}
let daemonSupported = (cachixVersion) ? semver_1.default.gte(cachixVersion, '1.7.0') : false;
core.saveState('daemonSupported', daemonSupported);
if (useDaemon && !daemonSupported) {
let supportsDaemonInterface = (cachixVersion) ? semver_1.default.gte(cachixVersion, '1.7.0') : false;
let supportsPostBuildHook = isTrustedUser();
if (useDaemon && !supportsDaemonInterface) {
core.warning(`Cachix Daemon is not supported by this version of Cachix (${cachixVersion}). Ignoring the 'useDaemon' option.`);
}
if (useDaemon && daemonSupported) {
if (useDaemon && !supportsPostBuildHook) {
core.warning("This user is not allowed to set the post-build-hook. Ignoring the 'useDaemon' option.");
}
let supportsDaemon = supportsDaemonInterface && supportsPostBuildHook;
core.saveState('supportsDaemon', supportsDaemon);
if (useDaemon && supportsDaemon) {
const tmpdir = process.env['RUNNER_TEMP'] ?? os.tmpdir();
const daemonDir = await fs.mkdtemp(path.join(tmpdir, 'cachix-daemon-'));
const daemonLog = await fs.open(`${daemonDir}/daemon.log`, 'a');
Expand Down Expand Up @@ -7861,13 +7866,13 @@ async function setup() {
async function upload() {
core.startGroup('Cachix: push');
const cachixBin = core.getState('cachixBin');
const daemonSupported = core.getState('daemonSupported');
const supportsDaemon = core.getState('supportsDaemon');
try {
if (skipPush === 'true') {
core.info('Pushing is disabled as skipPush is set to true');
}
else if (signingKey !== "" || authToken !== "") {
if (useDaemon && daemonSupported) {
if (useDaemon && supportsDaemon) {
const daemonDir = process.env[ENV_CACHIX_DAEMON_DIR];
if (!daemonDir) {
core.debug('Cachix Daemon not started. Skipping push');
Expand Down Expand Up @@ -7980,6 +7985,55 @@ function getUserConfigDirs() {
const xdgConfigDirs = (process.env['XDG_CONFIG_DIRS'] ?? '/etc/xdg').split(':');
return [xdgConfigHome, ...xdgConfigDirs];
}
async function isTrustedUser() {
try {
let user = os.userInfo().username;
let userGroups = await exec.exec('id', ['-Gn', user]).toString().split(' ');
let [trustedUsers, trustedGroups] = await fetchTrustedUsers().then(partitionUsersAndGroups);
// Chech if Nix is installed in single-user mode.
let isStoreWritable = isWritable('/nix/store');
return isStoreWritable
|| trustedUsers.includes(user)
|| trustedGroups.some((group) => userGroups.includes(group));
}
catch (error) {
core.warning('Failed to determine if the user is trusted. Assuming untrusted user.');
return false;
}
}
async function isWritable(path) {
try {
await fs.access(path, fs.constants.W_OK);
return true;
}
catch (error) {
return false;
}
}
async function fetchTrustedUsers() {
try {
let conf = await exec.exec('nix show-config').toString();
let match = conf.match(/trusted-users = (.+);/);
return match?.length === 2 ? match[1].split(' ') : [];
}
catch (error) {
core.warning('Failed to read the Nix configuration');
return [];
}
}
function partitionUsersAndGroups(mixedUsers) {
let users = [];
let groups = [];
mixedUsers.forEach((item) => {
if (item.startsWith('@')) {
groups.push(item.slice(1));
}
else {
users.push(item);
}
});
return [users, groups];
}
const isPost = !!core.getState('isPost');
// Main
if (!isPost) {
Expand Down
73 changes: 66 additions & 7 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,14 +100,19 @@ async function setup() {
core.exportVariable('CACHIX_SIGNING_KEY', signingKey);
}

let daemonSupported = (cachixVersion) ? semver.gte(cachixVersion, '1.7.0') : false;
core.saveState('daemonSupported', daemonSupported);

if (useDaemon && !daemonSupported) {
let supportsDaemonInterface = (cachixVersion) ? semver.gte(cachixVersion, '1.7.0') : false;
let supportsPostBuildHook = isTrustedUser();
if (useDaemon && !supportsDaemonInterface) {
core.warning(`Cachix Daemon is not supported by this version of Cachix (${cachixVersion}). Ignoring the 'useDaemon' option.`)
}
if (useDaemon && !supportsPostBuildHook) {
core.warning("This user is not allowed to set the post-build-hook. Ignoring the 'useDaemon' option.");
}

if (useDaemon && daemonSupported) {
let supportsDaemon = supportsDaemonInterface && supportsPostBuildHook;
core.saveState('supportsDaemon', supportsDaemon);

if (useDaemon && supportsDaemon) {
const tmpdir = process.env['RUNNER_TEMP'] ?? os.tmpdir();
const daemonDir = await fs.mkdtemp(path.join(tmpdir, 'cachix-daemon-'));
const daemonLog = await fs.open(`${daemonDir}/daemon.log`, 'a');
Expand Down Expand Up @@ -158,13 +163,13 @@ async function upload() {
core.startGroup('Cachix: push');

const cachixBin = core.getState('cachixBin');
const daemonSupported = core.getState('daemonSupported');
const supportsDaemon = core.getState('supportsDaemon');

try {
if (skipPush === 'true') {
core.info('Pushing is disabled as skipPush is set to true');
} else if (signingKey !== "" || authToken !== "") {
if (useDaemon && daemonSupported) {
if (useDaemon && supportsDaemon) {
const daemonDir = process.env[ENV_CACHIX_DAEMON_DIR];

if (!daemonDir) {
Expand Down Expand Up @@ -298,6 +303,60 @@ function getUserConfigDirs(): string[] {
return [xdgConfigHome, ...xdgConfigDirs];
}

async function isTrustedUser(): Promise<boolean> {
try {
let user = os.userInfo().username;
let userGroups = await exec.exec('id', ['-Gn', user]).toString().split(' ');

let [trustedUsers, trustedGroups] = await fetchTrustedUsers().then(partitionUsersAndGroups);

// Chech if Nix is installed in single-user mode.
let isStoreWritable = isWritable('/nix/store');

return isStoreWritable
|| trustedUsers.includes(user)
|| trustedGroups.some((group) => userGroups.includes(group));
} catch (error) {
core.warning('Failed to determine if the user is trusted. Assuming untrusted user.');
return false;
}
}

async function isWritable(path: string): Promise<boolean> {
try {
await fs.access(path, fs.constants.W_OK);
return true;
} catch (error) {
return false;
}
}

async function fetchTrustedUsers(): Promise<string[]> {
try {
let conf = await exec.exec('nix show-config').toString();
let match = conf.match(/trusted-users = (.+);/)
return match?.length === 2 ? match[1].split(' ') : [];
} catch (error) {
core.warning('Failed to read the Nix configuration');
return [];
}
}

function partitionUsersAndGroups(mixedUsers: string[]): [string[], string[]] {
let users: string[] = [];
let groups: string[] = []

mixedUsers.forEach((item) => {
if (item.startsWith('@')) {
groups.push(item.slice(1));
} else {
users.push(item);
}
});

return [users, groups];
}

const isPost = !!core.getState('isPost');

// Main
Expand Down

0 comments on commit 4386350

Please sign in to comment.