apache / jmeter

Apache JMeter open-source load testing tool for analyzing and measuring the performance of a variety of services
https://jmeter.apache.org/
Apache License 2.0
8.26k stars 2.09k forks source link

add skeleton-key http authentication to AccessLogSampler #2175

Open asfimport opened 15 years ago

asfimport commented 15 years ago

Eric Jensen (Bug 46237): The attached source files add a SkeletonAuthorizationFilter for the AccessLogSampler that reads the HTTP basic auth field of the log file and uses it plus a pre-configured skeleton key password via the "skeleton.password" property to authenticate the corresponding request. This is useful for load testing sites whose logs include behaviors that would differ across users. The test environment can be updated such that everyone's password is "skeleton" and authentication will be performed appropriately.

This is achieved without patching any existing jmeter source.

Also included is a FilterChain which allows specifying multiple filters as properties and calls them all (in no particular order), i.e.

use cookies per ip (session) and basic auth

accesslog.sampler.filterchain.1=org.apache.jmeter.protocol.http.util.accesslog.SkeletonAuthorizationFilter accesslog.sampler.filterchain.2=org.apache.jmeter.protocol.http.util.accesslog.SessionFilter

PS: someone should add the ability for the log parsers to stop the test when they hit the end of the file

PPS: i had to implement TestCloneable on these Filters otherwise they would be silently ignored by AccessLogSampler This is bad behavior and potentially a bug, as LogFilter does not implement it.

Created attachment accesslog_skel_auth.tar: SkeletonAuthManager.java, SkeletonAuthorizationFilter.java, and FilterChain.java

OS: All

asfimport commented 15 years ago

Eric Jensen (migrated from Bugzilla): Created attachment SkeletonAuthorizationFilter.java: updated version that grabs the username regexp from a property

SkeletonAuthorizationFilter.java ````diff package org.apache.jmeter.protocol.http.util.accesslog; import java.io.Serializable; import org.apache.jmeter.protocol.http.control.AuthManager; import org.apache.jmeter.protocol.http.control.SkeletonAuthManager; import org.apache.jmeter.protocol.http.sampler.HTTPSamplerBase; import org.apache.jmeter.testelement.TestCloneable; import org.apache.jmeter.testelement.TestElement; import org.apache.jmeter.util.JMeterUtils; import org.apache.jorphan.logging.LoggingManager; import org.apache.log.Logger; import org.apache.oro.text.regex.Pattern; import org.apache.oro.text.regex.Perl5Compiler; import org.apache.oro.text.regex.Perl5Matcher; /** * Provides username parsing from logs for the AccessLog Sampler, overrides AuthManager with one * that uses the username from the log (or no auth if it is "-") and a single password from the property "skeleton.password" * @author ej */ public class SkeletonAuthorizationFilter implements Filter, Serializable, TestCloneable { private static final long serialVersionUID = -480275799056489612L; private static final Logger log = LoggingManager.getLoggerForClass(); private static final AuthManager NULL_AUTH_MANAGER = new SkeletonAuthManager(); private static final String SKELETON_PASSWORD = JMeterUtils.getPropDefault("skeleton.password", "skeleton"); private static final String USERNAME_REGEX = JMeterUtils.getPropDefault("skeleton.username.regexp", "^\\S+ - (\\S+)"); private static boolean first = true; /** * */ public SkeletonAuthorizationFilter() { } public Object clone() { // no state, nothing to clone return new SkeletonAuthorizationFilter(); } protected String getUser(String logLine) { Pattern incIp = JMeterUtils.getPatternCache().getPattern(USERNAME_REGEX, Perl5Compiler.READ_ONLY_MASK | Perl5Compiler.SINGLELINE_MASK); if (first) { log.debug("skeleton.username.regexp = " + USERNAME_REGEX + " read as " + incIp.getPattern() + " EOL"); first = false; } Perl5Matcher matcher = JMeterUtils.getMatcher(); if (!matcher.contains(logLine, incIp)) { log.debug("line did not match skeleton.username.regexp"); return null; } return matcher.getMatch().group(1); } public boolean isFiltered( String logLine, TestElement sampler ) { String user = getUser(logLine); log.debug("getUser found " + user + " for " + logLine); if (user == null) { log.warn("log line didn't match user pattern, assuming no auth: " + logLine); ((HTTPSamplerBase)sampler).setAuthManager(NULL_AUTH_MANAGER); } else if (user.equals("-")) ((HTTPSamplerBase)sampler).setAuthManager(NULL_AUTH_MANAGER); else ((HTTPSamplerBase)sampler).setAuthManager(new SkeletonAuthManager(user, SKELETON_PASSWORD)); return false; } /* * (non-Javadoc) * * @see org.apache.jmeter.protocol.http.util.accesslog.Filter#filter() */ public void reset() { } /* * (non-Javadoc) * * @see org.apache.jmeter.protocol.http.util.accesslog.Filter#excludeFiles(java.lang.String[]) */ public void excludeFiles(String[] filenames) { } /* * (non-Javadoc) * * @see org.apache.jmeter.protocol.http.util.accesslog.Filter#excludePattern(java.lang.String[]) */ public void excludePattern(String[] regexp) { } /* * (non-Javadoc) * * @see org.apache.jmeter.protocol.http.util.accesslog.Filter#filter(java.lang.String) */ public String filter(String text) { return text; } /* * (non-Javadoc) * * @see org.apache.jmeter.protocol.http.util.accesslog.Filter#includeFiles(java.lang.String[]) */ public void includeFiles(String[] filenames) { } /* * (non-Javadoc) * * @see org.apache.jmeter.protocol.http.util.accesslog.Filter#includePattern(java.lang.String[]) */ public void includePattern(String[] regexp) { } /* * (non-Javadoc) * * @see org.apache.jmeter.protocol.http.util.accesslog.Filter#setReplaceExtension(java.lang.String, * java.lang.String) */ public void setReplaceExtension(String oldextension, String newextension) { } } ````