[BUG-27751] refactor property evaluator into PolicyContext and add support for resolving special cases ${{self}} and ${{alias:data}}
git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@447 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
parent
d0e514f192
commit
639d9712bc
|
@ -67,7 +67,7 @@ public class JettyPolicy extends Policy
|
||||||
public JettyPolicy( Set<String> policies, Map<String,String> properties )
|
public JettyPolicy( Set<String> policies, Map<String,String> properties )
|
||||||
{
|
{
|
||||||
_policies = policies;
|
_policies = policies;
|
||||||
_context.setEvaluator( new PropertyEvaluator( properties ) );
|
_context.setProperties( properties );
|
||||||
|
|
||||||
// we have the policies we need and an evaluator to reference, lets refresh and save the user a call.
|
// we have the policies we need and an evaluator to reference, lets refresh and save the user a call.
|
||||||
refresh();
|
refresh();
|
||||||
|
|
|
@ -1,31 +1,31 @@
|
||||||
package org.eclipse.jetty.policy;
|
package org.eclipse.jetty.policy;
|
||||||
|
|
||||||
import java.security.KeyStore;
|
import java.security.KeyStore;
|
||||||
|
import java.security.Principal;
|
||||||
|
import java.security.cert.Certificate;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.policy.component.GrantNode;
|
||||||
|
import org.eclipse.jetty.policy.component.PrincipalNode;
|
||||||
|
|
||||||
public class PolicyContext
|
public class PolicyContext
|
||||||
{
|
{
|
||||||
private PropertyEvaluator evaluator;
|
private Map<String, String> properties = new HashMap<String, String>();
|
||||||
|
|
||||||
|
private Principal[] principals;
|
||||||
private KeyStore keystore;
|
private KeyStore keystore;
|
||||||
|
|
||||||
public PolicyContext()
|
public void addProperty( String name, String value )
|
||||||
{
|
{
|
||||||
|
this.properties.put( name, value );
|
||||||
}
|
}
|
||||||
|
|
||||||
public PolicyContext( PropertyEvaluator evaluator )
|
public void setProperties( Map<String,String> properties )
|
||||||
{
|
{
|
||||||
this.evaluator = evaluator;
|
this.properties = properties;
|
||||||
}
|
|
||||||
|
|
||||||
public PropertyEvaluator getEvaluator()
|
|
||||||
{
|
|
||||||
return evaluator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setEvaluator( PropertyEvaluator evaluator )
|
|
||||||
{
|
|
||||||
this.evaluator = evaluator;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public KeyStore getKeystore()
|
public KeyStore getKeystore()
|
||||||
|
@ -33,8 +33,146 @@ public class PolicyContext
|
||||||
return keystore;
|
return keystore;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setKeystore( KeyStore keystores )
|
public void setKeystore( KeyStore keystore )
|
||||||
{
|
{
|
||||||
this.keystore = keystore;
|
this.keystore = keystore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Principal[] getPrincipals()
|
||||||
|
{
|
||||||
|
return principals;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPrincipals( Principal[] principals )
|
||||||
|
{
|
||||||
|
this.principals = principals;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String evaluate(String s) throws PolicyException
|
||||||
|
{
|
||||||
|
s = processProtocols( s );
|
||||||
|
|
||||||
|
int i1=0;
|
||||||
|
int i2=0;
|
||||||
|
|
||||||
|
while (s!=null)
|
||||||
|
{
|
||||||
|
i1=s.indexOf("${",i2);
|
||||||
|
if (i1<0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
i2=s.indexOf("}",i1+2);
|
||||||
|
if (i2<0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
String property=getProperty(s.substring(i1+2,i2));
|
||||||
|
|
||||||
|
s=s.substring(0,i1)+property+s.substring(i2+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String processProtocols( String s ) throws PolicyException
|
||||||
|
{
|
||||||
|
int i1=0;
|
||||||
|
int i2=0;
|
||||||
|
|
||||||
|
while (s!=null)
|
||||||
|
{
|
||||||
|
i1=s.indexOf("${{",i2);
|
||||||
|
if (i1<0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
i2=s.indexOf("}}",i1+2);
|
||||||
|
if (i2<0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
String property;
|
||||||
|
String target = s.substring(i1+3,i2);
|
||||||
|
|
||||||
|
if ( target.indexOf( ":" ) >= 0 )
|
||||||
|
{
|
||||||
|
String[] resolve = target.split( ":" );
|
||||||
|
property = resolve(resolve[0], resolve[1] );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
property = resolve( target, null );
|
||||||
|
}
|
||||||
|
s=s.substring(0,i1)+property+s.substring(i2+2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private String getProperty(String name)
|
||||||
|
{
|
||||||
|
if (properties.containsKey(name))
|
||||||
|
{
|
||||||
|
return properties.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return System.getProperty(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String resolve( String protocol, String data ) throws PolicyException
|
||||||
|
{
|
||||||
|
|
||||||
|
if ( "self".equals( protocol ) ) { //$NON-NLS-1$
|
||||||
|
// need expanding to list of principals in grant clause
|
||||||
|
if ( principals != null && principals.length != 0 )
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for ( int i = 0; i < principals.length; ++i )
|
||||||
|
{
|
||||||
|
sb.append( principals[i].getClass().getName() );
|
||||||
|
sb.append( " \"" );
|
||||||
|
sb.append( principals[i].getName() );
|
||||||
|
sb.append( "\" " );
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new PolicyException( "self can not be expanded, missing principals" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( "alias".equals( protocol ) )
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Certificate cert = keystore.getCertificate(data);
|
||||||
|
|
||||||
|
if ( cert instanceof X509Certificate )
|
||||||
|
{
|
||||||
|
Principal principal = ((X509Certificate) cert).getSubjectX500Principal();
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append( principal.getClass().getName() );
|
||||||
|
sb.append( " \"" );
|
||||||
|
sb.append( principal.getName() );
|
||||||
|
sb.append( "\" " );
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new PolicyException( "alias can not be expanded, bad cert" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch ( Exception e )
|
||||||
|
{
|
||||||
|
throw new PolicyException( "alias can not be expanded: " + data );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new PolicyException( "unknown protocol: " + protocol );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ package org.eclipse.jetty.policy;
|
||||||
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.security.Principal;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -44,11 +45,11 @@ public class PropertyEvaluator extends HashMap<String,String>
|
||||||
*/
|
*/
|
||||||
public String getSystemProperty(String name)
|
public String getSystemProperty(String name)
|
||||||
{
|
{
|
||||||
|
|
||||||
//System.out.println("Prop: " + name + " " + System.getProperty(name));
|
|
||||||
|
|
||||||
if (containsKey(name))
|
if (containsKey(name))
|
||||||
|
{
|
||||||
return get(name);
|
return get(name);
|
||||||
|
}
|
||||||
|
|
||||||
return System.getProperty(name);
|
return System.getProperty(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,4 +96,7 @@ public class PropertyEvaluator extends HashMap<String,String>
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,21 +63,25 @@ public class GrantNode extends AbstractNode
|
||||||
|
|
||||||
public void expand( PolicyContext context ) throws PolicyException
|
public void expand( PolicyContext context ) throws PolicyException
|
||||||
{
|
{
|
||||||
signerArray = resolveToCertificates( context.getKeystore(), signers ); // TODO alter to support self:: etc
|
if ( signers != null )
|
||||||
codebase = context.getEvaluator().evaluate( codebase );
|
{
|
||||||
|
signerArray = resolveToCertificates( context.getKeystore(), signers ); // TODO alter to support self:: etc
|
||||||
|
}
|
||||||
|
codebase = context.evaluate( codebase );
|
||||||
|
|
||||||
if ( principalNodes != null )
|
if ( principalNodes != null )
|
||||||
{
|
{
|
||||||
Set<Principal> principalSet = new HashSet<Principal>(); // TODO address this not being accurate ( missing prinicipals in codestore)
|
Set<Principal> principalSet = new HashSet<Principal>();
|
||||||
for ( Iterator<PrincipalNode> i = principalNodes.iterator(); i.hasNext(); )
|
for ( Iterator<PrincipalNode> i = principalNodes.iterator(); i.hasNext(); )
|
||||||
{
|
{
|
||||||
PrincipalNode node = i.next();
|
PrincipalNode node = i.next();
|
||||||
node.expand( context );
|
node.expand( context );
|
||||||
principalSet.add( node.toPrincipal( context ) );
|
principalSet.add( node.toPrincipal( context ) );
|
||||||
}
|
}
|
||||||
principals = principalSet.toArray( new Principal[principalSet.size()] );
|
principals = principalSet.toArray( new Principal[principalSet.size()] );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context.setPrincipals( principals );
|
||||||
permissions = new Permissions();
|
permissions = new Permissions();
|
||||||
for ( Iterator<PermissionNode> i = permissionNodes.iterator(); i.hasNext(); )
|
for ( Iterator<PermissionNode> i = permissionNodes.iterator(); i.hasNext(); )
|
||||||
{
|
{
|
||||||
|
@ -85,6 +89,7 @@ public class GrantNode extends AbstractNode
|
||||||
node.expand( context );
|
node.expand( context );
|
||||||
permissions.add( node.toPermission() );
|
permissions.add( node.toPermission() );
|
||||||
}
|
}
|
||||||
|
context.setPrincipals( null );
|
||||||
|
|
||||||
setExpanded( true );
|
setExpanded( true );
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ public class KeystoreNode extends AbstractNode
|
||||||
|
|
||||||
public void expand( PolicyContext context ) throws PolicyException
|
public void expand( PolicyContext context ) throws PolicyException
|
||||||
{
|
{
|
||||||
url = context.getEvaluator().evaluate( url );
|
url = context.evaluate( url );
|
||||||
|
|
||||||
setExpanded( true );
|
setExpanded( true );
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,7 +75,15 @@ public class PermissionNode extends AbstractNode
|
||||||
|
|
||||||
public void expand( PolicyContext context ) throws PolicyException
|
public void expand( PolicyContext context ) throws PolicyException
|
||||||
{
|
{
|
||||||
name = context.getEvaluator().evaluate( name );
|
if ( name != null )
|
||||||
|
{
|
||||||
|
name = context.evaluate( name ).trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( actions != null )
|
||||||
|
{
|
||||||
|
actions = context.evaluate( actions ).trim();
|
||||||
|
}
|
||||||
|
|
||||||
if ( signers != null )
|
if ( signers != null )
|
||||||
{
|
{
|
||||||
|
|
|
@ -67,7 +67,7 @@ public class PrincipalNode extends AbstractNode
|
||||||
public void expand( PolicyContext context )
|
public void expand( PolicyContext context )
|
||||||
throws PolicyException
|
throws PolicyException
|
||||||
{
|
{
|
||||||
name = context.getEvaluator().evaluate( name );
|
name = context.evaluate( name );
|
||||||
|
|
||||||
setExpanded(true);
|
setExpanded(true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,7 +72,6 @@ public class DefaultPolicyLoader
|
||||||
for ( Iterator<GrantNode> i = grantEntries.iterator(); i.hasNext(); )
|
for ( Iterator<GrantNode> i = grantEntries.iterator(); i.hasNext(); )
|
||||||
{
|
{
|
||||||
GrantNode grant = i.next();
|
GrantNode grant = i.next();
|
||||||
|
|
||||||
grant.expand( context );
|
grant.expand( context );
|
||||||
|
|
||||||
PolicyEntry policy = new PolicyEntry();
|
PolicyEntry policy = new PolicyEntry();
|
||||||
|
@ -92,3 +91,8 @@ public class DefaultPolicyLoader
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,102 @@
|
||||||
|
package org.eclipse.jetty.policy;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.security.Permission;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.policy.component.GrantNode;
|
||||||
|
import org.eclipse.jetty.policy.component.KeystoreNode;
|
||||||
|
import org.eclipse.jetty.policy.loader.PolicyFileScanner;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
public class TestPolicyContext
|
||||||
|
extends TestCase
|
||||||
|
{
|
||||||
|
public static final String __PRINCIPAL = "javax.security.auth.x500.X500Principal \"CN=Jetty Policy,OU=Artifact,O=Jetty Project,L=Earth,ST=Internet,C=US\"";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setUp()
|
||||||
|
throws Exception
|
||||||
|
{
|
||||||
|
|
||||||
|
System.setProperty( "basedir", getWorkingDirectory() );
|
||||||
|
|
||||||
|
super.setUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSelfPropertyExpansion() throws Exception
|
||||||
|
{
|
||||||
|
|
||||||
|
PolicyContext context = new PolicyContext();
|
||||||
|
PolicyFileScanner loader = new PolicyFileScanner();
|
||||||
|
List<GrantNode> grantEntries = new ArrayList<GrantNode>();
|
||||||
|
List<KeystoreNode> keystoreEntries = new ArrayList<KeystoreNode>();
|
||||||
|
|
||||||
|
File policyFile = new File( getWorkingDirectory() + "/src/test/resources/context/jetty-certificate.policy" );
|
||||||
|
|
||||||
|
loader.scanStream( new InputStreamReader( new FileInputStream( policyFile ) ), grantEntries, keystoreEntries );
|
||||||
|
|
||||||
|
for ( Iterator<KeystoreNode> i = keystoreEntries.iterator(); i.hasNext();)
|
||||||
|
{
|
||||||
|
KeystoreNode node = i.next();
|
||||||
|
node.expand( context );
|
||||||
|
|
||||||
|
context.setKeystore( node.toKeyStore() );
|
||||||
|
}
|
||||||
|
|
||||||
|
GrantNode grant = grantEntries.get( 0 );
|
||||||
|
grant.expand( context );
|
||||||
|
|
||||||
|
Permission perm = grant.getPermissions().elements().nextElement();
|
||||||
|
|
||||||
|
assertEquals( __PRINCIPAL, perm.getName() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAliasPropertyExpansion() throws Exception
|
||||||
|
{
|
||||||
|
|
||||||
|
PolicyContext context = new PolicyContext();
|
||||||
|
PolicyFileScanner loader = new PolicyFileScanner();
|
||||||
|
List<GrantNode> grantEntries = new ArrayList<GrantNode>();
|
||||||
|
List<KeystoreNode> keystoreEntries = new ArrayList<KeystoreNode>();
|
||||||
|
|
||||||
|
File policyFile = new File( getWorkingDirectory() + "/src/test/resources/context/jetty-certificate-alias.policy" );
|
||||||
|
|
||||||
|
loader.scanStream( new InputStreamReader( new FileInputStream( policyFile ) ), grantEntries, keystoreEntries );
|
||||||
|
|
||||||
|
for ( Iterator<KeystoreNode> i = keystoreEntries.iterator(); i.hasNext();)
|
||||||
|
{
|
||||||
|
KeystoreNode node = i.next();
|
||||||
|
node.expand( context );
|
||||||
|
|
||||||
|
context.setKeystore( node.toKeyStore() );
|
||||||
|
}
|
||||||
|
|
||||||
|
GrantNode grant = grantEntries.get( 0 );
|
||||||
|
grant.expand( context );
|
||||||
|
|
||||||
|
Permission perm = grant.getPermissions().elements().nextElement();
|
||||||
|
|
||||||
|
assertEquals( __PRINCIPAL, perm.getName() );
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getWorkingDirectory()
|
||||||
|
{
|
||||||
|
String cwd = System.getProperty( "basedir" );
|
||||||
|
|
||||||
|
if ( cwd == null )
|
||||||
|
{
|
||||||
|
cwd = System.getProperty( "user.dir" );
|
||||||
|
}
|
||||||
|
return cwd;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
keystore "file://${basedir}/target/test-policy/jetty-policy.keystore", "jks";
|
||||||
|
|
||||||
|
grant signedBy "jetty-policy-bad", codeBase "file://${basedir}/target/test-policy/jetty-test-policy-1.0-SNAPSHOT.jar"
|
||||||
|
{
|
||||||
|
permission java.util.PropertyPermission "${{alias:jetty-policy}}", "read";
|
||||||
|
};
|
|
@ -0,0 +1,6 @@
|
||||||
|
keystore "file://${basedir}/target/test-policy/jetty-policy.keystore", "jks";
|
||||||
|
|
||||||
|
grant principal "jetty-policy"
|
||||||
|
{
|
||||||
|
permission java.util.PropertyPermission "${{self}}", "read";
|
||||||
|
};
|
Loading…
Reference in New Issue