mirror of
https://github.com/kestra-io/kestra.git
synced 2025-12-23 21:04:39 -05:00
fix(plugins): properly handle POSIX permissions for Docker task runner
Set POSIX file permissions when uploading/download working-dir files from and to Docker container
This commit is contained in:
committed by
Florian Hussonnois
parent
09d91034ab
commit
59e631f048
@@ -0,0 +1,68 @@
|
||||
package io.kestra.core.utils;
|
||||
|
||||
import java.nio.file.attribute.PosixFilePermission;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Utility method for converting Unix file mode into PosixFilePermission.
|
||||
*/
|
||||
public final class UnixModeToPosixFilePermissions {
|
||||
|
||||
public static Set<PosixFilePermission> toPosixPermissions(int mode) {
|
||||
Set<PosixFilePermission> permissions = new HashSet<>();
|
||||
|
||||
// Check owner permissions
|
||||
if ((mode & 0400) != 0) {
|
||||
permissions.add(PosixFilePermission.OWNER_READ);
|
||||
}
|
||||
if ((mode & 0200) != 0) {
|
||||
permissions.add(PosixFilePermission.OWNER_WRITE);
|
||||
}
|
||||
if ((mode & 0100) != 0) {
|
||||
permissions.add(PosixFilePermission.OWNER_EXECUTE);
|
||||
}
|
||||
|
||||
// Check group permissions
|
||||
if ((mode & 0040) != 0) {
|
||||
permissions.add(PosixFilePermission.GROUP_READ);
|
||||
}
|
||||
if ((mode & 0020) != 0) {
|
||||
permissions.add(PosixFilePermission.GROUP_WRITE);
|
||||
}
|
||||
if ((mode & 0010) != 0) {
|
||||
permissions.add(PosixFilePermission.GROUP_EXECUTE);
|
||||
}
|
||||
|
||||
// Check others permissions
|
||||
if ((mode & 0004) != 0) {
|
||||
permissions.add(PosixFilePermission.OTHERS_READ);
|
||||
}
|
||||
if ((mode & 0002) != 0) {
|
||||
permissions.add(PosixFilePermission.OTHERS_WRITE);
|
||||
}
|
||||
if ((mode & 0001) != 0) {
|
||||
permissions.add(PosixFilePermission.OTHERS_EXECUTE);
|
||||
}
|
||||
|
||||
return permissions;
|
||||
}
|
||||
|
||||
public static int fromPosixFilePermissions(final Set<PosixFilePermission> perms) {
|
||||
int mode = 0;
|
||||
for (PosixFilePermission perm : perms) {
|
||||
switch (perm) {
|
||||
case OWNER_READ: mode |= 0400; break;
|
||||
case OWNER_WRITE: mode |= 0200; break;
|
||||
case OWNER_EXECUTE: mode |= 0100; break;
|
||||
case GROUP_READ: mode |= 0040; break;
|
||||
case GROUP_WRITE: mode |= 0020; break;
|
||||
case GROUP_EXECUTE: mode |= 0010; break;
|
||||
case OTHERS_READ: mode |= 0004; break;
|
||||
case OTHERS_WRITE: mode |= 0002; break;
|
||||
case OTHERS_EXECUTE:mode |= 0001; break;
|
||||
}
|
||||
}
|
||||
return mode;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package io.kestra.core.utils;
|
||||
|
||||
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.nio.file.attribute.PosixFilePermissions;
|
||||
import java.util.Set;
|
||||
|
||||
import static java.nio.file.attribute.PosixFilePermission.*;
|
||||
import static java.nio.file.attribute.PosixFilePermission.OWNER_READ;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class UnixModeToPosixFilePermissionsTest {
|
||||
|
||||
@Test
|
||||
void shouldReturnPosixFilePermissions() {
|
||||
assertThat(PosixFilePermissions.toString(UnixModeToPosixFilePermissions.toPosixPermissions(Integer.parseInt("700", 8)))).isEqualTo("rwx------");
|
||||
assertThat(PosixFilePermissions.toString(UnixModeToPosixFilePermissions.toPosixPermissions(Integer.parseInt("620", 8)))).isEqualTo("rw--w----");
|
||||
assertThat(PosixFilePermissions.toString(UnixModeToPosixFilePermissions.toPosixPermissions(Integer.parseInt("777", 8)))).isEqualTo("rwxrwxrwx");
|
||||
assertThat(PosixFilePermissions.toString(UnixModeToPosixFilePermissions.toPosixPermissions(TarArchiveEntry.DEFAULT_FILE_MODE))).isEqualTo("rw-r--r--");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReturnPosixFilePermissionsFromString() {
|
||||
assertThat(Integer.toOctalString(UnixModeToPosixFilePermissions.fromPosixFilePermissions(Set.of(OWNER_READ, OWNER_WRITE, OWNER_EXECUTE)))).isEqualTo("700");
|
||||
assertThat(Integer.toOctalString(UnixModeToPosixFilePermissions.fromPosixFilePermissions(Set.of(OWNER_READ, OWNER_WRITE, GROUP_WRITE)))).isEqualTo("620");
|
||||
}
|
||||
}
|
||||
@@ -22,13 +22,13 @@ import io.kestra.core.runners.RunContext;
|
||||
import io.kestra.core.utils.Await;
|
||||
import io.kestra.core.utils.ListUtils;
|
||||
import io.kestra.core.utils.RetryUtils;
|
||||
import io.kestra.core.utils.UnixModeToPosixFilePermissions;
|
||||
import io.kestra.plugin.scripts.exec.scripts.models.DockerOptions;
|
||||
import io.micronaut.core.convert.format.ReadableBytesTypeConverter;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.*;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
import org.apache.commons.compress.archivers.ArchiveEntry;
|
||||
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
|
||||
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
|
||||
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
|
||||
@@ -44,6 +44,7 @@ import java.net.Socket;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.nio.file.attribute.PosixFilePermission;
|
||||
import java.time.Duration;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
@@ -406,6 +407,13 @@ public class Docker extends TaskRunner<Docker.DockerTaskRunnerDetailResult> {
|
||||
for (Path file: relativeWorkingDirectoryFilesPaths) {
|
||||
Path resolvedFile = runContext.workingDir().resolve(file);
|
||||
TarArchiveEntry entry = out.createArchiveEntry(resolvedFile.toFile(), file.toString());
|
||||
// Preserve POSIX permissions if supported
|
||||
try {
|
||||
Set<PosixFilePermission> perms = Files.getPosixFilePermissions(resolvedFile);
|
||||
entry.setMode(UnixModeToPosixFilePermissions.fromPosixFilePermissions(perms));
|
||||
} catch (UnsupportedOperationException | IOException ignore) {
|
||||
// Skipping unix file permission
|
||||
}
|
||||
out.putArchiveEntry(entry);
|
||||
if (!Files.isDirectory(resolvedFile)) {
|
||||
try (InputStream fis = Files.newInputStream(resolvedFile)) {
|
||||
@@ -589,7 +597,7 @@ public class Docker extends TaskRunner<Docker.DockerTaskRunnerDetailResult> {
|
||||
CopyArchiveFromContainerCmd copyArchiveFromContainerCmd = dockerClient.copyArchiveFromContainerCmd(execId, windowsToUnixPath(taskCommands.getWorkingDirectory().toString()));
|
||||
try (InputStream is = copyArchiveFromContainerCmd.exec();
|
||||
TarArchiveInputStream tar = new TarArchiveInputStream(is)) {
|
||||
ArchiveEntry entry;
|
||||
TarArchiveEntry entry;
|
||||
while ((entry = tar.getNextEntry()) != null) {
|
||||
// each entry contains the working directory as the first part, we need to remove it
|
||||
Path extractTo = runContext.workingDir().resolve(Path.of(entry.getName().substring(runContext.workingDir().id().length() + 1)));
|
||||
@@ -599,6 +607,11 @@ public class Docker extends TaskRunner<Docker.DockerTaskRunnerDetailResult> {
|
||||
}
|
||||
} else {
|
||||
Files.copy(tar, extractTo, StandardCopyOption.REPLACE_EXISTING);
|
||||
try {
|
||||
Files.setPosixFilePermissions(extractTo, UnixModeToPosixFilePermissions.toPosixPermissions(entry.getMode()));
|
||||
} catch (UnsupportedOperationException | IOException e) {
|
||||
// File system does not support POSIX permissions (e.g., Windows)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user