Merge pull request #4562 from backstage/orkohunter/techdocs-run-container-with-user-permissions
This commit is contained in:
@@ -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,
|
||||
},
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user