cloudstack-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bhais...@apache.org
Subject git commit: updated refs/heads/4.5 to b6b3494
Date Sat, 28 Feb 2015 12:44:16 GMT
Repository: cloudstack
Updated Branches:
  refs/heads/4.5 f70afa137 -> b6b349478


CLOUDSTACK-7063, CLOUDSTACK-7064: Add security headers on HTTP response

- Adds X-XSS-Protection header
- Adds X-Content-Type-Options header
- Fixes to use json content type defined from global settings
- Uses secure cookie if enabled in global settings

Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/b6b34947
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/b6b34947
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/b6b34947

Branch: refs/heads/4.5
Commit: b6b3494782d8bc1033941b802380ba1d5ebd464c
Parents: f70afa1
Author: Rohit Yadav <rohit.yadav@shapeblue.com>
Authored: Sat Feb 28 18:12:37 2015 +0530
Committer: Rohit Yadav <rohit.yadav@shapeblue.com>
Committed: Sat Feb 28 18:12:37 2015 +0530

----------------------------------------------------------------------
 server/src/com/cloud/api/ApiServer.java        | 21 ++++++++++++-----
 server/src/com/cloud/api/ApiServlet.java       | 24 ++++++++++++-------
 server/src/com/cloud/configuration/Config.java | 15 +++++++++---
 utils/src/com/cloud/utils/HttpUtils.java       | 26 ++++++++++++++++++---
 4 files changed, 66 insertions(+), 20 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b6b34947/server/src/com/cloud/api/ApiServer.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/ApiServer.java b/server/src/com/cloud/api/ApiServer.java
index 59f9316..6dcf48a 100755
--- a/server/src/com/cloud/api/ApiServer.java
+++ b/server/src/com/cloud/api/ApiServer.java
@@ -181,7 +181,8 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler,
ApiSer
     private static final Logger s_accessLogger = Logger.getLogger("apiserver." + ApiServer.class.getName());
 
     public static boolean encodeApiResponse = false;
