PropertyUserStore should extract packed config file #1520

Signed-off-by: olivier lamy <olamy@webtide.com>
This commit is contained in:
olivier lamy 2017-05-12 14:57:46 +10:00
parent 2679715a30
commit e9f75e81d9
2 changed files with 141 additions and 21 deletions

View File

@ -28,8 +28,10 @@ import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.security.Credential;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashSet;
@ -38,6 +40,8 @@ import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
/**
* PropertyUserStore
@ -57,6 +61,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 +117,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 +125,55 @@ 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 filePath = configFile.substring( JAR_FILE.length(), fileIndex );
String entryPath = configFile.substring( fileIndex + 1, configFile.length() );
try (FileInputStream fileInputStream = new FileInputStream( new File( filePath ) ))
{
ZipInputStream zin = new ZipInputStream( fileInputStream );
for ( ZipEntry e; ( e = zin.getNextEntry() ) != null; )
{
if ( e.getName().equals( entryPath ) )
{
Path extractedPath = Files.createTempFile( "users_store", ".tmp" );
byte[] buffer = new byte[1024];
int bytesRead;
try (OutputStream textOutputStream = Files.newOutputStream( extractedPath ))
{
while ( ( bytesRead = zin.read( buffer ) ) != -1 )
{
textOutputStream.write( buffer, 0, bytesRead );
}
}
return extractedPath;
}
}
}
throw new RuntimeException( "cannot find file from url " + configFile );
}
/**

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
{