Skip to content

Commit 5c26635

Browse files
committed
Download ability and removed "composite"
First pass at downloading files Removed all mentions of composite because it is confusing Bumped pom version
1 parent 0320c87 commit 5c26635

File tree

13 files changed

+609
-13
lines changed

13 files changed

+609
-13
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ Steps:
166166
3. Assign systems to profile
167167
4. Assign profiles to users
168168
5. Users can login to create sessions on assigned systems
169-
6. Start a composite SSH session or create and execute a script across multiple sessions
169+
6. Start a SSH session or create and execute a script across multiple sessions
170170
7. Add additional public keys to systems
171171
8. Disable any administrative public key forcing key rotation.
172172
9. Audit session history

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<modelVersion>4.0.0</modelVersion>
55
<groupId>com.keybox</groupId>
66
<artifactId>keybox</artifactId>
7-
<version>2.85.01-looker-2017-04-07</version>
7+
<version>2.85.01-looker-2017-05-12</version>
88
<packaging>war</packaging>
99
<name>KeyBox</name>
1010
<properties>

src/main/java/com/keybox/manage/action/AuthKeysAction.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ public String downloadPvtKey() {
209209
servletResponse.getOutputStream().close();
210210
} catch (Exception ex) {
211211
log.error(ex.toString(), ex);
212+
addActionError("Exception occurred during download of private key: " + ex.getMessage());
212213
}
213214
}
214215
//remove pvt key
Lines changed: 268 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,268 @@
1+
/**
2+
* Copyright 2013 Sean Kavanagh - [email protected]
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.keybox.manage.action;
17+
18+
import com.keybox.common.util.AuthUtil;
19+
import com.keybox.manage.db.SystemStatusDB;
20+
import com.keybox.manage.model.HostSystem;
21+
import com.keybox.manage.model.SchSession;
22+
import com.keybox.manage.util.DBUtils;
23+
import com.keybox.manage.util.SSHUtil;
24+
import com.opensymphony.xwork2.ActionSupport;
25+
import org.apache.struts2.convention.annotation.Action;
26+
import org.apache.struts2.convention.annotation.Result;
27+
import org.apache.struts2.interceptor.ServletRequestAware;
28+
import org.apache.struts2.interceptor.ServletResponseAware;
29+
import org.slf4j.Logger;
30+
import org.slf4j.LoggerFactory;
31+
32+
import javax.servlet.http.HttpServletRequest;
33+
import javax.servlet.http.HttpServletResponse;
34+
import java.io.File;
35+
import java.io.FileInputStream;
36+
import java.util.*;
37+
38+
public class DownloadAction extends ActionSupport implements ServletRequestAware, ServletResponseAware {
39+
40+
private static Logger log = LoggerFactory.getLogger(DownloadAction.class);
41+
42+
String downloadContentType;
43+
String downloadFileName;
44+
List<Long> idList = new ArrayList<Long>();
45+
String pullFile = "~/full_path_to_file";
46+
List<HostSystem> hostSystemList;
47+
HostSystem pendingSystemStatus;
48+
HostSystem currentSystemStatus;
49+
HttpServletRequest servletRequest;
50+
HttpServletResponse servletResponse;
51+
FileInputStream fileInputStream = null;
52+
53+
public static final String DOWNLOAD_PATH = DBUtils.class.getClassLoader().getResource(".").getPath() + "../download";
54+
55+
56+
@Action(value = "/admin/setDownload",
57+
results = {
58+
@Result(name = "success", location = "/admin/download.jsp")
59+
}
60+
)
61+
public String setDownload() throws Exception {
62+
Long userId= AuthUtil.getUserId(servletRequest.getSession());
63+
64+
SystemStatusDB.setInitialSystemStatus(idList, userId, AuthUtil.getUserType(servletRequest.getSession()));
65+
return SUCCESS;
66+
67+
}
68+
69+
70+
@Action(value = "/admin/pull",
71+
results = {
72+
@Result(name = "input", location = "/admin/download.jsp"),
73+
@Result(name = "success", location = "/admin/download_result.jsp")
74+
}
75+
)
76+
public String pull() {
77+
78+
Long userId=AuthUtil.getUserId(servletRequest.getSession());
79+
Long sessionId=AuthUtil.getSessionId(servletRequest.getSession());
80+
try {
81+
82+
//get next pending system
83+
pendingSystemStatus = SystemStatusDB.getNextPendingSystem(userId);
84+
if (pendingSystemStatus != null) {
85+
//get session for system
86+
SchSession session = null;
87+
for(Integer instanceId : SecureShellAction.getUserSchSessionMap().get(sessionId).getSchSessionMap().keySet()) {
88+
89+
//if host system id matches pending system then download
90+
if(pendingSystemStatus.getId().equals(SecureShellAction.getUserSchSessionMap().get(sessionId).getSchSessionMap().get(instanceId).getHostSystem().getId())){
91+
session = SecureShellAction.getUserSchSessionMap().get(sessionId).getSchSessionMap().get(instanceId);
92+
}
93+
}
94+
95+
if(session!=null) {
96+
97+
// clean filename paths out
98+
downloadFileName = cleanFilenameForDownloadFile(pullFile);
99+
100+
//pull download from system, saving with systemId and userId to make it unique for that system/user
101+
currentSystemStatus = SSHUtil.pullDownload(pendingSystemStatus, session.getSession(), pullFile,
102+
buildFilePath(cleanDownloadFilename(pullFile, pendingSystemStatus.getId()), userId));
103+
104+
//update system status
105+
SystemStatusDB.updateSystemStatus(currentSystemStatus, userId);
106+
107+
pendingSystemStatus = SystemStatusDB.getNextPendingSystem(userId);
108+
}
109+
110+
}
111+
hostSystemList = SystemStatusDB.getAllSystemStatus(userId);
112+
113+
114+
} catch (Exception e) {
115+
log.error(e.toString(), e);
116+
addActionError("Exception occurred during pull to keybox: " + e.getMessage());
117+
return ERROR;
118+
}
119+
120+
return SUCCESS;
121+
}
122+
123+
@Action(value = "/admin/download",
124+
results = {
125+
@Result(name = "success",
126+
type = "stream",
127+
params = { "contentType", "application/octet-stream",
128+
"inputName", "fileInputStream",
129+
"contentDisposition", "attachment;filename=${downloadFileName}" }
130+
),
131+
@Result(name = "error", location = "/admin/error.jsp")
132+
}
133+
)
134+
public String download() {
135+
136+
// https://www.mkyong.com/struts/struts-download-file-from-website-example/
137+
// http://stackoverflow.com/questions/13973264/download-file-in-struts-2-using-annotation
138+
Long userId = AuthUtil.getUserId(servletRequest.getSession());
139+
try {
140+
141+
// build the file path based on the user downloading
142+
String filePath = buildFilePath(downloadFileName, userId);
143+
144+
File fileToDownload = new File(filePath);
145+
if (!fileToDownload.isFile()) {
146+
// file requested doesn't exist
147+
addActionError("File (" + downloadFileName + ") does not exist");
148+
return ERROR;
149+
}
150+
151+
fileInputStream = new FileInputStream(fileToDownload);
152+
} catch (Exception e) {
153+
log.error(e.toString(), e);
154+
addActionError("Exception occurred during download: " + e.getMessage());
155+
return ERROR;
156+
}
157+
158+
return SUCCESS;
159+
160+
}
161+
162+
/**
163+
* Validates all fields for downloading a file
164+
*/
165+
public void validateDownload() {
166+
167+
if (pullFile == null || pullFile.trim().equals("")) {
168+
addFieldError("pullFile", "Required");
169+
170+
}
171+
172+
}
173+
174+
public String getDownloadContentType() {
175+
return downloadContentType;
176+
}
177+
178+
public void setDownloadContentType(String downloadContentType) {
179+
this.downloadContentType = downloadContentType;
180+
}
181+
182+
public String getDownloadFileName() {
183+
return downloadFileName;
184+
}
185+
186+
public void setDownloadFileName(String downloadFileName) {
187+
this.downloadFileName = downloadFileName;
188+
}
189+
190+
public String getPullFile() {
191+
return pullFile;
192+
}
193+
194+
public void setPullFile(String pullDir) {
195+
this.pullFile = pullDir;
196+
}
197+
198+
public List<Long> getIdList() {
199+
return idList;
200+
}
201+
202+
public void setIdList(List<Long> idList) {
203+
this.idList = idList;
204+
}
205+
206+
public List<HostSystem> getHostSystemList() {
207+
return hostSystemList;
208+
}
209+
210+
public void setHostSystemList(List<HostSystem> hostSystemList) {
211+
this.hostSystemList = hostSystemList;
212+
}
213+
214+
215+
216+
public HttpServletRequest getServletRequest() {
217+
return servletRequest;
218+
}
219+
220+
public void setServletRequest(HttpServletRequest servletRequest) {
221+
this.servletRequest = servletRequest;
222+
}
223+
224+
public HttpServletResponse getServletResponse() {
225+
return servletResponse;
226+
}
227+
228+
public void setServletResponse(HttpServletResponse servletResponse) {
229+
this.servletResponse = servletResponse;
230+
}
231+
232+
public HostSystem getPendingSystemStatus() {
233+
return pendingSystemStatus;
234+
}
235+
236+
public void setPendingSystemStatus(HostSystem pendingSystemStatus) {
237+
this.pendingSystemStatus = pendingSystemStatus;
238+
}
239+
240+
public HostSystem getCurrentSystemStatus() {
241+
return currentSystemStatus;
242+
}
243+
244+
public void setCurrentSystemStatus(HostSystem currentSystemStatus) {
245+
this.currentSystemStatus = currentSystemStatus;
246+
}
247+
248+
private static String cleanFilenameForDownloadFile(String filePath) {
249+
return filePath.replaceAll("[^A-Za-z0-9]", "");
250+
}
251+
252+
// builds up the full download path, for the given user
253+
private static String buildFilePath(String filenameWithSystem, long userId) {
254+
return DOWNLOAD_PATH + "/" + filenameWithSystem + "_" + userId;
255+
}
256+
257+
private static String cleanDownloadFilename(String pullPath, long systemId) {
258+
return cleanFilenameForDownloadFile(pullPath) + "_" + systemId;
259+
}
260+
261+
public FileInputStream getFileInputStream() {
262+
return fileInputStream;
263+
}
264+
265+
public void setFileInputStream(FileInputStream fileInputStream) {
266+
this.fileInputStream = fileInputStream;
267+
}
268+
}