-    public static String jsonContentType = "text/javascript";
+    public static boolean s_enableSecureCookie = false;
+    public static String s_jsonContentType = HttpUtils.JSON_CONTENT_TYPE;
 
     /**
      * Non-printable ASCII characters - numbers 0 to 31 and 127 decimal
@@ -362,9 +363,13 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler,
ApiSer
         }
 
         setEncodeApiResponse(Boolean.valueOf(_configDao.getValue(Config.EncodeApiResponse.key())));
-        final String jsonType = _configDao.getValue(Config.JavaScriptDefaultContentType.key());
+        final String jsonType = _configDao.getValue(Config.JSONDefaultContentType.key());
         if (jsonType != null) {
-            jsonContentType = jsonType;
+            s_jsonContentType = jsonType;
+        }
+        final Boolean enableSecureSessionCookie = Boolean.valueOf(_configDao.getValue(Config.EnableSecureSessionCookie.key()));
+        if (enableSecureSessionCookie != null) {
+            s_enableSecureCookie = enableSecureSessionCookie;
         }
 
         if (apiPort != null) {
@@ -1136,7 +1141,7 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler,
ApiSer
             final BasicHttpEntity body = new BasicHttpEntity();
             if (HttpUtils.RESPONSE_TYPE_JSON.equalsIgnoreCase(responseType)) {
                 // JSON response
-                body.setContentType(jsonContentType);
+                body.setContentType(getJSONContentType());
                 if (responseText == null) {
                     body.setContent(new ByteArrayInputStream("{ \"error\" : { \"description\"
: \"Internal Server Error\" } }".getBytes(HttpUtils.UTF_8)));
                 }
@@ -1367,7 +1372,11 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler,
ApiSer
         ApiServer.encodeApiResponse = encodeApiResponse;
     }
 
-    public static String getJsonContentType() {
-        return jsonContentType;
+    public static boolean isSecureSessionCookieEnabled() {
+        return s_enableSecureCookie;
+    }
+
+    public static String getJSONContentType() {
+        return s_jsonContentType;
     }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b6b34947/server/src/com/cloud/api/ApiServlet.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/ApiServlet.java b/server/src/com/cloud/api/ApiServlet.java
index 3d2e843..edfc246 100644
--- a/server/src/com/cloud/api/ApiServlet.java
+++ b/server/src/com/cloud/api/ApiServlet.java
@@ -148,12 +148,20 @@ public class ApiServlet extends HttpServlet {
         try {
 
             if (HttpUtils.RESPONSE_TYPE_JSON.equalsIgnoreCase(responseType)) {
-                resp.setContentType(HttpUtils.JSON_CONTENT_TYPE);
+                resp.setContentType(ApiServer.getJSONContentType());
             } else if (HttpUtils.RESPONSE_TYPE_XML.equalsIgnoreCase(responseType)){
                 resp.setContentType(HttpUtils.XML_CONTENT_TYPE);
             }
 
             HttpSession session = req.getSession(false);
+            if (ApiServer.isSecureSessionCookieEnabled()) {
+                resp.setHeader("SET-COOKIE", "JSESSIONID=" + session.getId() + ";Secure;Path=/client");
+                if (s_logger.isDebugEnabled()) {
+                    if (s_logger.isDebugEnabled()) {
+                        s_logger.debug("Session cookie is marked secure!");
+                    }
+                }
+            }
             final Object[] responseTypeParam = params.get(ApiConstants.RESPONSE);
             if (responseTypeParam != null) {
                 responseType = (String)responseTypeParam[0];
@@ -206,7 +214,7 @@ public class ApiServlet extends HttpServlet {
                             }
                         }
                     }
-                    HttpUtils.writeHttpResponse(resp, responseString, httpResponseCode, responseType);
+                    HttpUtils.writeHttpResponse(resp, responseString, httpResponseCode, responseType,
ApiServer.getJSONContentType());
                     return;
                 }
             }
@@ -233,7 +241,7 @@ public class ApiServlet extends HttpServlet {
                     auditTrailSb.append(" " + HttpServletResponse.SC_UNAUTHORIZED + " " +
"unable to verify user credentials");
                     final String serializedResponse =
                         _apiServer.getSerializedApiError(HttpServletResponse.SC_UNAUTHORIZED,
"unable to verify user credentials", params, responseType);
-                    HttpUtils.writeHttpResponse(resp, serializedResponse, HttpServletResponse.SC_UNAUTHORIZED,
responseType);
+                    HttpUtils.writeHttpResponse(resp, serializedResponse, HttpServletResponse.SC_UNAUTHORIZED,
responseType, ApiServer.getJSONContentType());
                     return;
                 }
 
@@ -244,7 +252,7 @@ public class ApiServlet extends HttpServlet {
                         s_logger.info("missing command, ignoring request...");
                         auditTrailSb.append(" " + HttpServletResponse.SC_BAD_REQUEST + "
" + "no command specified");
                         final String serializedResponse = _apiServer.getSerializedApiError(HttpServletResponse.SC_BAD_REQUEST,
"no command specified", params, responseType);
-                        HttpUtils.writeHttpResponse(resp, serializedResponse, HttpServletResponse.SC_BAD_REQUEST,
responseType);
+                        HttpUtils.writeHttpResponse(resp, serializedResponse, HttpServletResponse.SC_BAD_REQUEST,
responseType, ApiServer.getJSONContentType());
                         return;
                     }
                     final User user = _entityMgr.findById(User.class, userId);
@@ -260,7 +268,7 @@ public class ApiServlet extends HttpServlet {
                     auditTrailSb.append(" " + HttpServletResponse.SC_UNAUTHORIZED + " " +
"unable to verify user credentials");
                     final String serializedResponse =
                         _apiServer.getSerializedApiError(HttpServletResponse.SC_UNAUTHORIZED,
"unable to verify user credentials", params, responseType);
-                    HttpUtils.writeHttpResponse(resp, serializedResponse, HttpServletResponse.SC_UNAUTHORIZED,
responseType);
+                    HttpUtils.writeHttpResponse(resp, serializedResponse, HttpServletResponse.SC_UNAUTHORIZED,
responseType, ApiServer.getJSONContentType());
                     return;
                 }
             } else {
@@ -274,7 +282,7 @@ public class ApiServlet extends HttpServlet {
                 // Add the HTTP method (GET/POST/PUT/DELETE) as well into the params map.
                 params.put("httpmethod", new String[] {req.getMethod()});
                 final String response = _apiServer.handleRequest(params, responseType, auditTrailSb);
-                HttpUtils.writeHttpResponse(resp, response != null ? response : "", HttpServletResponse.SC_OK,
responseType);
+                HttpUtils.writeHttpResponse(resp, response != null ? response : "", HttpServletResponse.SC_OK,
responseType, ApiServer.getJSONContentType());
             } else {
                 if (session != null) {
                     try {
@@ -287,13 +295,13 @@ public class ApiServlet extends HttpServlet {
                 final String serializedResponse =
                     _apiServer.getSerializedApiError(HttpServletResponse.SC_UNAUTHORIZED,
"unable to verify user credentials and/or request signature", params,
                         responseType);
-                HttpUtils.writeHttpResponse(resp, serializedResponse, HttpServletResponse.SC_UNAUTHORIZED,
responseType);
+                HttpUtils.writeHttpResponse(resp, serializedResponse, HttpServletResponse.SC_UNAUTHORIZED,
responseType, ApiServer.getJSONContentType());
 
             }
         } catch (final ServerApiException se) {
             final String serializedResponseText = _apiServer.getSerializedApiError(se, params,
responseType);
             resp.setHeader("X-Description", se.getDescription());
-            HttpUtils.writeHttpResponse(resp, serializedResponseText, se.getErrorCode().getHttpCode(),
responseType);
+            HttpUtils.writeHttpResponse(resp, serializedResponseText, se.getErrorCode().getHttpCode(),
responseType, ApiServer.getJSONContentType());
             auditTrailSb.append(" " + se.getErrorCode() + " " + se.getDescription());
         } catch (final Exception ex) {
             s_logger.error("unknown exception writing api response", ex);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b6b34947/server/src/com/cloud/configuration/Config.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java
index 93ee1ca..a6089fc 100755
--- a/server/src/com/cloud/configuration/Config.java
+++ b/server/src/com/cloud/configuration/Config.java
@@ -1591,13 +1591,22 @@ public enum Config {
             "Percentage (as a value between 0 and 1) of connected agents after which agent
load balancing will start happening",
             null),
 
-    JavaScriptDefaultContentType(
+    JSONDefaultContentType(
             "Advanced",
             ManagementServer.class,
             String.class,
             "json.content.type",
-            "text/javascript",
-            "Http response content type for .js files (default is text/javascript)",
+            "application/json; charset=UTF-8",
+            "Http response content type for JSON",
+            null),
+
+    EnableSecureSessionCookie(
+            "Advanced",
+            ManagementServer.class,
+            Boolean.class,
+            "enable.secure.session.cookie",
+            "false",
+            "Session cookie's secure flag is enabled if true. Use this only when using HTTPS",
             null),
 
     DefaultMaxProjectUserVms(

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b6b34947/utils/src/com/cloud/utils/HttpUtils.java
----------------------------------------------------------------------
diff --git a/utils/src/com/cloud/utils/HttpUtils.java b/utils/src/com/cloud/utils/HttpUtils.java
index 0ed2afa..58768dc 100644
--- a/utils/src/com/cloud/utils/HttpUtils.java
+++ b/utils/src/com/cloud/utils/HttpUtils.java
@@ -31,20 +31,40 @@ public class HttpUtils {
     public static final String UTF_8 = "UTF-8";
     public static final String RESPONSE_TYPE_JSON = "json";
     public static final String RESPONSE_TYPE_XML = "xml";
-    public static final String JSON_CONTENT_TYPE = "text/javascript; charset=UTF-8";
+    public static final String JSON_CONTENT_TYPE = "application/json; charset=UTF-8";
     public static final String XML_CONTENT_TYPE = "text/xml; charset=UTF-8";
 
+    public static void addSecurityHeaders(final HttpServletResponse resp) {
+        if (resp.containsHeader("X-Content-Type-Options")) {
+            resp.setHeader("X-Content-Type-Options", "nosniff");
+        }
+        else {
+            resp.addHeader("X-Content-Type-Options", "nosniff");
+        }
+        if (resp.containsHeader("X-XSS-Protection")) {
+            resp.setHeader("X-XSS-Protection", "1;mode=block");
+        }
+        else {
+            resp.addHeader("X-XSS-Protection", "1;mode=block");
+        }
+    }
+
     public static void writeHttpResponse(final HttpServletResponse resp, final String response,
-                                         final Integer responseCode, final String responseType)
{
+                                         final Integer responseCode, final String responseType,
final String jsonContentType) {
         try {
             if (RESPONSE_TYPE_JSON.equalsIgnoreCase(responseType)) {
-                resp.setContentType(JSON_CONTENT_TYPE);
+                if (jsonContentType != null && !jsonContentType.isEmpty()) {
+                    resp.setContentType(jsonContentType);
+                } else {
+                    resp.setContentType(JSON_CONTENT_TYPE);
+                }
             } else if (RESPONSE_TYPE_XML.equalsIgnoreCase(responseType)){
                 resp.setContentType(XML_CONTENT_TYPE);
             }
             if (responseCode != null) {
                 resp.setStatus(responseCode);
             }
+            addSecurityHeaders(resp);
             resp.getWriter().print(response);
         } catch (final IOException ioex) {
             if (s_logger.isTraceEnabled()) {


Mime
View raw message