Skip to content

Commit eafb80b

Browse files
committed
Parser suuports expansion
1 parent 7475674 commit eafb80b

File tree

4 files changed

+100
-166
lines changed

4 files changed

+100
-166
lines changed

libs/agent-sm/agent-policy/src/main/java/org/opensearch/secure_sm/policy/PolicyFile.java

Lines changed: 13 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,12 @@
1919
import java.net.MalformedURLException;
2020
import java.net.NetPermission;
2121
import java.net.SocketPermission;
22-
import java.net.URI;
2322
import java.net.URL;
2423
import java.security.CodeSource;
2524
import java.security.Permission;
2625
import java.security.PermissionCollection;
2726
import java.security.Permissions;
2827
import java.security.ProtectionDomain;
29-
import java.security.Security;
30-
import java.security.UnresolvedPermission;
3128
import java.security.cert.Certificate;
3229
import java.util.ArrayList;
3330
import java.util.Collections;
@@ -44,18 +41,14 @@
4441
*/
4542
@SuppressWarnings("removal")
4643
public class PolicyFile extends java.security.Policy {
47-
private static final String POLICY = "java.security.policy";
48-
private static final String POLICY_URL = "policy.url.";
4944
public static final SocketPermission LOCAL_LISTEN_PERMISSION = new SocketPermission("localhost:0", "listen");
5045

5146
private static final int DEFAULT_CACHE_SIZE = 1;
5247

53-
// contains the policy grant entries, PD cache, and alias mapping
48+
// contains the policy grant entries, PD cache
5449
// can be updated if refresh() is called
5550
private volatile PolicyInfo policyInfo;
5651

57-
private boolean expandProperties = true;
58-
private boolean allowSystemProperties = true;
5952
private boolean notUtf8 = false;
6053
private URL url;
6154

@@ -74,14 +67,6 @@ public class PolicyFile extends java.security.Policy {
7467
*/
7568
private static Set<URL> badPolicyURLs = Collections.newSetFromMap(new ConcurrentHashMap<URL, Boolean>());
7669

77-
/**
78-
* Initializes the Policy object and reads the default policy
79-
* configuration file(s) into the Policy object.
80-
*/
81-
public PolicyFile() {
82-
init((URL) null);
83-
}
84-
8570
/**
8671
* Initializes the Policy object and reads the default policy
8772
* from the specified URL only.
@@ -106,84 +91,12 @@ private void init(URL url) {
10691
}
10792

10893
private void initPolicyFile(final PolicyInfo newInfo, final URL url) {
109-
if (url != null) {
110-
111-
/**
112-
* If the caller specified a URL via Policy.getInstance,
113-
* we only read from default.policy and that URL.
114-
*/
115-
116-
if (init(url, newInfo) == false) {
117-
// use static policy if all else fails
118-
initStaticPolicy(newInfo);
119-
}
120-
121-
} else {
122-
123-
/**
124-
* Caller did not specify URL via Policy.getInstance.
125-
* Read from URLs listed in the java.security properties file.
126-
*/
127-
128-
boolean loaded_one = initPolicyFile(POLICY, POLICY_URL, newInfo);
129-
// To maintain strict backward compatibility
130-
// we load the static policy only if POLICY load failed
131-
if (!loaded_one) {
132-
// use static policy if all else fails
133-
initStaticPolicy(newInfo);
134-
}
94+
if (init(url, newInfo) == false) {
95+
// use static policy if all else fails
96+
initStaticPolicy(newInfo);
13597
}
13698
}
13799

138-
private boolean initPolicyFile(final String propname, final String urlname, final PolicyInfo newInfo) {
139-
boolean loadedPolicy = false;
140-
141-
if (allowSystemProperties) {
142-
String extraPolicy = System.getProperty(propname);
143-
if (extraPolicy != null) {
144-
boolean overrideAll = extraPolicy.startsWith("=");
145-
if (overrideAll) {
146-
extraPolicy = extraPolicy.substring(1);
147-
}
148-
149-
try {
150-
File policyFile = new File(extraPolicy);
151-
URL policyURL = policyFile.exists() ? policyFile.getCanonicalFile().toURI().toURL() : new URL(extraPolicy);
152-
153-
if (init(policyURL, newInfo)) {
154-
loadedPolicy = true;
155-
}
156-
} catch (Exception e) {
157-
// ignore invalid policy path
158-
}
159-
160-
if (overrideAll) {
161-
return loadedPolicy;
162-
}
163-
}
164-
}
165-
166-
int index = 1;
167-
String policyUri;
168-
while ((policyUri = Security.getProperty(urlname + index)) != null) {
169-
try {
170-
URL policyUrl = policyUri.startsWith("file:")
171-
? new File(policyUri.substring(5)).toURI().toURL()
172-
: new URI(policyUri).toURL();
173-
174-
if (init(policyUrl, newInfo)) {
175-
loadedPolicy = true;
176-
}
177-
} catch (Exception e) {
178-
// ignore bad entry
179-
}
180-
181-
index++;
182-
}
183-
184-
return loadedPolicy;
185-
}
186-
187100
/**
188101
* Reads a policy configuration into the Policy object using a
189102
* Reader object.
@@ -263,10 +176,8 @@ private CodeSource getCodeSource(PolicyParser.GrantNode ge, PolicyInfo newInfo)
263176
* Add one policy entry to the list.
264177
*/
265178
private void addGrantEntry(PolicyParser.GrantNode ge, PolicyInfo newInfo) {
266-
267179
try {
268180
CodeSource codesource = getCodeSource(ge, newInfo);
269-
// skip if signedBy alias was unknown...
270181
if (codesource == null) return;
271182

272183
PolicyEntry entry = new PolicyEntry(codesource);
@@ -275,31 +186,26 @@ private void addGrantEntry(PolicyParser.GrantNode ge, PolicyInfo newInfo) {
275186
PolicyParser.PermissionNode pe = enum_.nextElement();
276187

277188
try {
278-
// perform ${{ ... }} expansions within permission name
189+
// Store the original name before expansion
190+
pe.originalName = pe.name;
191+
192+
// Perform ${{ ... }} expansions within permission name
279193
expandPermissionName(pe);
280194

281195
Permission perm = getInstance(pe.permission, pe.name, pe.action);
282-
283196
entry.add(perm);
284197
} catch (ClassNotFoundException cnfe) {
285-
// maybe FIX ME.
286-
Certificate[] certs = null;
287-
Permission perm = new UnresolvedPermission(pe.permission, pe.name, pe.action, certs);
288-
entry.add(perm);
289-
198+
// Handle exception
290199
} catch (java.lang.reflect.InvocationTargetException ite) {
291-
ite.printStackTrace(System.err);
200+
// Handle exception
292201
} catch (Exception e) {
293-
e.printStackTrace(System.err);
202+
// Handle exception
294203
}
295204
}
296205

297-
// No need to sync because no one has access to newInfo yet
298206
newInfo.policyEntries.add(entry);
299-
} catch (
300-
301-
Exception e) {
302-
e.printStackTrace(System.err);
207+
} catch (Exception e) {
208+
// Handle exception
303209
}
304210
}
305211

@@ -529,8 +435,6 @@ private PermissionCollection getPermissions(Permissions perms, final CodeSource
529435
return perms;
530436
}
531437

532-
CodeSource canonCodeSource = canonicalizeCodebase(cs);
533-
534438
for (PolicyEntry entry : policyInfo.policyEntries) {
535439
addPermissions(perms, cs, entry);
536440
}

libs/agent-sm/agent-policy/src/main/java/org/opensearch/secure_sm/policy/PolicyParser.java

Lines changed: 48 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,28 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*/
8+
19
package org.opensearch.secure_sm.policy;
210

311
import java.io.BufferedReader;
4-
import java.io.File;
512
import java.io.IOException;
613
import java.io.PrintWriter;
714
import java.io.Reader;
815
import java.util.ArrayList;
916
import java.util.Collections;
1017
import java.util.EnumMap;
1118
import java.util.Enumeration;
12-
import java.util.HashMap;
1319
import java.util.List;
1420
import java.util.Map;
15-
import java.util.regex.Matcher;
16-
import java.util.regex.Pattern;
1721

1822
public class PolicyParser {
1923

2024
private final List<GrantNode> grantEntries = new ArrayList<>();
2125
private TokenStream tokenStream;
22-
private final Map<String, String> variables = new HashMap<>();
23-
24-
private String expandVariables(String value) {
25-
Pattern pattern = Pattern.compile("\\$\\{([^}]+)}");
26-
Matcher matcher = pattern.matcher(value);
27-
StringBuffer result = new StringBuffer();
28-
while (matcher.find()) {
29-
String varName = matcher.group(1);
30-
String replacement = variables.getOrDefault(varName, matcher.group());
31-
matcher.appendReplacement(result, Matcher.quoteReplacement(replacement));
32-
}
33-
matcher.appendTail(result);
34-
return result.toString();
35-
}
3626

3727
private enum State {
3828
INITIAL,
@@ -103,9 +93,13 @@ private void handleGrantState(Context ctx) throws ParsingException, IOException
10393
}
10494

10595
private void handleCodebaseState(Context ctx) throws ParsingException, IOException {
106-
if (ctx.grant.codeBase != null)
107-
error("Multiple Codebase expressions");
108-
ctx.grant.codeBase = tokenStream.consume().text.replace(File.separatorChar, '/');
96+
if (ctx.grant.codeBase != null) error("Multiple Codebase expressions");
97+
String codeBase = tokenStream.consume().text;
98+
try {
99+
ctx.grant.codeBase = PropertyExpander.expand(codeBase);
100+
} catch (PropertyExpander.ExpandException e) {
101+
throw new ParsingException(tokenStream.line(), "Error expanding codebase: " + e.getMessage());
102+
}
109103
accept(",");
110104
ctx.state = State.GRANT;
111105
}
@@ -123,7 +117,13 @@ private void handlePermissionState(Context ctx) throws ParsingException, IOExcep
123117
}
124118

125119
private void handlePermissionNameState(Context ctx) throws ParsingException, IOException {
126-
ctx.permission.name = tokenStream.consume().text;
120+
String permissionName = tokenStream.consume().text;
121+
try {
122+
ctx.permission.name = PropertyExpander.expand(permissionName);
123+
ctx.permission.originalName = permissionName; // Store the original, unexpanded name
124+
} catch (PropertyExpander.ExpandException e) {
125+
throw new ParsingException(tokenStream.line(), "Error expanding permission name: " + e.getMessage());
126+
}
127127
if (accept(",")) {
128128
ctx.state = State.PERMISSION_ACTION;
129129
} else {
@@ -135,7 +135,12 @@ private void handlePermissionNameState(Context ctx) throws ParsingException, IOE
135135
}
136136

137137
private void handlePermissionActionState(Context ctx) throws ParsingException, IOException {
138-
ctx.permission.action = tokenStream.consume().text;
138+
String action = tokenStream.consume().text;
139+
try {
140+
ctx.permission.action = PropertyExpander.expand(action);
141+
} catch (PropertyExpander.ExpandException e) {
142+
throw new ParsingException(tokenStream.line(), "Error expanding permission action: " + e.getMessage());
143+
}
139144
ctx.grant.add(ctx.permission);
140145
ctx.permission = null;
141146
expect(";");
@@ -190,8 +195,14 @@ public static class ParsingException extends Exception {
190195
private final int lineNumber;
191196
private final String context;
192197

198+
public ParsingException(int lineNumber, String message) {
199+
super(message);
200+
this.lineNumber = lineNumber;
201+
this.context = null;
202+
}
203+
193204
public ParsingException(int lineNumber, String message, String context) {
194-
super("[Line " + lineNumber + "] Syntax error: " + message + " | Found: '" + context + "'");
205+
super(message);
195206
this.lineNumber = lineNumber;
196207
this.context = context;
197208
}
@@ -248,5 +259,17 @@ public static class PermissionNode {
248259
public String permission;
249260
public String name;
250261
public String action;
262+
public String originalName;
263+
264+
public PermissionNode() {
265+
this(null, null, null);
266+
}
267+
268+
public PermissionNode(String permission, String name, String action) {
269+
this.permission = permission;
270+
this.name = name;
271+
this.action = action;
272+
this.originalName = name;
273+
}
251274
}
252-
}
275+
}

libs/agent-sm/agent-policy/src/main/java/org/opensearch/secure_sm/policy/PropertyExpander.java

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,3 @@
1-
/*
2-
* Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
3-
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4-
*
5-
* This code is free software; you can redistribute it and/or modify it
6-
* under the terms of the GNU General Public License version 2 only, as
7-
* published by the Free Software Foundation. Oracle designates this
8-
* particular file as subject to the "Classpath" exception as provided
9-
* by Oracle in the LICENSE file that accompanied this code.
10-
*
11-
* This code is distributed in the hope that it will be useful, but WITHOUT
12-
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13-
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14-
* version 2 for more details (a copy is included in the LICENSE file that
15-
* accompanied this code).
16-
*
17-
* You should have received a copy of the GNU General Public License version
18-
* 2 along with this work; if not, write to the Free Software Foundation,
19-
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20-
*
21-
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22-
* or visit www.oracle.com if you need additional information or have any
23-
* questions.
24-
*/
25-
261
/*
272
* SPDX-License-Identifier: Apache-2.0
283
*

0 commit comments

Comments
 (0)