Skip to content

Commit 1d1247d

Browse files
YesOrNo828xintongsong
authored andcommitted
[FLINK-32817][Yarn] Harnessing Jackson for Secure Serialization of YarnLocalResourceDescriptor
This closes apache#23292
1 parent 4739dab commit 1d1247d

File tree

3 files changed

+68
-31
lines changed

3 files changed

+68
-31
lines changed

flink-core/src/main/java/org/apache/flink/util/jackson/JacksonMapperFactory.java

+7
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import org.apache.flink.annotation.Experimental;
2121

22+
import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.core.JsonFactory;
2223
import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.ObjectMapper;
2324
import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.SerializationFeature;
2425
import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.dataformat.csv.CsvMapper;
@@ -35,6 +36,12 @@ public static ObjectMapper createObjectMapper() {
3536
return objectMapper;
3637
}
3738

39+
public static ObjectMapper createObjectMapper(JsonFactory jsonFactory) {
40+
final ObjectMapper objectMapper = new ObjectMapper(jsonFactory);
41+
registerModules(objectMapper);
42+
return objectMapper;
43+
}
44+
3845
public static CsvMapper createCsvMapper() {
3946
final CsvMapper csvMapper = new CsvMapper();
4047
registerModules(csvMapper);

flink-yarn/src/main/java/org/apache/flink/yarn/YarnLocalResourceDescriptor.java

+52-28
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,24 @@
1919
package org.apache.flink.yarn;
2020

2121
import org.apache.flink.util.FlinkException;
22+
import org.apache.flink.util.jackson.JacksonMapperFactory;
23+
24+
import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.core.JsonFactoryBuilder;
25+
import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.core.JsonParser;
26+
import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.core.JsonProcessingException;
27+
import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.JsonNode;
28+
import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.ObjectMapper;
29+
import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.node.ObjectNode;
2230

2331
import org.apache.hadoop.fs.FileStatus;
2432
import org.apache.hadoop.fs.Path;
2533
import org.apache.hadoop.yarn.api.records.LocalResource;
2634
import org.apache.hadoop.yarn.api.records.LocalResourceType;
2735
import org.apache.hadoop.yarn.api.records.LocalResourceVisibility;
36+
import org.slf4j.Logger;
37+
import org.slf4j.LoggerFactory;
2838

2939
import java.util.Objects;
30-
import java.util.regex.Matcher;
31-
import java.util.regex.Pattern;
3240

3341
import static org.apache.flink.util.Preconditions.checkNotNull;
3442

@@ -38,14 +46,12 @@
3846
* {@link Utils#createTaskExecutorContext}.
3947
*/
4048
class YarnLocalResourceDescriptor {
49+
private static final Logger LOG = LoggerFactory.getLogger(YarnLocalResourceDescriptor.class);
4150

42-
private static final String STRING_FORMAT =
43-
"YarnLocalResourceDescriptor{"
44-
+ "key=%s, path=%s, size=%d, modificationTime=%d, visibility=%s, type=%s}";
45-
private static final Pattern LOCAL_RESOURCE_DESC_FORMAT =
46-
Pattern.compile(
47-
"YarnLocalResourceDescriptor\\{"
48-
+ "key=(\\S+), path=(\\S+), size=([\\d]+), modificationTime=([\\d]+), visibility=(\\S+), type=(\\S+)}");
51+
private static final ObjectMapper OBJECT_MAPPER =
52+
JacksonMapperFactory.createObjectMapper(
53+
new JsonFactoryBuilder().quoteChar('\'').build())
54+
.enable(JsonParser.Feature.ALLOW_SINGLE_QUOTES);
4955

5056
private final String resourceKey;
5157
private final Path path;
@@ -98,21 +104,33 @@ LocalResourceType getResourceType() {
98104
}
99105

100106
static YarnLocalResourceDescriptor fromString(String desc) throws Exception {
101-
Matcher m = LOCAL_RESOURCE_DESC_FORMAT.matcher(desc);
102-
boolean mat = m.find();
103-
if (mat) {
107+
try {
108+
JsonNode node = OBJECT_MAPPER.readTree(desc);
109+
if (!validate(node)) {
110+
throw new FlinkException("Error to parse YarnLocalResourceDescriptor from " + desc);
111+
}
104112
return new YarnLocalResourceDescriptor(
105-
m.group(1),
106-
new Path(m.group(2)),
107-
Long.parseLong(m.group(3)),
108-
Long.parseLong(m.group(4)),
109-
LocalResourceVisibility.valueOf(m.group(5)),
110-
LocalResourceType.valueOf(m.group(6)));
111-
} else {
112-
throw new FlinkException("Error to parse YarnLocalResourceDescriptor from " + desc);
113+
node.get("resourceKey").asText(),
114+
new Path(node.get("path").asText()),
115+
node.get("size").asLong(),
116+
node.get("modificationTime").asLong(),
117+
LocalResourceVisibility.valueOf(node.get("visibility").asText()),
118+
LocalResourceType.valueOf(node.get("resourceType").asText()));
119+
} catch (JsonProcessingException e) {
120+
throw new FlinkException("Error to parse YarnLocalResourceDescriptor from " + desc, e);
113121
}
114122
}
115123

124+
private static boolean validate(JsonNode node) {
125+
return !node.isNull()
126+
&& node.hasNonNull("resourceKey")
127+
&& node.hasNonNull("path")
128+
&& node.hasNonNull("size")
129+
&& node.hasNonNull("modificationTime")
130+
&& node.hasNonNull("visibility")
131+
&& node.hasNonNull("resourceType");
132+
}
133+
116134
static YarnLocalResourceDescriptor fromFileStatus(
117135
final String key,
118136
final FileStatus fileStatus,
@@ -132,14 +150,20 @@ static YarnLocalResourceDescriptor fromFileStatus(
132150

133151
@Override
134152
public String toString() {
135-
return String.format(
136-
STRING_FORMAT,
137-
resourceKey,
138-
path.toString(),
139-
size,
140-
modificationTime,
141-
visibility,
142-
resourceType);
153+
try {
154+
ObjectNode node = OBJECT_MAPPER.createObjectNode();
155+
node.put("resourceKey", resourceKey);
156+
node.put("path", path.toString());
157+
node.put("size", size);
158+
node.put("modificationTime", modificationTime);
159+
node.put("visibility", visibility.toString());
160+
node.put("resourceType", resourceType.toString());
161+
return OBJECT_MAPPER.writeValueAsString(node);
162+
} catch (JsonProcessingException e) {
163+
LOG.error("Could not serialize YarnLocalResourceDescriptor to String.", e);
164+
throw new RuntimeException(
165+
"Could not serialize YarnLocalResourceDescriptor[%s] to String.", e);
166+
}
143167
}
144168

145169
@Override

flink-yarn/src/test/java/org/apache/flink/yarn/YarnLocalResourceDescriptionTest.java

+9-3
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@
3131
/** Tests for the {@link YarnLocalResourceDescriptor}. */
3232
class YarnLocalResourceDescriptionTest {
3333

34-
private final String key = "flink.jar";
35-
private final Path path = new Path("hdfs://nn/tmp/flink.jar");
34+
private final String key = "fli'nk 2.jar";
35+
private final Path path = new Path("hdfs://nn/tmp/fli'nk 2.jar");
3636
private final long size = 100 * 1024 * 1024;
3737
private final long ts = System.currentTimeMillis();
3838

@@ -62,8 +62,14 @@ void testFromString() throws Exception {
6262
void testFromStringMalformed() {
6363
final String desc =
6464
String.format(
65-
"YarnLocalResourceDescriptor{key=%s path=%s size=%d modTime=%d visibility=%s}",
65+
"{'resourceKey':'%s','path':'%s','size':%s,'modificationTime':%s,'visibility':'%s'}",
6666
key, path, size, ts, LocalResourceVisibility.PUBLIC);
67+
assertThrows(desc);
68+
assertThrows("{}");
69+
assertThrows("{");
70+
}
71+
72+
private void assertThrows(final String desc) {
6773
assertThatThrownBy(() -> YarnLocalResourceDescriptor.fromString(desc))
6874
.isInstanceOf(FlinkException.class)
6975
.hasMessageContaining("Error to parse YarnLocalResourceDescriptor from " + desc);

0 commit comments

Comments
 (0)