[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:
Jesse McConnell 2009-06-30 21:23:49 +00:00
parent d0e514f192
commit 639d9712bc
11 changed files with 308 additions and 35 deletions

View File

@ -67,7 +67,7 @@ public class JettyPolicy extends Policy
public JettyPolicy( Set<String> policies, Map<String,String> properties )
{
_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.
refresh();

View File

@ -1,31 +1,31 @@
package org.eclipse.jetty.policy;
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
{
private PropertyEvaluator evaluator;
private Map<String, String> properties = new HashMap<String, String>();
private Principal[] principals;
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;
}
public PropertyEvaluator getEvaluator()
{
return evaluator;
}
public void setEvaluator( PropertyEvaluator evaluator )
{
this.evaluator = evaluator;
this.properties = properties;
}
public KeyStore getKeystore()
@ -33,8 +33,146 @@ public class PolicyContext
return keystore;
}
public void setKeystore( KeyStore keystores )
public void setKeystore( 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 );
}
}

View File

@ -15,6 +15,7 @@ package org.eclipse.jetty.policy;
import java.io.File;
import java.security.Principal;
import java.util.HashMap;
import java.util.Map;
@ -44,11 +45,11 @@ public class PropertyEvaluator extends HashMap<String,String>
*/
public String getSystemProperty(String name)
{
//System.out.println("Prop: " + name + " " + System.getProperty(name));
if (containsKey(name))
{
return get(name);
}
return System.getProperty(name);
}
@ -95,4 +96,7 @@ public class PropertyEvaluator extends HashMap<String,String>
return s;
}
}

View File

@ -63,21 +63,25 @@ public class GrantNode extends AbstractNode
public void expand( PolicyContext context ) throws PolicyException
{
signerArray = resolveToCertificates( context.getKeystore(), signers ); // TODO alter to support self:: etc
codebase = context.getEvaluator().evaluate( codebase );
if ( signers != null )
{
signerArray = resolveToCertificates( context.getKeystore(), signers ); // TODO alter to support self:: etc
}
codebase = context.evaluate( codebase );
if ( principalNodes != null )
{
Set<Principal> principalSet = new HashSet<Principal>(); // TODO address this not being accurate ( missing prinicipals in codestore)
for ( Iterator<PrincipalNode> i = principalNodes.iterator(); i.hasNext(); )
{
PrincipalNode node = i.next();
node.expand( context );
principalSet.add( node.toPrincipal( context ) );
}
principals = principalSet.toArray( new Principal[principalSet.size()] );
Set<Principal> principalSet = new HashSet<Principal>();
for ( Iterator<PrincipalNode> i = principalNodes.iterator(); i.hasNext(); )
{
PrincipalNode node = i.next();
node.expand( context );
principalSet.add( node.toPrincipal( context ) );
}
principals = principalSet.toArray( new Principal[principalSet.size()] );
}
context.setPrincipals( principals );
permissions = new Permissions();
for ( Iterator<PermissionNode> i = permissionNodes.iterator(); i.hasNext(); )
{
@ -85,6 +89,7 @@ public class GrantNode extends AbstractNode
node.expand( context );
permissions.add( node.toPermission() );
}
context.setPrincipals( null );
setExpanded( true );
}

View File

@ -48,7 +48,7 @@ public class KeystoreNode extends AbstractNode
public void expand( PolicyContext context ) throws PolicyException
{
url = context.getEvaluator().evaluate( url );
url = context.evaluate( url );
setExpanded( true );
}

View File

@ -75,7 +75,15 @@ public class PermissionNode extends AbstractNode
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 )
{

View File

@ -67,7 +67,7 @@ public class PrincipalNode extends AbstractNode
public void expand( PolicyContext context )
throws PolicyException
{
name = context.getEvaluator().evaluate( name );
name = context.evaluate( name );
setExpanded(true);
}

View File

@ -72,7 +72,6 @@ public class DefaultPolicyLoader
for ( Iterator<GrantNode> i = grantEntries.iterator(); i.hasNext(); )
{
GrantNode grant = i.next();
grant.expand( context );
PolicyEntry policy = new PolicyEntry();
@ -92,3 +91,8 @@ public class DefaultPolicyLoader
}
}
}

View File

@ -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;
}
}

View File

@ -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";
};

View File

@ -0,0 +1,6 @@
keystore "file://${basedir}/target/test-policy/jetty-policy.keystore", "jks";
grant principal "jetty-policy"
{
permission java.util.PropertyPermission "${{self}}", "read";
};