Merge pull request #1545 from olamy/bugfix/1520

PropertyUserStore should extract packed config file #1520
This commit is contained in:
Jan Bartel 2017-05-23 11:51:48 +02:00 committed by GitHub
commit 79883c739d
2 changed files with 123 additions and 21 deletions

View File

@ -23,14 +23,16 @@ import org.eclipse.jetty.util.PathWatcher.PathWatchEvent;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.JarResource;
import org.eclipse.jetty.util.resource.PathResource;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.security.Credential;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
@ -57,6 +59,8 @@ public class PropertyUserStore extends UserStore implements PathWatcher.Listener
{
private static final Logger LOG = Log.getLogger(PropertyUserStore.class);
private static final String JAR_FILE = "jar:file:";
protected Path _configPath;
protected Resource _configResource;
@ -111,7 +115,7 @@ public class PropertyUserStore extends UserStore implements PathWatcher.Listener
/**
* Set the Config Path from a String reference to a file
* @param configFile the config file
* @param configFile the config file can a be a file path or a reference to a file within a jar file <code>jar:file:</code>
*/
public void setConfigPath(String configFile)
{
@ -119,10 +123,39 @@ public class PropertyUserStore extends UserStore implements PathWatcher.Listener
{
_configPath = null;
}
else
else if (new File( configFile ).exists())
{
_configPath = new File(configFile).toPath();
}
if ( !new File( configFile ).exists() && configFile.startsWith( JAR_FILE ))
{
// format of the url is jar:file:/foo/bar/beer.jar!/mountain_goat/pale_ale.txt
// ideally we'd like to extract this to Resource class?
try
{
_configPath = extractPackedFile( configFile );
}
catch ( IOException e )
{
throw new RuntimeException( "cannot extract file from url:" + configFile, e );
}
}
}
private Path extractPackedFile( String configFile )
throws IOException
{
int fileIndex = configFile.indexOf( "!" );
String entryPath = configFile.substring( fileIndex + 1, configFile.length() );
Path tmpDirectory = Files.createTempDirectory( "users_store" );
Path extractedPath = Paths.get(tmpDirectory.toString(), entryPath);
// delete if exists as copyTo do not overwrite
Files.deleteIfExists( extractedPath );
// delete on shutdown
extractedPath.toFile().deleteOnExit();
JarResource.newResource( configFile ).copyTo( tmpDirectory.toFile() );
return extractedPath;
}
/**

View File

@ -18,20 +18,6 @@
package org.eclipse.jetty.security;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.junit.Assume.*;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.Writer;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import org.eclipse.jetty.toolchain.test.FS;
import org.eclipse.jetty.toolchain.test.OS;
import org.eclipse.jetty.toolchain.test.TestingDir;
@ -40,6 +26,25 @@ import org.hamcrest.Matcher;
import org.junit.Rule;
import org.junit.Test;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.OutputStream;
import java.io.Writer;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertThat;
import static org.junit.Assume.assumeThat;
public class PropertyUserStoreTest
{
private final class UserCount implements PropertyUserStore.UserListener
@ -97,15 +102,55 @@ public class PropertyUserStoreTest
Path dir = testdir.getPath().toRealPath();
FS.ensureDirExists(dir.toFile());
File users = dir.resolve("users.txt").toFile();
try (Writer writer = new BufferedWriter(new FileWriter(users)))
writeUser( users );
return users;
}
private String initUsersPackedFileText()
throws Exception
{
Path dir = testdir.getPath().toRealPath();
FS.ensureDirExists( dir.toFile() );
File users = dir.resolve( "users.txt" ).toFile();
writeUser( users );
File usersJar = dir.resolve( "users.jar" ).toFile();
String entryPath = "mountain_goat/pale_ale.txt";
try (FileInputStream fileInputStream = new FileInputStream( users ))
{
try (OutputStream outputStream = new FileOutputStream( usersJar ))
{
try (JarOutputStream jarOutputStream = new JarOutputStream( outputStream ))
{
// add fake entry
jarOutputStream.putNextEntry( new JarEntry( "foo/wine" ) );
JarEntry jarEntry = new JarEntry( entryPath );
jarOutputStream.putNextEntry( jarEntry );
byte[] buffer = new byte[1024];
int bytesRead;
while ( ( bytesRead = fileInputStream.read( buffer ) ) != -1 )
{
jarOutputStream.write( buffer, 0, bytesRead );
}
// add fake entry
jarOutputStream.putNextEntry( new JarEntry( "foo/cheese" ) );
}
}
}
return "jar:file:" + usersJar.getCanonicalPath() + "!/" + entryPath;
}
private void writeUser(File usersFile)
throws Exception
{
try (Writer writer = new BufferedWriter(new FileWriter(usersFile)))
{
writer.append("tom: tom, roleA\n");
writer.append("dick: dick, roleB\n");
writer.append("harry: harry, roleA, roleB\n");
}
return users;
}
private void addAdditionalUser(File usersFile, String userRef) throws Exception
@ -137,6 +182,30 @@ public class PropertyUserStoreTest
userCount.awaitCount(3);
}
@Test
public void testPropertyUserStoreLoadFromJarFile() throws Exception
{
final UserCount userCount = new UserCount();
final String usersFile = initUsersPackedFileText();
PropertyUserStore store = new PropertyUserStore();
store.setConfigPath(usersFile);
store.registerUserListener(userCount);
store.start();
assertThat("Failed to retrieve UserIdentity directly from PropertyUserStore", //
store.getUserIdentity("tom"), notNullValue());
assertThat("Failed to retrieve UserIdentity directly from PropertyUserStore", //
store.getUserIdentity("dick"), notNullValue());
assertThat("Failed to retrieve UserIdentity directly from PropertyUserStore", //
store.getUserIdentity("harry"), notNullValue());
userCount.assertThatCount(is(3));
userCount.awaitCount(3);
}
@Test
public void testPropertyUserStoreLoadUpdateUser() throws Exception
{