Skip to content

Commit 45e80f5

Browse files
authored
Add PolicyValdidationException for entitlements (#120225)
This adds a new exception called PolicyValdidationException. This exception is intended to be used during construction of entitlements that require parsing additional arguments. This allows PolicyParser to give improved error messaging about a specific entitlement that may have failed during the parsing process.
1 parent e54bd24 commit 45e80f5

File tree

5 files changed

+91
-3
lines changed

5 files changed

+91
-3
lines changed

libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/NetworkEntitlement.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,10 @@ public NetworkEntitlement(List<String> actionsList) {
4747
for (String actionString : actionsList) {
4848
var action = ACTION_MAP.get(actionString);
4949
if (action == null) {
50-
throw new IllegalArgumentException("unknown network action [" + actionString + "]");
50+
throw new PolicyValidationException("unknown network action [" + actionString + "]");
5151
}
5252
if ((actionsInt & action) == action) {
53-
throw new IllegalArgumentException(Strings.format("network action [%s] specified multiple times", actionString));
53+
throw new PolicyValidationException(Strings.format("network action [%s] specified multiple times", actionString));
5454
}
5555
actionsInt |= action;
5656
}

libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/PolicyParser.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
package org.elasticsearch.entitlement.runtime.policy;
1111

12+
import org.elasticsearch.xcontent.XContentLocation;
1213
import org.elasticsearch.xcontent.XContentParser;
1314
import org.elasticsearch.xcontent.XContentParserConfiguration;
1415
import org.elasticsearch.xcontent.yaml.YamlXContent;
@@ -119,6 +120,7 @@ protected Scope parseScope(String scopeName) throws IOException {
119120
}
120121

121122
protected Entitlement parseEntitlement(String scopeName, String entitlementType) throws IOException {
123+
XContentLocation startLocation = policyParser.getTokenLocation();
122124
Class<?> entitlementClass = EXTERNAL_ENTITLEMENTS.get(entitlementType);
123125

124126
if (entitlementClass == null) {
@@ -170,7 +172,10 @@ protected Entitlement parseEntitlement(String scopeName, String entitlementType)
170172
try {
171173
return (Entitlement) entitlementConstructor.newInstance(parameterValues);
172174
} catch (InvocationTargetException | InstantiationException | IllegalAccessException e) {
173-
throw new IllegalStateException("internal error");
175+
if (e.getCause() instanceof PolicyValidationException piae) {
176+
throw newPolicyParserException(startLocation, scopeName, entitlementType, piae);
177+
}
178+
throw new IllegalStateException("internal error", e);
174179
}
175180
}
176181

@@ -191,4 +196,13 @@ protected PolicyParserException newPolicyParserException(String scopeName, Strin
191196
message
192197
);
193198
}
199+
200+
protected PolicyParserException newPolicyParserException(
201+
XContentLocation location,
202+
String scopeName,
203+
String entitlementType,
204+
PolicyValidationException cause
205+
) {
206+
return PolicyParserException.newPolicyParserException(location, policyName, scopeName, entitlementType, cause);
207+
}
194208
}

libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/PolicyParserException.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,36 @@ public static PolicyParserException newPolicyParserException(
8686
}
8787
}
8888

89+
public static PolicyParserException newPolicyParserException(
90+
XContentLocation location,
91+
String policyName,
92+
String scopeName,
93+
String entitlementType,
94+
PolicyValidationException cause
95+
) {
96+
assert (scopeName != null);
97+
return new PolicyParserException(
98+
"["
99+
+ location.lineNumber()
100+
+ ":"
101+
+ location.columnNumber()
102+
+ "] policy parsing error for ["
103+
+ policyName
104+
+ "] in scope ["
105+
+ scopeName
106+
+ "] for entitlement type ["
107+
+ entitlementType
108+
+ "]: "
109+
+ cause.getMessage(),
110+
cause
111+
);
112+
}
113+
89114
private PolicyParserException(String message) {
90115
super(message);
91116
}
117+
118+
private PolicyParserException(String message, PolicyValidationException cause) {
119+
super(message, cause);
120+
}
92121
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
package org.elasticsearch.entitlement.runtime.policy;
11+
12+
/**
13+
* This exception is used to track validation errors thrown during the construction
14+
* of entitlements. By using this instead of other exception types the policy
15+
* parser is able to wrap this exception with a line/character number for
16+
* additional useful error information.
17+
*/
18+
class PolicyValidationException extends RuntimeException {
19+
20+
PolicyValidationException(String message) {
21+
super(message);
22+
}
23+
24+
PolicyValidationException(String message, Throwable cause) {
25+
super(message, cause);
26+
}
27+
}

libs/entitlement/src/test/java/org/elasticsearch/entitlement/runtime/policy/PolicyParserTests.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,24 @@ public void testParseNetwork() throws IOException {
6868
assertEquals(expected, parsedPolicy);
6969
}
7070

71+
public void testParseNetworkIllegalAction() throws IOException {
72+
var ex = expectThrows(PolicyParserException.class, () -> new PolicyParser(new ByteArrayInputStream("""
73+
entitlement-module-name:
74+
- network:
75+
actions:
76+
- listen
77+
- doesnotexist
78+
- connect
79+
""".getBytes(StandardCharsets.UTF_8)), "test-policy.yaml", false).parsePolicy());
80+
assertThat(
81+
ex.getMessage(),
82+
equalTo(
83+
"[2:5] policy parsing error for [test-policy.yaml] in scope [entitlement-module-name] for entitlement type [network]: "
84+
+ "unknown network action [doesnotexist]"
85+
)
86+
);
87+
}
88+
7189
public void testParseCreateClassloader() throws IOException {
7290
Policy parsedPolicy = new PolicyParser(new ByteArrayInputStream("""
7391
entitlement-module-name:

0 commit comments

Comments
 (0)