Skip to content
This repository has been archived by the owner on Nov 9, 2017. It is now read-only.

Commit

Permalink
fix bug where content length was being set (but we don't know the con…
Browse files Browse the repository at this point in the history
…tent length until its too late)

support security key/password in agent config
don't be as rigid in looking for replacement strings in the default properties file - use regex to find the values
rename the installer jar file
we still need to set the hostname/port to the ones of the server providing the content - there is a TODO in the code for this
  • Loading branch information
jmazzitelli committed Nov 13, 2015
1 parent 10595bd commit 26afa0d
Show file tree
Hide file tree
Showing 2 changed files with 134 additions and 63 deletions.
5 changes: 2 additions & 3 deletions dist/assembly.xml
Original file line number Diff line number Diff line change
Expand Up @@ -136,14 +136,14 @@
<directoryMode>0755</directoryMode>
</dependencySet>

<!-- put the agent installer to the same directory as previous artefact from the same reason -->
<!-- put the agent installer to the same directory as previous artifact from the same reason -->
<dependencySet>
<outputDirectory>${hawkular.dist.zip.root.dir}/standalone/configuration</outputDirectory>
<useProjectArtifact>false</useProjectArtifact>
<includes>
<include>org.hawkular.agent:hawkular-wildfly-agent-installer:jar</include>
</includes>
<outputFileNameMapping>agent-installer.${artifact.extension}</outputFileNameMapping>
<outputFileNameMapping>${artifact.artifactId}-${artifact.version}.${artifact.extension}</outputFileNameMapping>
<unpack>false</unpack>
<fileMode>0644</fileMode>
<directoryMode>0755</directoryMode>
Expand All @@ -166,7 +166,6 @@
<outputDirectory>${hawkular.dist.zip.root.dir}/modules</outputDirectory>
<useProjectArtifact>false</useProjectArtifact>
<includes>
<include>org.hawkular.agent:hawkular-monitor-wf-extension:zip:</include>
<include>org.hawkular.accounts:hawkular-accounts-keycloak-event-listener-rest:zip:module</include>
<include>org.hawkular.accounts:hawkular-accounts-keycloak-event-listener-jms:zip:module</include>
</includes>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,14 @@
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
Expand All @@ -53,13 +58,15 @@ public class WildFlyAgentServlet extends HttpServlet {
private static final int DEFAULT_AGENT_DOWNLOADS_LIMIT = 100;

// name of the property file stored in the root of the installer jar file
private static String AGENT_INSTALLER_PROPERTIES_FILE_NAME = "hawkular-wildfly-agent-installer.properties";
private static final String AGENT_INSTALLER_PROPERTIES_FILE_NAME = "hawkular-wildfly-agent-installer.properties";

private static String AGENT_INSTALLER_PROPERTY_WILDFLY_HOME = "wildfly-home";
private static String AGENT_INSTALLER_PROPERTY_MODULE_DIST = "module-dist";
private static String AGENT_INSTALLER_PROPERTY_HAWKULAR_SERVER = "hawkular-server-url";
private static String AGENT_INSTALLER_PROPERTY_USERNAME = "hawkular-username";
private static String AGENT_INSTALLER_PROPERTY_PASSWORD = "hawkular-password";
private static final String AGENT_INSTALLER_PROPERTY_WILDFLY_HOME = "wildfly-home";
private static final String AGENT_INSTALLER_PROPERTY_MODULE_DIST = "module-dist";
private static final String AGENT_INSTALLER_PROPERTY_HAWKULAR_SERVER = "hawkular-server-url";
private static final String AGENT_INSTALLER_PROPERTY_USERNAME = "hawkular-username";
private static final String AGENT_INSTALLER_PROPERTY_PASSWORD = "hawkular-password";
private static final String AGENT_INSTALLER_PROPERTY_SECURITY_KEY = "hawkular-security-key";
private static final String AGENT_INSTALLER_PROPERTY_SECURITY_SECRET = "hawkular-security-secret";

// the error code that will be returned if the server has been configured to disable agent updates
private static final int ERROR_CODE_AGENT_UPDATE_DISABLED = HttpServletResponse.SC_FORBIDDEN;
Expand All @@ -78,7 +85,12 @@ public void init() throws ServletException {
try {
log("Agent Module File: " + getAgentModuleDownloadFile());
} catch (Throwable t) {
throw new ServletException("Missing Hawkular WildFly Agent download file", t);
throw new ServletException("Missing Hawkular WildFly Agent module download file", t);
}
try {
log("Agent Installer File: " + getAgentInstallerDownloadFile());
} catch (Throwable t) {
throw new ServletException("Missing Hawkular WildFly Agent installer download file", t);
}
}

Expand Down Expand Up @@ -128,73 +140,133 @@ private void downloadAgentInstaller(HttpServletRequest req, HttpServletResponse
File agentInstallerJar = getAgentInstallerDownloadFile();
resp.setContentType("application/octet-stream");
resp.setHeader("Content-Disposition", "attachment; filename=" + agentInstallerJar.getName());
resp.setContentLength((int) agentInstallerJar.length());
resp.setDateHeader("Last-Modified", agentInstallerJar.lastModified());

ZipFile agentInstallerZip = new ZipFile(agentInstallerJar);
ZipOutputStream zos = new ZipOutputStream(resp.getOutputStream(), StandardCharsets.UTF_8);
final String wildflyHome = getValueFromQueryParam(req, AGENT_INSTALLER_PROPERTY_WILDFLY_HOME, null);
final String hawkularServer = getValueFromQueryParam(req, AGENT_INSTALLER_PROPERTY_HAWKULAR_SERVER,
"http://localhost:8080");
String defaultModuleDist = hawkularServer.startsWith("http:") ? hawkularServer +
"/hawkular/wildfly-agent/download" : "http://localhost:8080/wildfly-agent/download";
final String moduleDist = getValueFromQueryParam(req, AGENT_INSTALLER_PROPERTY_MODULE_DIST,
defaultModuleDist);
final String username = getValueFromQueryParam(req, AGENT_INSTALLER_PROPERTY_USERNAME, null);
final String password = getValueFromQueryParam(req, AGENT_INSTALLER_PROPERTY_PASSWORD, null);


for (Enumeration<? extends ZipEntry> e = agentInstallerZip.entries(); e.hasMoreElements(); ) {
ZipEntry entryIn = e.nextElement();
if (!entryIn.getName().equalsIgnoreCase(AGENT_INSTALLER_PROPERTIES_FILE_NAME)) {
// skip everything else
zos.putNextEntry(entryIn);
try (InputStream is = agentInstallerZip.getInputStream(entryIn)) {
byte[] buf = new byte[4096];
int len;
while ((len = (is.read(buf))) > 0) {
zos.write(buf, 0, len);
HashMap<String, String> newProperties = new HashMap<>();

String serverUrl = getValueFromQueryParam(req, AGENT_INSTALLER_PROPERTY_HAWKULAR_SERVER,
getDefaultHawkularServerUrl(false));
// strip any ending slash in the url since we don't want it
if (serverUrl.endsWith("/")) {
serverUrl = serverUrl.substring(0, serverUrl.length() - 1);
}
new URL(serverUrl); // validates the URL - this throws an exception if the URL is invalid

String moduleDist = getValueFromQueryParam(req, AGENT_INSTALLER_PROPERTY_MODULE_DIST,
serverUrl + "/hawkular/wildfly-agent/download");
String wildflyHome = getValueFromQueryParam(req, AGENT_INSTALLER_PROPERTY_WILDFLY_HOME, null);
String username = getValueFromQueryParam(req, AGENT_INSTALLER_PROPERTY_USERNAME, null);
String password = getValueFromQueryParam(req, AGENT_INSTALLER_PROPERTY_PASSWORD, null);
String securityKey = getValueFromQueryParam(req, AGENT_INSTALLER_PROPERTY_SECURITY_KEY, null);
String securitySecret = getValueFromQueryParam(req, AGENT_INSTALLER_PROPERTY_SECURITY_SECRET, null);
newProperties.put(AGENT_INSTALLER_PROPERTY_HAWKULAR_SERVER, serverUrl);
newProperties.put(AGENT_INSTALLER_PROPERTY_MODULE_DIST, moduleDist);
newProperties.put(AGENT_INSTALLER_PROPERTY_WILDFLY_HOME, wildflyHome);
newProperties.put(AGENT_INSTALLER_PROPERTY_USERNAME, username);
newProperties.put(AGENT_INSTALLER_PROPERTY_PASSWORD, password);
newProperties.put(AGENT_INSTALLER_PROPERTY_SECURITY_KEY, securityKey);
newProperties.put(AGENT_INSTALLER_PROPERTY_SECURITY_SECRET, securitySecret);

int contentLength = 0;

try (ZipFile agentInstallerZip = new ZipFile(agentInstallerJar);
ZipOutputStream zos = new ZipOutputStream(resp.getOutputStream(), StandardCharsets.UTF_8)) {

for (Enumeration<? extends ZipEntry> e = agentInstallerZip.entries(); e.hasMoreElements();) {
ZipEntry entryIn = e.nextElement();
if (!entryIn.getName().equalsIgnoreCase(AGENT_INSTALLER_PROPERTIES_FILE_NAME)) {
// skip everything else
zos.putNextEntry(entryIn);
try (InputStream is = agentInstallerZip.getInputStream(entryIn)) {
byte[] buf = new byte[4096];
int len;
while ((len = (is.read(buf))) > 0) {
zos.write(buf, 0, len);
contentLength += len;
}
}
}
} else {
zos.putNextEntry(new ZipEntry(AGENT_INSTALLER_PROPERTIES_FILE_NAME));
try (BufferedReader br =
new BufferedReader(
new InputStreamReader(agentInstallerZip.getInputStream(entryIn),
StandardCharsets.UTF_8)
)) {
String line;
while ((line = br.readLine()) != null) {
//todo: it'd be better to reuse the strings from the agent installer module to keep it DRY
// and resilient against the changes
if (wildflyHome != null && line.contains("#wildfly-home=/opt/wildfly")) {
line = line.replaceAll("#wildfly-home=/opt/wildfly", "wildfly-home=" + wildflyHome);
} else if (line.contains("#module-dist=")) {
line = line.replaceAll("#module-dist=", "module-dist=" + moduleDist);
} else if (line.contains("#hawkular-server-url=http://localhost:8080")) {
line = line.replaceAll("#hawkular-server-url=http://localhost:8080",
"hawkular-server-url=" + hawkularServer);
} else if (username != null && line.contains("hawkular-username=")) {
line = line.replaceAll("hawkular-username=", "hawkular-username=" + username);
} else if (password != null && line.contains("hawkular-password=")) {
line = line.replaceAll("hawkular-password=", "hawkular-password=" + password);
} else {
zos.putNextEntry(new ZipEntry(AGENT_INSTALLER_PROPERTIES_FILE_NAME));
try (BufferedReader br = new BufferedReader(
new InputStreamReader(agentInstallerZip.getInputStream(entryIn),
StandardCharsets.UTF_8))) {
String line;
while ((line = br.readLine()) != null) {
// for each new prop, see if current line sets it; if so, set the prop to our new value
for (Map.Entry<String, String> entry : newProperties.entrySet()) {
String newLine = getNewPropertyLine(line, entry.getKey(), entry.getValue());
if (!line.equals(newLine)) {
line = newLine;
break; // found the property, no need to keep going; go write the new line now
}
}
byte[] buf = (line + '\n').getBytes(StandardCharsets.UTF_8);
zos.write(buf);
contentLength += buf.length;
}
byte[] buf = (line + '\n').getBytes(StandardCharsets.UTF_8);
zos.write(buf);
}
}
zos.closeEntry();
}
zos.closeEntry();
}
zos.close();

// I don't think this will work, because if the content is large enough, we will have flushed
// the resp outputStream, at which time you can no longer send headers such as content length
// resp.setContentLength(contentLength);
log("Sending Hawkular WildFly Agent installer with content length of: " + contentLength);

} catch (Throwable t) {
String clientAddr = getClientAddress(req);
log("Failed to stream file to remote client [" + clientAddr + "]", t);
disableBrowserCache(resp);
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Failed to stream file");
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Failed to stream file: " + t);
}
}

/**
* Given a single line of a properties file, this will look to see if it contains a property we are looking for.
* If it does, we'll set it to the given new value.
* Note that this will look to see if the property is explicitly set
* or if it is commented out - if it is either, we'll modify the line regardless.
*
* If newPropValue is null, and the property is found in the line,
* the line returned will be a commented out property
*
* For example, if you pass in a lineToModify of "#wildfly-home=/opt/wildfly", propNameToFind of "wildfly-home"
* and newPropValue of "/usr/bin/wf", this method will return "wildfly-home=/usr/bin/wf". Notice that the given
* lineToModify was a commented out property - this method will detect that and still modify the line. This allows
* us to "uncomment" a property and set it to the new value.
*
* @param lineToModify the line to check if its what we want - we'll modify it and returned that modified string
* @param propNameToFind the property to search in the line
* @param newPropValue the new value to set the property to.
*
* @return if the line has the property we are looking for, a new line is returned with the property set to the
* given new value; otherwise, lineToModify is returned as-is
*/
private String getNewPropertyLine(String lineToModify, String propNameToFind, String newPropValue) {
// Look for the property (even if its commented out) and ignore spaces before and after the property name.
// We also don't care what the value was (doesn't matter what is after the = character).
Matcher m = Pattern.compile("#? *" + propNameToFind + " *=.*").matcher(lineToModify);
if (m.matches()) {
if (newPropValue != null) {
lineToModify = m.replaceAll(propNameToFind + "=" + newPropValue);
} else {
lineToModify = m.replaceAll("#" + propNameToFind + "=");
}
}
return lineToModify;
}

// TODO we need to return the URL of the server we are actually running in, not "localhost"
private String getDefaultHawkularServerUrl(boolean secure) {
String protocol = (secure) ? "https" : "http";
String hostname = "localhost";
int port = (secure) ? 8443 : 8080;

return String.format("%s://%s:%d", protocol, hostname, port);
}

private String getValueFromQueryParam(HttpServletRequest req, String key, String
defaultValue) throws IOException {
String value = req.getParameter(key);
Expand Down Expand Up @@ -303,7 +375,7 @@ private File getAgentInstallerDownloadFile() throws Exception {

File configDir = new File(System.getProperty("jboss.server.config.dir"));
for (File file : configDir.listFiles()) {
if (file.getName().startsWith("agent-installer") && file.getName().endsWith(".jar")) {
if (file.getName().startsWith("hawkular-wildfly-agent-installer") && file.getName().endsWith(".jar")) {
installerDownloadFile = file;
return installerDownloadFile;
}
Expand Down

0 comments on commit 26afa0d

Please sign in to comment.