ng-storage updates

misc fixes
This commit is contained in:
Jason Rivard 2019-05-25 20:30:34 -04:00
parent ceb9337c65
commit 9dd4bc28b2
14 changed files with 197 additions and 253 deletions

View file

@ -77,19 +77,12 @@ public class UserIdentity implements Serializable, Comparable
{
return null;
}
if ( configuration.getLdapProfiles().containsKey( this.getLdapProfileID() ) )
{
return configuration.getLdapProfiles().get( this.getLdapProfileID() );
}
else
{
return null;
}
return configuration.getLdapProfiles().getOrDefault( this.getLdapProfileID(), null );
}
public String toString( )
{
return "UserIdentity" + JsonUtil.serialize( this );
return toDisplayString();
}
public String toObfuscatedKey( final PwmApplication pwmApplication )

View file

@ -1,143 +0,0 @@
/*
* Password Management Servlets (PWM)
* http://www.pwm-project.org
*
* Copyright (c) 2006-2009 Novell, Inc.
* Copyright (c) 2009-2018 The PWM Project
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package password.pwm.config.stored;
import password.pwm.bean.UserIdentity;
import password.pwm.config.StoredValue;
import java.time.Instant;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.locks.ReentrantReadWriteLock;
class NGStorageEngineImpl implements StorageEngine
{
private final Map<StoredConfigReference, StoredValue> values = new TreeMap<>();
private final Map<StoredConfigReference, ValueMetaData> metaValues = new TreeMap<>();
private final ConfigChangeLog changeLog;
private final ReentrantReadWriteLock bigLock = new ReentrantReadWriteLock();
private boolean writeLocked;
NGStorageEngineImpl(
final Map<StoredConfigReference, StoredValue> values,
final Map<StoredConfigReference, ValueMetaData> metaValues
)
{
this.values.putAll( values );
this.metaValues.putAll( metaValues );
changeLog = new ConfigChangeLogImpl( this );
}
public ConfigChangeLog changeLog( )
{
return changeLog;
}
public StoredValue read( final StoredConfigReference storedConfigReference )
{
bigLock.readLock().lock();
try
{
return values.get( storedConfigReference );
}
finally
{
bigLock.readLock().unlock();
}
}
public ValueMetaData readMetaData( final StoredConfigReference storedConfigReference )
{
return metaValues.get( storedConfigReference );
}
public void write( final StoredConfigReference reference, final StoredValue value, final UserIdentity userIdentity )
{
checkWriteLock();
bigLock.writeLock().lock();
try
{
if ( values.containsKey( reference ) )
{
changeLog.updateChangeLog( reference, values.get( reference ), value );
}
else
{
changeLog.updateChangeLog( reference, value );
}
values.put( reference, value );
final ValueMetaData valueMetaData = new ValueMetaData( Instant.now(), userIdentity );
metaValues.put( reference, valueMetaData );
}
finally
{
bigLock.writeLock().unlock();
}
}
public void reset( final StoredConfigReference reference, final UserIdentity userIdentity )
{
checkWriteLock();
bigLock.writeLock().lock();
try
{
if ( values.containsKey( reference ) )
{
changeLog.updateChangeLog( reference, values.get( reference ), null );
}
else
{
changeLog.updateChangeLog( reference, null );
}
values.remove( reference );
if ( metaValues.containsKey( reference ) )
{
final ValueMetaData valueMetaData = new ValueMetaData( Instant.now(), userIdentity );
metaValues.put( reference, valueMetaData );
}
}
finally
{
bigLock.writeLock().unlock();
}
}
private void checkWriteLock( )
{
if ( writeLocked )
{
throw new IllegalStateException( "attempt to modify writeLock configuration" );
}
}
public boolean isWriteLocked( )
{
return writeLocked;
}
public void writeLock( )
{
writeLocked = true;
}
}

View file

@ -25,7 +25,7 @@ package password.pwm.config.stored;
import password.pwm.bean.UserIdentity;
import password.pwm.config.StoredValue;
interface StorageEngine
public interface StorageEngine
{
StoredValue read( StoredConfigReference storedConfigReference );

View file

@ -22,15 +22,18 @@
package password.pwm.config.stored;
import lombok.Value;
import java.io.Serializable;
class StoredConfigReferenceBean implements StoredConfigReference, Serializable, Comparable
@Value
public class StoredConfigReferenceBean implements StoredConfigReference, Serializable, Comparable
{
private RecordType recordType;
private String recordID;
private String profileID;
StoredConfigReferenceBean( final RecordType type, final String recordID, final String profileID )
public StoredConfigReferenceBean( final RecordType type, final String recordID, final String profileID )
{
if ( type == null )
{
@ -47,36 +50,6 @@ class StoredConfigReferenceBean implements StoredConfigReference, Serializable,
this.profileID = profileID;
}
public RecordType getRecordType( )
{
return recordType;
}
public String getRecordID( )
{
return recordID;
}
@Override
public String getProfileID( )
{
return profileID;
}
@Override
public boolean equals( final Object o )
{
return o != null
&& o instanceof StoredConfigReference
&& toString().equals( o.toString() );
}
@Override
public int hashCode( )
{
return toString().hashCode();
}
@Override
public String toString( )

View file

@ -22,6 +22,7 @@
package password.pwm.config.stored;
import lombok.Builder;
import lombok.Value;
import password.pwm.bean.UserIdentity;
@ -29,6 +30,7 @@ import java.io.Serializable;
import java.time.Instant;
@Value
@Builder( toBuilder = true )
public class ValueMetaData implements Serializable
{
private Instant modifyDate;

View file

@ -0,0 +1,101 @@
/*
* Password Management Servlets (PWM)
* http://www.pwm-project.org
*
* Copyright (c) 2006-2009 Novell, Inc.
* Copyright (c) 2009-2018 The PWM Project
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package password.pwm.config.stored.ng;
import password.pwm.bean.UserIdentity;
import password.pwm.config.StoredValue;
import password.pwm.config.stored.StoredConfigReference;
import password.pwm.config.stored.ValueMetaData;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
class NGStorageEngineImpl
{
private final Map<StoredConfigReference, StoredValue> storedValues = new HashMap<>();
private final Map<StoredConfigReference, ValueMetaData> metaValues = new HashMap<>();
NGStorageEngineImpl()
{
}
NGStorageEngineImpl(
final Map<StoredConfigReference, StoredValue> storedValues,
final Map<StoredConfigReference, ValueMetaData> metaValues
)
{
this.storedValues.putAll( storedValues );
this.metaValues.putAll( metaValues );
}
StoredValue read( final StoredConfigReference storedConfigReference )
{
return storedValues.get( storedConfigReference );
}
ValueMetaData readMetaData( final StoredConfigReference storedConfigReference )
{
return metaValues.get( storedConfigReference );
}
void writeMetaData( final StoredConfigReference storedConfigReference, final ValueMetaData valueMetaData )
{
metaValues.put( storedConfigReference, valueMetaData );
}
void write( final StoredConfigReference reference, final StoredValue value, final UserIdentity userIdentity )
{
if ( reference != null )
{
if ( value != null )
{
storedValues.put( reference, value );
}
updateUserIdentity( reference, userIdentity );
}
}
void reset( final StoredConfigReference reference, final UserIdentity userIdentity )
{
if ( reference != null )
{
storedValues.remove( reference );
updateUserIdentity( reference, userIdentity );
}
}
private void updateUserIdentity(
final StoredConfigReference reference,
final UserIdentity userIdentity
)
{
metaValues.put(
reference,
ValueMetaData.builder().modifyDate( Instant.now() )
.userIdentity( userIdentity )
.build() );
}
}

View file

@ -20,12 +20,17 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package password.pwm.config.stored;
package password.pwm.config.stored.ng;
import password.pwm.bean.UserIdentity;
import password.pwm.config.PwmSetting;
import password.pwm.config.PwmSettingCategory;
import password.pwm.config.StoredValue;
import password.pwm.config.stored.ConfigurationProperty;
import password.pwm.config.stored.StoredConfigReference;
import password.pwm.config.stored.StoredConfigReferenceBean;
import password.pwm.config.stored.StoredConfiguration;
import password.pwm.config.stored.ValueMetaData;
import password.pwm.config.value.StringValue;
import password.pwm.error.PwmUnrecoverableException;
import password.pwm.util.java.JavaHelper;
@ -33,20 +38,19 @@ import password.pwm.util.logging.PwmLogger;
import password.pwm.util.secure.PwmSecurityKey;
import java.time.Instant;
import java.util.Map;
class NGStoredConfiguration implements StoredConfiguration
public class NGStoredConfiguration implements StoredConfiguration
{
private static final PwmLogger LOGGER = PwmLogger.forClass( NGStoredConfiguration.class );
private final PwmSecurityKey configurationSecurityKey;
private final StorageEngine engine;
private final NGStorageEngineImpl engine;
private boolean readOnly = false;
NGStoredConfiguration(
final Map<StoredConfigReference, StoredValue> values,
final Map<StoredConfigReference, ValueMetaData> metaValues,
final NGStorageEngineImpl storageEngine,
final PwmSecurityKey pwmSecurityKey )
{
engine = new NGStorageEngineImpl( values, metaValues );
engine = storageEngine;
configurationSecurityKey = pwmSecurityKey;
}
@ -65,7 +69,9 @@ class NGStoredConfiguration implements StoredConfiguration
return ( String ) storedValue.toNativeObject();
}
public void writeConfigProperty( final ConfigurationProperty configurationProperty, final String value )
public void writeConfigProperty(
final ConfigurationProperty configurationProperty,
final String value )
{
final StoredConfigReference storedConfigReference = new StoredConfigReferenceBean(
StoredConfigReference.RecordType.PROPERTY,
@ -73,7 +79,7 @@ class NGStoredConfiguration implements StoredConfiguration
null
);
final StoredValue storedValue = new StringValue( value );
engine.write( storedConfigReference, storedValue, null );
engine.write( storedConfigReference, storedValue, null );
}
public void resetSetting( final PwmSetting setting, final String profileID, final UserIdentity userIdentity )
@ -158,13 +164,13 @@ class NGStoredConfiguration implements StoredConfiguration
@Override
public boolean isLocked( )
{
return engine.isWriteLocked();
return readOnly;
}
@Override
public void lock( )
{
engine.writeLock();
readOnly = true;
}
@Override

View file

@ -20,11 +20,15 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package password.pwm.config.stored;
package password.pwm.config.stored.ng;
import password.pwm.bean.UserIdentity;
import password.pwm.config.PwmSetting;
import password.pwm.config.StoredValue;
import password.pwm.config.stored.StoredConfigReference;
import password.pwm.config.stored.StoredConfigReferenceBean;
import password.pwm.config.stored.StoredConfiguration;
import password.pwm.config.stored.ValueMetaData;
import password.pwm.config.value.StringValue;
import password.pwm.config.value.ValueFactory;
import password.pwm.error.PwmUnrecoverableException;
@ -38,8 +42,6 @@ import password.pwm.util.secure.PwmSecurityKey;
import java.io.InputStream;
import java.io.OutputStream;
import java.time.Instant;
import java.util.LinkedHashMap;
import java.util.Map;
public class NGStoredConfigurationFactory
@ -59,12 +61,10 @@ public class NGStoredConfigurationFactory
private static class XmlEngine
{
static NGStoredConfiguration fromXmlImpl( final InputStream inputStream )
throws PwmUnrecoverableException
{
final Map<StoredConfigReference, StoredValue> values = new LinkedHashMap<>();
final Map<StoredConfigReference, ValueMetaData> metaData = new LinkedHashMap<>();
final NGStorageEngineImpl storageEngine = new NGStorageEngineImpl();
final XmlDocument inputDocument = XmlFactory.getFactory().parseXml( inputStream );
final XmlElement rootElement = inputDocument.getRootElement();
@ -79,22 +79,21 @@ public class NGStoredConfigurationFactory
{
for ( final XmlElement propertyElement : loopElement.getChildren( StoredConfiguration.XML_ELEMENT_PROPERTY ) )
{
readInterestingElement( propertyElement, pwmSecurityKey, values, metaData );
readInterestingElement( propertyElement, pwmSecurityKey, storageEngine );
}
}
else if ( StoredConfiguration.XML_ELEMENT_SETTING.equals( loopElement.getName() ) )
{
readInterestingElement( loopElement, pwmSecurityKey, values, metaData );
readInterestingElement( loopElement, pwmSecurityKey, storageEngine );
}
}
return new NGStoredConfiguration( values, metaData, readSecurityKey( rootElement ) );
return new NGStoredConfiguration( storageEngine, pwmSecurityKey );
}
static void readInterestingElement(
final XmlElement loopElement,
final PwmSecurityKey pwmSecurityKey,
final Map<StoredConfigReference, StoredValue> values,
final Map<StoredConfigReference, ValueMetaData> metaData
final NGStorageEngineImpl engine
)
{
final StoredConfigReference reference = referenceForElement( loopElement );
@ -107,7 +106,7 @@ public class NGStoredConfigurationFactory
final StoredValue storedValue = readSettingValue( reference, loopElement, pwmSecurityKey );
if ( storedValue != null )
{
values.put( reference, storedValue );
engine.write( reference, storedValue, null );
}
}
break;
@ -115,17 +114,17 @@ public class NGStoredConfigurationFactory
case PROPERTY:
{
final StoredValue storedValue = readPropertyValue( reference, loopElement );
if ( storedValue != null )
{
engine.write( reference, storedValue, null );
}
}
break;
default:
throw new IllegalArgumentException( "unimplemented setting recordtype in reader" );
}
final ValueMetaData valueMetaData = readValueMetaData( loopElement );
if ( valueMetaData != null )
{
metaData.put( reference, valueMetaData );
}
engine.writeMetaData( reference, readValueMetaData( loopElement ) );
}
}
@ -246,7 +245,10 @@ public class NGStoredConfigurationFactory
? new UserIdentity( modifyUser, modifyUserProfile )
: null;
return new ValueMetaData( modifyDate, userIdentity );
return ValueMetaData.builder()
.modifyDate( modifyDate )
.userIdentity( userIdentity )
.build();
}
}

View file

@ -96,10 +96,17 @@ public class ConfigAccessFilter extends AbstractPwmFilter
}
}
final ConfigManagerBean configManagerBean = pwmRequest.getPwmApplication().getSessionStateService().getBean( pwmRequest, ConfigManagerBean.class );
if ( checkAuthentication( pwmRequest, configManagerBean ) == ProcessStatus.Continue )
try
{
filterChain.doFilter();
final ConfigManagerBean configManagerBean = pwmRequest.getPwmApplication().getSessionStateService().getBean( pwmRequest, ConfigManagerBean.class );
if ( checkAuthentication( pwmRequest, configManagerBean ) == ProcessStatus.Continue )
{
filterChain.doFilter();
}
}
catch ( PwmUnrecoverableException e )
{
pwmRequest.respondWithError( e.getErrorInformation() );
}
}
@ -120,21 +127,7 @@ public class ConfigAccessFilter extends AbstractPwmFilter
final ConfigurationReader runningConfigReader = ContextManager.getContextManager( pwmRequest.getHttpServletRequest().getSession() ).getConfigReader();
final StoredConfigurationImpl storedConfig = runningConfigReader.getStoredConfiguration();
if ( !checkIfAuthIsRequired( pwmRequest, storedConfig ) )
{
return ProcessStatus.Continue;
}
if ( !storedConfig.hasPassword() )
{
final String errorMsg = "config file does not have a configuration password";
final ErrorInformation errorInformation = new ErrorInformation( PwmError.CONFIG_FORMAT_ERROR, errorMsg, new String[]
{
errorMsg,
}
);
return denyAndError( pwmRequest, errorInformation );
}
checkPreconditions( pwmRequest, storedConfig );
if ( configManagerBean.isPasswordVerified() )
{
@ -252,15 +245,22 @@ public class ConfigAccessFilter extends AbstractPwmFilter
}
private static boolean checkIfAuthIsRequired(
private static void checkPreconditions(
final PwmRequest pwmRequest,
final StoredConfigurationImpl storedConfig
)
throws PwmUnrecoverableException
{
if ( storedConfig.hasPassword() )
if ( !storedConfig.hasPassword() )
{
return true;
final String errorMsg = "config file does not have a configuration password";
final ErrorInformation errorInformation = new ErrorInformation( PwmError.CONFIG_FORMAT_ERROR, errorMsg, new String[]
{
errorMsg,
}
);
throw new PwmUnrecoverableException( errorInformation );
}
if ( PwmApplicationMode.RUNNING == pwmRequest.getPwmApplication().getApplicationMode() )
@ -274,14 +274,7 @@ public class ConfigAccessFilter extends AbstractPwmFilter
{
throw new PwmUnrecoverableException( PwmError.ERROR_UNAUTHORIZED );
}
}
if ( PwmApplicationMode.CONFIGURATION != pwmRequest.getPwmApplication().getApplicationMode() )
{
return true;
}
return false;
}
}
private static boolean persistentLoginEnabled(
@ -410,8 +403,7 @@ public class ConfigAccessFilter extends AbstractPwmFilter
private static ProcessStatus denyAndError( final PwmRequest pwmRequest, final ErrorInformation errorInformation )
throws ServletException, PwmUnrecoverableException, IOException
{
pwmRequest.setAttribute( PwmRequestAttribute.PwmErrorInfo, errorInformation );
forwardToJsp( pwmRequest );
pwmRequest.respondWithError( errorInformation );
return ProcessStatus.Halt;
}

View file

@ -628,7 +628,7 @@ public class ForgottenPasswordServlet extends ControlledPwmServlet
final boolean otpPassed;
if ( otpUserRecord != null )
{
LOGGER.info( pwmRequest, () -> "checking entered OTP" );
LOGGER.info( pwmRequest, () -> "checking entered OTP for user " + userInfo.getUserIdentity().toDisplayString() );
try
{
// forces service to use proxy account to update (write) updated otp record if necessary.

View file

@ -339,7 +339,12 @@ public class HelpdeskServlet extends ControlledPwmServlet
String userID = null;
try
{
userID = pwmSession.getUserInfo().getUsername();
final UserInfo deletedUserInfo = UserInfoFactory.newUserInfoUsingProxy(
pwmApplication,
pwmSession.getLabel(),
userIdentity,
pwmRequest.getLocale() );
userID = deletedUserInfo.getUsername();
}
catch ( PwmUnrecoverableException e )
{

View file

@ -281,7 +281,8 @@ class PeopleSearchDataReader
userDetailBean.setLinks( makeUserDetailLinks( userIdentity ) );
LOGGER.trace( pwmRequest, () -> "finished building userDetail result in " + TimeDuration.fromCurrent( startTime ).asCompactString() );
LOGGER.trace( pwmRequest, () -> "finished building userDetail result of " + userIdentity
+ " in " + TimeDuration.fromCurrent( startTime ).asCompactString() );
storeDataInCache( pwmRequest.getPwmApplication(), cacheKey, userDetailBean );
return userDetailBean;
}
@ -480,6 +481,7 @@ class PeopleSearchDataReader
)
throws PwmUnrecoverableException
{
final Instant startTime = Instant.now();
final PwmApplication pwmApplication = pwmRequest.getPwmApplication();
final boolean enabled = peopleSearchConfiguration.isPhotosEnabled( pwmRequest.getUserInfoIfLoggedIn(), pwmRequest.getSessionLabel() );
if ( !enabled )
@ -492,7 +494,8 @@ class PeopleSearchDataReader
final boolean hasPermission = LdapPermissionTester.testUserPermissions( pwmApplication, pwmRequest.getSessionLabel(), userIdentity, permissions );
if ( !hasPermission )
{
LOGGER.debug( pwmRequest, () -> "user " + userIdentity.toString() + " failed photo query filter, denying photo view" );
LOGGER.debug( pwmRequest, () -> "user " + userIdentity + " failed photo query filter, denying photo view ("
+ TimeDuration.compactFromCurrent( startTime ) + ")" );
return null;
}
}
@ -512,7 +515,8 @@ class PeopleSearchDataReader
}
catch ( PwmOperationalException e )
{
LOGGER.debug( pwmRequest, () -> "determined " + userIdentity + " does not have photo data available while generating detail data" );
LOGGER.debug( pwmRequest, () -> "determined " + userIdentity.toDisplayString() + " does not have photo data available while generating detail data ("
+ TimeDuration.compactFromCurrent( startTime ) + ")" );
return null;
}
}

View file

@ -86,7 +86,8 @@ class LDAPNodeDataService implements NodeDataServiceProvider
}
catch ( ChaiException e )
{
throw new PwmUnrecoverableException( PwmError.ERROR_LDAP_DATA_ERROR, "error reading node service data: " + e.getMessage() );
throw new PwmUnrecoverableException( PwmError.ERROR_LDAP_DATA_ERROR, "error reading node service data "
+ ldapHelper.debugInfo() + ", error: " + e.getMessage() );
}
return returnData;
@ -116,7 +117,8 @@ class LDAPNodeDataService implements NodeDataServiceProvider
}
catch ( ChaiException e )
{
throw new PwmUnrecoverableException( PwmError.ERROR_LDAP_DATA_ERROR, "error writing node service data: " + e.getMessage() );
throw new PwmUnrecoverableException( PwmError.ERROR_LDAP_DATA_ERROR, "error writing node service data "
+ ldapHelper.debugInfo() + ", error: " + e.getMessage() );
}
}
@ -148,7 +150,8 @@ class LDAPNodeDataService implements NodeDataServiceProvider
}
catch ( ChaiException e )
{
throw new PwmUnrecoverableException( PwmError.ERROR_LDAP_DATA_ERROR, "error purging node service data: " + e.getMessage() );
throw new PwmUnrecoverableException( PwmError.ERROR_LDAP_DATA_ERROR, "error purging node service data "
+ ldapHelper.debugInfo() + ", error: " + e.getMessage() );
}
}
}
@ -189,5 +192,10 @@ class LDAPNodeDataService implements NodeDataServiceProvider
{
return new LDAPHelper( pwmApplication );
}
String debugInfo()
{
return "user '" + this.userIdentity.toDisplayString() + "' attribute '" + attr + "'";
}
}
}

View file

@ -178,6 +178,7 @@ public class XodusLocalDB implements LocalDBProvider
environmentConfig.setEnvCloseForcedly( true );
environmentConfig.setMemoryUsage( 50 * 1024 * 1024 );
environmentConfig.setEnvGatherStatistics( true );
environmentConfig.setGcUtilizationFromScratch( true );
for ( final Map.Entry<String, String> entry : initParameters.entrySet() )
{