From 51e65cc7104bcccdfc2554f489c8a5c0e8feea37 Mon Sep 17 00:00:00 2001 From: Varun Vasudev Date: Thu, 18 May 2017 11:53:16 +0530 Subject: [PATCH] Validate docker image name before launching container. --- .../runtime/DockerLinuxContainerRuntime.java | 24 ++++++++++++--- .../runtime/TestDockerContainerRuntime.java | 29 +++++++++++++++++++ 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/DockerLinuxContainerRuntime.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/DockerLinuxContainerRuntime.java index c303e9474f4..fc3376ae23f 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/DockerLinuxContainerRuntime.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/DockerLinuxContainerRuntime.java @@ -51,6 +51,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.regex.Pattern; import static org.apache.hadoop.yarn.server.nodemanager.containermanager.linux.runtime.LinuxContainerRuntimeConstants.*; @@ -60,6 +61,12 @@ public class DockerLinuxContainerRuntime implements LinuxContainerRuntime { private static final Log LOG = LogFactory.getLog( DockerLinuxContainerRuntime.class); + // This validates that the image is a proper docker image + public static final String DOCKER_IMAGE_PATTERN = + "^(([a-zA-Z0-9.-]+)(:\\d+)?/)?([a-z0-9_./-]+)(:[\\w.-]+)?$"; + private static final Pattern dockerImagePattern = + Pattern.compile(DOCKER_IMAGE_PATTERN); + @InterfaceAudience.Private public static final String ENV_DOCKER_CONTAINER_IMAGE = "YARN_CONTAINER_RUNTIME_DOCKER_IMAGE"; @@ -216,10 +223,7 @@ public class DockerLinuxContainerRuntime implements LinuxContainerRuntime { .getEnvironment(); String imageName = environment.get(ENV_DOCKER_CONTAINER_IMAGE); - if (imageName == null) { - throw new ContainerExecutionException(ENV_DOCKER_CONTAINER_IMAGE - + " not set!"); - } + validateImageName(imageName); String containerIdStr = container.getContainerId().toString(); String runAsUser = ctx.getExecutionAttribute(RUN_AS_USER); @@ -354,4 +358,16 @@ public class DockerLinuxContainerRuntime implements LinuxContainerRuntime { throws ContainerExecutionException { } + + public static void validateImageName(String imageName) + throws ContainerExecutionException { + if (imageName == null || imageName.isEmpty()) { + throw new ContainerExecutionException( + ENV_DOCKER_CONTAINER_IMAGE + " not set!"); + } + if (!dockerImagePattern.matcher(imageName).matches()) { + throw new ContainerExecutionException("Image name '" + imageName + + "' doesn't match docker image name pattern"); + } + } } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/TestDockerContainerRuntime.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/TestDockerContainerRuntime.java index 05f144f3a4e..1d955138841 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/TestDockerContainerRuntime.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/TestDockerContainerRuntime.java @@ -388,4 +388,33 @@ public class TestDockerContainerRuntime { + ": " + command, command.contains("--privileged")); } + @Test + public void testDockerImageNamePattern() throws Exception { + String[] validNames = + { "ubuntu", "fedora/httpd:version1.0", + "fedora/httpd:version1.0.test", + "fedora/httpd:version1.0.TEST", + "myregistryhost:5000/ubuntu", + "myregistryhost:5000/fedora/httpd:version1.0", + "myregistryhost:5000/fedora/httpd:version1.0.test", + "myregistryhost:5000/fedora/httpd:version1.0.TEST"}; + + String[] invalidNames = { "Ubuntu", "ubuntu || fedora", "ubuntu#", + "myregistryhost:50AB0/ubuntu", "myregistry#host:50AB0/ubuntu", + ":8080/ubuntu" + }; + + for (String name : validNames) { + DockerLinuxContainerRuntime.validateImageName(name); + } + + for (String name : invalidNames) { + try { + DockerLinuxContainerRuntime.validateImageName(name); + Assert.fail(name + " is an invalid name and should fail the regex"); + } catch (ContainerExecutionException ce) { + continue; + } + } + } }