org.eclipse.jetty.security.PropertyUserStore Maven / Gradle / Ivy
//
// ========================================================================
// Copyright (c) 1995-2018 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.security;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
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;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.PathWatcher;
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.JarFileResource;
import org.eclipse.jetty.util.resource.PathResource;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.security.Credential;
/**
* PropertyUserStore
*
* This class monitors a property file of the format mentioned below and notifies registered listeners of the changes to the the given file.
*
*
* username: password [,rolename ...]
*
*
* Passwords may be clear text, obfuscated or checksummed. The class com.eclipse.Util.Password should be used to generate obfuscated passwords or password
* checksums.
*
* If DIGEST Authentication is used, the password must be in a recoverable format, either plain text or OBF:.
*/
public class PropertyUserStore extends UserStore implements PathWatcher.Listener
{
private static final Logger LOG = Log.getLogger(PropertyUserStore.class);
protected Path _configPath;
protected PathWatcher _pathWatcher;
protected boolean _hotReload = false; // default is not to reload
protected boolean _firstLoad = true; // true if first load, false from that point on
protected List _listeners;
/**
* Get the config (as a string)
* @return the config path as a string
*/
public String getConfig()
{
if (_configPath != null)
return _configPath.toString();
return null;
}
/**
* Set the Config Path from a String reference to a file
* @param config the config file
*/
public void setConfig(String config)
{
if (config == null)
{
_configPath = null;
return;
}
try
{
Resource configResource = Resource.newResource(config);
if (configResource instanceof JarFileResource)
_configPath = extractPackedFile((JarFileResource)configResource);
else if (configResource instanceof PathResource)
_configPath = ((PathResource)configResource).getPath();
else if (configResource.getFile() != null)
setConfigFile(configResource.getFile());
else
throw new IllegalArgumentException(config);
}
catch (Exception e)
{
_configPath = null;
throw new IllegalStateException(e);
}
}
/**
* Get the Config {@link Path} reference.
* @return the config path
*/
public Path getConfigPath()
{
return _configPath;
}
/**
* Set the Config Path from a String reference to a file
* @param configFile the config file can a be a file path or a reference to a file within a jar file jar:file:
*/
@Deprecated
public void setConfigPath(String configFile)
{
setConfig(configFile);
}
private Path extractPackedFile( JarFileResource configResource )
throws IOException
{
String uri = configResource.getURI().toASCIIString();
int colon = uri.lastIndexOf(":");
int bang_slash = uri.indexOf("!/");
if (colon<0 || bang_slash<0 || colon>bang_slash)
throw new IllegalArgumentException("Not resolved JarFile resource: "+uri);
String entry_path = uri.substring(colon+2).replace("!/","__").replace('/','_').replace('.','_');
Path tmpDirectory = Files.createTempDirectory( "users_store" );
tmpDirectory.toFile().deleteOnExit();
Path extractedPath = Paths.get(tmpDirectory.toString(), entry_path);
Files.deleteIfExists( extractedPath );
extractedPath.toFile().deleteOnExit();
IO.copy(configResource.getInputStream(),new FileOutputStream(extractedPath.toFile()));
if (isHotReload())
{
LOG.warn("Cannot hot reload from packed configuration: {}",configResource);
setHotReload(false);
}
return extractedPath;
}
/**
* Set the Config Path from a {@link File} reference
* @param configFile the config file
*/
@Deprecated
public void setConfigPath(File configFile)
{
setConfigFile(configFile);
}
/**
* Set the Config Path from a {@link File} reference
* @param configFile the config file
*/
public void setConfigFile(File configFile)
{
if(configFile == null)
{
_configPath = null;
return;
}
_configPath = configFile.toPath();
}
/**
* Set the Config Path
* @param configPath the config path
*/
public void setConfigPath(Path configPath)
{
_configPath = configPath;
}
/**
* @return the resource associated with the configured properties file, creating it if necessary
* @throws IOException if unable to get the resource
*/
public Resource getConfigResource() throws IOException
{
if (_configPath==null)
return null;
return new PathResource(_configPath);
}
/**
* Is hot reload enabled on this user store
*
* @return true if hot reload was enabled before startup
*/
public boolean isHotReload()
{
return _hotReload;
}
/**
* Enable Hot Reload of the Property File
*
* @param enable true to enable, false to disable
*/
public void setHotReload(boolean enable)
{
if (isRunning())
{
throw new IllegalStateException("Cannot set hot reload while user store is running");
}
this._hotReload = enable;
}
@Override
public String toString()
{
StringBuilder s = new StringBuilder();
s.append(this.getClass().getName());
s.append("[");
s.append("users.count=").append(this.getKnownUserIdentities().size());
s.append("identityService=").append(this.getIdentityService());
s.append("]");
return s.toString();
}
/* ------------------------------------------------------------ */
protected void loadUsers() throws IOException
{
if (_configPath == null)
return;
if (LOG.isDebugEnabled())
{
LOG.debug("Loading " + this + " from " + _configPath);
}
Properties properties = new Properties();
Resource config = getConfigResource();
if (config!=null && config.exists())
properties.load(config.getInputStream());
Set known = new HashSet<>();
for (Map.Entry
© 2015 - 2025 Weber Informatics LLC | Privacy Policy