1 /* 2 * Copyright (c) 2016 Google Inc. All Rights Reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you 5 * may not use this file except in compliance with the License. You may 6 * 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 13 * implied. See the License for the specific language governing 14 * permissions and limitations under the License. 15 */ 16 17 package com.android.vts.api; 18 19 import com.android.vts.proto.VtsReportMessage.TestReportMessage; 20 import com.android.vts.servlet.BaseServlet; 21 import com.android.vts.util.DatastoreHelper; 22 import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; 23 import com.google.api.client.http.javanet.NetHttpTransport; 24 import com.google.api.client.json.jackson.JacksonFactory; 25 import com.google.api.services.oauth2.Oauth2; 26 import com.google.api.services.oauth2.model.Tokeninfo; 27 import com.google.protobuf.InvalidProtocolBufferException; 28 import java.io.BufferedReader; 29 import java.io.FileNotFoundException; 30 import java.io.IOException; 31 import java.io.InputStream; 32 import java.util.Properties; 33 import java.util.logging.Level; 34 import java.util.logging.Logger; 35 import javax.servlet.ServletConfig; 36 import javax.servlet.ServletException; 37 import javax.servlet.http.HttpServlet; 38 import javax.servlet.http.HttpServletRequest; 39 import javax.servlet.http.HttpServletResponse; 40 import org.apache.commons.codec.binary.Base64; 41 import org.json.JSONException; 42 import org.json.JSONObject; 43 44 /** REST endpoint for posting data JSON to the Dashboard. */ 45 @Deprecated 46 public class BigtableLegacyJsonServlet extends HttpServlet { 47 private static String SERVICE_CLIENT_ID; 48 private static final String SERVICE_NAME = "VTS Dashboard"; 49 private static final Logger logger = 50 Logger.getLogger(BigtableLegacyJsonServlet.class.getName()); 51 52 /** System Configuration Property class */ 53 protected Properties systemConfigProp = new Properties(); 54 55 @Override init(ServletConfig cfg)56 public void init(ServletConfig cfg) throws ServletException { 57 super.init(cfg); 58 59 try { 60 InputStream defaultInputStream = 61 BigtableLegacyJsonServlet.class 62 .getClassLoader() 63 .getResourceAsStream("config.properties"); 64 systemConfigProp.load(defaultInputStream); 65 66 SERVICE_CLIENT_ID = systemConfigProp.getProperty("appengine.serviceClientID"); 67 } catch (FileNotFoundException e) { 68 e.printStackTrace(); 69 } catch (IOException e) { 70 e.printStackTrace(); 71 } 72 } 73 74 @Override doPost(HttpServletRequest request, HttpServletResponse response)75 public void doPost(HttpServletRequest request, HttpServletResponse response) 76 throws IOException { 77 // Retrieve the params 78 String payload = new String(); 79 JSONObject payloadJson; 80 try { 81 String line = null; 82 BufferedReader reader = request.getReader(); 83 while ((line = reader.readLine()) != null) { 84 payload += line; 85 } 86 payloadJson = new JSONObject(payload); 87 } catch (IOException | JSONException e) { 88 response.setStatus(HttpServletResponse.SC_BAD_REQUEST); 89 logger.log(Level.WARNING, "Invalid JSON: " + payload); 90 return; 91 } 92 93 // Verify service account access token. 94 boolean authorized = false; 95 if (payloadJson.has("accessToken")) { 96 String accessToken = payloadJson.getString("accessToken").trim(); 97 GoogleCredential credential = new GoogleCredential().setAccessToken(accessToken); 98 Oauth2 oauth2 = 99 new Oauth2.Builder(new NetHttpTransport(), new JacksonFactory(), credential) 100 .setApplicationName(SERVICE_NAME) 101 .build(); 102 Tokeninfo tokenInfo = oauth2.tokeninfo().setAccessToken(accessToken).execute(); 103 if (tokenInfo.getIssuedTo().equals(SERVICE_CLIENT_ID)) { 104 authorized = true; 105 } 106 } 107 108 if (!authorized) { 109 response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); 110 return; 111 } 112 113 // Parse the desired action and execute the command 114 try { 115 if (payloadJson.has("verb")) { 116 switch (payloadJson.getString("verb")) { 117 case "createTable": 118 logger.log(Level.INFO, "Deprecated verb: createTable."); 119 break; 120 case "insertRow": 121 insertData(payloadJson); 122 break; 123 default: 124 logger.log( 125 Level.WARNING, 126 "Invalid Datastore REST verb: " + payloadJson.getString("verb")); 127 throw new IOException("Unsupported POST verb."); 128 } 129 } 130 } catch (IOException e) { 131 response.setStatus(HttpServletResponse.SC_BAD_REQUEST); 132 return; 133 } 134 response.setStatus(HttpServletResponse.SC_OK); 135 } 136 137 /** 138 * Inserts a data into the Cloud Datastore 139 * 140 * @param payloadJson The JSON object representing the row to be inserted. Of the form: { 141 * (deprecated) 'tableName' : 'table', (deprecated) 'rowKey' : 'row', (deprecated) 'family' 142 * : 'family', (deprecated) 'qualifier' : 'qualifier', 'value' : 'value' } 143 * @throws IOException 144 */ insertData(JSONObject payloadJson)145 private void insertData(JSONObject payloadJson) throws IOException { 146 if (!payloadJson.has("value")) { 147 logger.log(Level.WARNING, "Missing attributes for datastore api insertRow()."); 148 return; 149 } 150 try { 151 byte[] value = Base64.decodeBase64(payloadJson.getString("value")); 152 TestReportMessage testReportMessage = TestReportMessage.parseFrom(value); 153 } catch (InvalidProtocolBufferException e) { 154 logger.log(Level.WARNING, "Invalid report posted to dashboard."); 155 } 156 } 157 } 158