src/main/java/com/keybox/manage/action/SecureShellAction.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
import org.slf4j.LoggerFactory;
3838

3939
/**
40-
* This action will create composite ssh terminals to be used
40+
* This action will create ssh terminals to be used
4141
*/
4242
public class SecureShellAction extends ActionSupport implements ServletRequestAware, ServletResponseAware {
4343

@@ -64,7 +64,7 @@ public class SecureShellAction extends ActionSupport implements ServletRequestAw
6464

6565

6666
/**
67-
* creates composite terminals if there are errors or authentication issues.
67+
* creates terminals if there are errors or authentication issues.
6868
*/
6969
@Action(value = "/admin/createTerms",
7070
results = {
@@ -221,6 +221,7 @@ public String disconnectTerm() {
221221
userSchSessions.getSchSessionMap().remove(id);
222222
} catch (Exception ex) {
223223
log.error(ex.toString(), ex);
224+
addActionError("Exception occurred during terminal disconnect: " + ex.getMessage());
224225
}
225226
}
226227

@@ -305,7 +306,7 @@ private void setSystemList(Long userId, Long sessionId) {
305306
}
306307
} catch (Exception e) {
307308
log.error(e.toString(), e);
308-
309+
addActionError("Exception occurred during set system list: " + e.getMessage());
309310
}
310311
}
311312
}

src/main/java/com/keybox/manage/action/UploadAndPushAction.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ public String push() {
162162

163163
} catch (Exception e) {
164164
log.error(e.toString(), e);
165+
addActionError("Exception occurred during push from keybox to host: " + e.getMessage());
165166
}
166167

167168
return SUCCESS;

0 commit comments

Comments
 (0)