Merge pull request #4562 from backstage/orkohunter/techdocs-run-container-with-user-permissions

This commit is contained in:
Himanshu Mishra
2021-02-17 17:41:30 +01:00
committed by GitHub
3 changed files with 50 additions and 2 deletions
@@ -0,0 +1,5 @@
---
'@backstage/techdocs-common': patch
---
Pass user and group ID when invoking docker container. When TechDocs invokes Docker, docker could be run as a `root` user which results in generation of files by applications run by non-root user (e.g. TechDocs) will not have access to modify. This PR passes in current user and group ID to docker so that the file permissions of the generated files and folders are correct.
@@ -30,6 +30,7 @@ import {
patchMkdocsYmlPreBuild,
runDockerContainer,
storeEtagMetadata,
UserOptions,
} from './helpers';
const mockEntity = {
@@ -114,7 +115,7 @@ describe('helpers', () => {
imageName,
args,
expect.any(Stream),
{
expect.objectContaining({
Volumes: {
'/content': {},
'/result': {},
@@ -123,7 +124,7 @@ describe('helpers', () => {
HostConfig: {
Binds: [`${docsDir}:/content`, `${outputDir}:/result`],
},
},
}),
);
});
@@ -139,6 +140,30 @@ describe('helpers', () => {
expect(mockDocker.ping).toHaveBeenCalled();
});
it('should pass through the user and group id from the host machine and set the home dir', async () => {
await runDockerContainer({
imageName,
args,
docsDir,
outputDir,
dockerClient: mockDocker,
});
const userOptions: UserOptions = {};
if (process.getuid && process.getgid) {
userOptions.User = `${process.getuid()}:${process.getgid()}`;
}
expect(mockDocker.run).toHaveBeenCalledWith(
imageName,
args,
expect.any(Stream),
expect.objectContaining({
...userOptions,
}),
);
});
describe('where docker is unavailable', () => {
const dockerError = 'a docker error';
@@ -51,6 +51,12 @@ export type RunCommandOptions = {
logStream?: Writable;
};
export type UserOptions = {
User?: string;
};
// To be replaced by a runDockerContainer from backend-common
// shared between Scaffolder and TechDocs and any other plugin.
export async function runDockerContainer({
imageName,
args,
@@ -78,6 +84,17 @@ export async function runDockerContainer({
});
});
const userOptions: UserOptions = {};
// @ts-ignore
if (process.getuid && process.getgid) {
// Files that are created inside the Docker container will be owned by
// root on the host system on non Mac systems, because of reasons. Mainly the fact that
// volume sharing is done using NFS on Mac and actual mounts in Linux world.
// So we set the user in the container as the same user and group id as the host.
// On Windows we don't have process.getuid nor process.getgid
userOptions.User = `${process.getuid()}:${process.getgid()}`;
}
const [{ Error: error, StatusCode: statusCode }] = await dockerClient.run(
imageName,
args,
@@ -91,6 +108,7 @@ export async function runDockerContainer({
HostConfig: {
Binds: [`${docsDir}:/content`, `${outputDir}:/result`],
},
...userOptions,
...createOptions,
},
);