Я работаю над одним проектом по интеграции Tenable.sc (который является инструментом мониторинга сети) и ServiceNow (инструмент SaaS для создания инцидентов). Я использую API-интерфейсы tenable.sc для получения данных анализа уязвимостей из tenable и их хранения в базе данных Postgres. Мой вопрос связан с Java HttpURLConnection и Cookie manager.
Я использую приведенный ниже код для получения всех данных через API. Основная проблема - когда я запускаю свое приложение Spring-Boot и пытаюсь запустить этот API в первый раз, он выдает ошибку 403. После каждого последующего вызова API я получаю правильные результаты.
Пожалуйста, обратитесь ниже код и шаги:
@ Услуги
открытый класс MyAppService {
private CookieManager cookieManager;
static final String COOKIES_HEADER = "Set-Cookie";
@Value("${tenable.analysis.severity}")
private String severities;
public MyAppService() {
// Setting The CookieHandler so we have access to clear it
// This also allows us to open separate connections with the same cookies
cookieManager = new CookieManager();
CookieHandler.setDefault(cookieManager);
cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
}
// Fetches all Vulnerabilities for the given asset
public List<VulnerabilitiesRequest> fetchVulnerabilities(String base, String path, String user, String pass, String action, int startOffSet, int endOffSet) throws IOException {
return fetchRequest(base, path, user, pass, action, startOffSet, endOffSet, new KillerAppzException("Error fetching vulnerabilities"));
}
private List<VulnerabilitiesRequest> fetchRequest(String base, String path, String user, String pass, String action, int startOffSet, int endOffSet, KillerAppzException exception) throws IOException {
HttpURLConnection conn = request(base, path, user, pass, action, startOffSet, endOffSet);
if (conn.getResponseCode() == 200) {
StringBuilder response = HttpUtils.readInputStream(conn);
conn.disconnect();
ObjectMapper objectMapper = new ObjectMapper();
JsonNode rootNode = objectMapper.readTree(response.toString());
JsonNode locatedNode = rootNode.path("response").path("results");
Gson gson = new Gson();
VulnerabilitiesRequest clicks[] = gson.fromJson(locatedNode.toString(), VulnerabilitiesRequest[].class);
List<VulnerabilitiesRequest> list = Arrays.asList(clicks);
return list;
} else {
conn.disconnect();
throw exception;
}
}
private HttpURLConnection request(String base, String path, String user, String pass, String action, int startOffSet, int endOffSet) throws IOException {
URL baseURL = new URL(base + path);
HttpURLConnection conn = (HttpURLConnection) baseURL.openConnection();
conn.setDoOutput(true);
conn.setRequestProperty("X-SecurityCenter", generateNewToken(user,pass));
conn.setRequestProperty("Authorization", getAuthorizationHeaderValue(user, pass));
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestProperty("Accept", "application/json");
conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.95 Safari/537.11");
conn.setRequestMethod("POST");
String postJsonData="";
if(action.equalsIgnoreCase("FETCH")) {
postJsonData = "{\r\n" +
"\"query\": {\r\n" +
"\"type\": \"vuln\",\r\n" +
"\"tool\": \"vulndetails\",\r\n" +
"\"sourceType\": \"cumulative\",\r\n" +
"\"startOffset\": " + startOffSet + ",\r\n" +
"\"endOffset\": " + endOffSet + ",\r\n" +
"\"filters\": [\r\n" +
" {\r\n" +
" \"filterName\": \"severity\",\r\n" +
" \"operator\": \"=\",\r\n" +
" \"value\": \""+ severities + "\"\r\n" +
" },\r\n" +
" {\r\n" +
" \"filterName\": \"lastSeen\",\r\n" +
" \"operator\": \"=\",\r\n" +
" \"value\": \"0:30\"\r\n" +
" }\r\n" +
"]\r\n" +
"},\r\n" +
"\"sourceType\": \"cumulative\",\r\n" +
"\"sortField\": \"severity\",\r\n" +
"\"sortDir\": \"asc\",\r\n" +
"\"columns\": [],\r\n" +
"\"type\": \"vuln\"\r\n" +
"}";
}else {
postJsonData = "{\r\n" +
"\"query\": {\r\n" +
"\"type\": \"vuln\",\r\n" +
"\"tool\": \"vulndetails\",\r\n" +
"\"sourceType\": \"patched\",\r\n" +
"\"startOffset\": " + startOffSet + ",\r\n" +
"\"endOffset\": " + endOffSet + ",\r\n" +
"\"filters\": [\r\n" +
" {\r\n" +
" \"filterName\": \"severity\",\r\n" +
" \"operator\": \"=\",\r\n" +
" \"value\": \""+ severities + "\"\r\n" +
" }\r\n" +
"]\r\n" +
"},\r\n" +
"\"sourceType\": \"patched\",\r\n" +
"\"sortField\": \"severity\",\r\n" +
"\"sortDir\": \"asc\",\r\n" +
"\"columns\": [],\r\n" +
"\"type\": \"vuln\"\r\n" +
"}";
}
String cookieValue = "";
if (cookieManager.getCookieStore().getCookies().size() > 0) {
List<HttpCookie> cookies = cookieManager.getCookieStore().getCookies();
if (cookies != null) {
for (HttpCookie cookie : cookies) {
if(cookie.getName().equals("TNS_SESSIONID")) {
cookieValue = cookie.getValue();
}
}
}
}
conn.setRequestProperty("Cookie", "TNS_SESSIONID=" + cookieValue);
DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
wr.writeBytes(postJsonData);
wr.flush();
wr.close();
return conn;
}
private String generateNewToken(String user, String pass) throws IOException {
URL tokenGenerationURL = new URL("https://sc.tenalab.online/rest/token?username="+ user +"&password="+ pass);
HttpURLConnection tokenConn = (HttpURLConnection) tokenGenerationURL.openConnection();
tokenConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
tokenConn.setRequestProperty("Accept", "application/json");
tokenConn.setDoOutput(true);
tokenConn.setRequestMethod("POST");
BufferedReader in = new BufferedReader(new InputStreamReader(tokenConn.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
ObjectNode node = new ObjectMapper().readValue(response.toString(), ObjectNode.class);
JsonNode generatedToken = node.path("response").path("token");
tokenConn.disconnect();
return generatedToken.toString();
}
private String getAuthorizationHeaderValue(String user, String pass) {
return "username=" + user + "; password=" + pass + ";";
}
}
Шаги:
- Первый метод fetchVulnerabilities вызовет метод fetchRequest для соединения и результата.
- Метод fetchRequest вызовет метод request, а в методе request я установил HttpURLConnection.
- 'conn.setRequestProperty ("X-SecurityCenter", generateNewToken (user, pass));' - эта строка в методе 'request' сгенерирует токен (с помощью API генерации токенов) для основного API, чтобы присоединить этот токен в заголовок. Также будет сгенерирован cookie, который также будет установлен в основной API.
После запуска этого метода 'request' я получаю ошибку в методе 'fetchRequest', где я не получаю responseCode как 200. Эта проблема возникает только при самом первом запуске. Если я попытаюсь запустить этот API второй раз, он будет работать нормально.