You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2019/01/16 02:11:41 UTC
[brooklyn-server] 01/49: adding oauth server
This is an automated email from the ASF dual-hosted git repository.
heneveld pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/brooklyn-server.git
commit 5df761c7fcba55949943829b324c62af09bd5f55
Author: Juan Cabrerizo <ju...@cloudsoft.io>
AuthorDate: Mon Nov 26 11:24:50 2018 +0000
adding oauth server
---
launcher/pom.xml | 12 +
.../brooklyn/launcher/BrooklynWebServer.java | 11 +-
rest/rest-server/pom.xml | 12 +
.../org/apache/brooklyn/rest/RestApiSetup.java | 17 ++
.../apache/brooklyn/rest/filter/MyOauthFilter.java | 244 +++++++++++++++++++++
5 files changed, 288 insertions(+), 8 deletions(-)
diff --git a/launcher/pom.xml b/launcher/pom.xml
index a18827e..23d6d76 100644
--- a/launcher/pom.xml
+++ b/launcher/pom.xml
@@ -213,6 +213,18 @@
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>com.googlecode.json-simple</groupId>
+ <artifactId>json-simple</artifactId>
+ <version>1.1</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.googlecode.json-simple</groupId>
+ <artifactId>json-simple</artifactId>
+ <version>1.1</version>
+ <scope>compile</scope>
+ </dependency>
</dependencies>
diff --git a/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynWebServer.java b/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynWebServer.java
index 9ead29a..cd0cb00 100644
--- a/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynWebServer.java
+++ b/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynWebServer.java
@@ -53,14 +53,7 @@ import org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocati
import org.apache.brooklyn.rest.BrooklynWebConfig;
import org.apache.brooklyn.rest.NopSecurityHandler;
import org.apache.brooklyn.rest.RestApiSetup;
-import org.apache.brooklyn.rest.filter.CorsImplSupplierFilter;
-import org.apache.brooklyn.rest.filter.CsrfTokenFilter;
-import org.apache.brooklyn.rest.filter.EntitlementContextFilter;
-import org.apache.brooklyn.rest.filter.HaHotCheckResourceFilter;
-import org.apache.brooklyn.rest.filter.LoggingFilter;
-import org.apache.brooklyn.rest.filter.NoCacheFilter;
-import org.apache.brooklyn.rest.filter.RequestTaggingFilter;
-import org.apache.brooklyn.rest.filter.RequestTaggingRsFilter;
+import org.apache.brooklyn.rest.filter.*;
import org.apache.brooklyn.rest.security.jaas.BrooklynLoginModule;
import org.apache.brooklyn.rest.security.jaas.BrooklynLoginModule.RolePrincipal;
import org.apache.brooklyn.rest.security.jaas.JaasUtils;
@@ -501,6 +494,8 @@ public class BrooklynWebServer {
RestApiSetup.installServletFilters(context,
RequestTaggingFilter.class,
LoggingFilter.class);
+ RestApiSetup.installOauthServletFilters(context,
+ MyOauthFilter.class);
if (securityFilterClazz != null) {
RestApiSetup.installServletFilters(context, securityFilterClazz);
}
diff --git a/rest/rest-server/pom.xml b/rest/rest-server/pom.xml
index fca9be4..aa97e00 100644
--- a/rest/rest-server/pom.xml
+++ b/rest/rest-server/pom.xml
@@ -209,6 +209,18 @@
<artifactId>cxf-rt-rs-client</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>com.googlecode.json-simple</groupId>
+ <artifactId>json-simple</artifactId>
+ <version>1.1</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.googlecode.json-simple</groupId>
+ <artifactId>json-simple</artifactId>
+ <version>1.1</version>
+ <scope>compile</scope>
+ </dependency>
</dependencies>
<build>
diff --git a/rest/rest-server/src/main/java/org/apache/brooklyn/rest/RestApiSetup.java b/rest/rest-server/src/main/java/org/apache/brooklyn/rest/RestApiSetup.java
index 33bbfd3..d961f7d 100644
--- a/rest/rest-server/src/main/java/org/apache/brooklyn/rest/RestApiSetup.java
+++ b/rest/rest-server/src/main/java/org/apache/brooklyn/rest/RestApiSetup.java
@@ -26,14 +26,17 @@ import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import org.apache.brooklyn.rest.apidoc.RestApiResourceScanner;
+import org.apache.brooklyn.rest.filter.MyOauthFilter;
import org.apache.cxf.BusFactory;
import org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet;
import org.apache.cxf.transport.common.gzip.GZIPInInterceptor;
import org.apache.cxf.transport.common.gzip.GZIPOutInterceptor;
+import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import io.swagger.config.ScannerFactory;
+import org.eclipse.jetty.webapp.WebAppContext;
public class RestApiSetup {
@@ -70,4 +73,18 @@ public class RestApiSetup {
ScannerFactory.setScanner(new RestApiResourceScanner());
}
+ public static void installOauthServletFilters(WebAppContext context, Class<MyOauthFilter> myOauthFilterClass) {
+ FilterHolder fh= context.addFilter(myOauthFilterClass, "/*", EnumSet.allOf(DispatcherType.class));
+ setFilterParams(fh);
+ }
+ private static void setFilterParams(FilterHolder fh) {
+ fh.setInitParameter(MyOauthFilter.PARAM_URI_GETTOKEN, "https://accounts.google.com/o/oauth2/token");
+ fh.setInitParameter(MyOauthFilter.PARAM_URI_TOKEN_INFO, "https://www.googleapis.com/oauth2/v1/tokeninfo");
+ fh.setInitParameter(MyOauthFilter.PARAM_URI_LOGIN_REDIRECT, "/login");
+ fh.setInitParameter(MyOauthFilter.PARAM_CLIENT_ID,
+ "789182012565-burd24h3bc0im74g2qemi7lnihvfqd02.apps.googleusercontent.com");
+ fh.setInitParameter(MyOauthFilter.PARAM_CLIENT_SECRET, "X00v-LfU34U4SfsHqPKMWfQl");
+ fh.setInitParameter(MyOauthFilter.PARAM_CALLBACK_URI, "http://localhost.io:8080/service/ping");
+ fh.setInitParameter(MyOauthFilter.PARAM_AUDIENCE, "audience");
+ }
}
diff --git a/rest/rest-server/src/main/java/org/apache/brooklyn/rest/filter/MyOauthFilter.java b/rest/rest-server/src/main/java/org/apache/brooklyn/rest/filter/MyOauthFilter.java
new file mode 100644
index 0000000..4ae2b4a
--- /dev/null
+++ b/rest/rest-server/src/main/java/org/apache/brooklyn/rest/filter/MyOauthFilter.java
@@ -0,0 +1,244 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.rest.filter;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import net.minidev.json.JSONObject;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.methods.HttpRequestBase;
+import org.apache.http.entity.ContentType;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.util.EntityUtils;
+import org.json.simple.parser.JSONParser;
+import org.json.simple.parser.ParseException;
+
+public class MyOauthFilter implements Filter {
+
+ private static final String SESSION_KEY_CODE = "code";
+
+ private static final String SESSION_KEY_ACCESS_TOKEN = "access_token";
+
+ public static final String PARAM_URI_TOKEN_INFO = "uriTokenInfo";
+ private String uriTokenInfo = "";
+ public static final String PARAM_URI_GETTOKEN = "uriGetToken";
+ private String uriGetToken = "";
+ public static final String PARAM_URI_LOGIN_REDIRECT = "uriLoginRedirect";
+ private String uriTokenRedirect = "";
+ public static final String PARAM_CLIENT_ID = "clientId";
+ private String clientId = "";
+ public static final String PARAM_CLIENT_SECRET = "clientSecret";
+ private String clientSecret = "";
+ public static final String PARAM_CALLBACK_URI = "callbackUri";
+ private String callbackUri = "";
+ public static final String PARAM_AUDIENCE = "audience";
+ private String audience = "";
+
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+ initializateParams(filterConfig);
+ }
+
+ private void initializateParams(FilterConfig filterConfig) {
+ Enumeration<String> enums = filterConfig.getInitParameterNames();
+
+ while (enums.hasMoreElements()) {
+ String paramKey = enums.nextElement();
+ String paramValue = filterConfig.getInitParameter(paramKey);
+ System.out.println(paramKey + ":" + paramValue);
+ switch (paramKey) {
+ case PARAM_URI_TOKEN_INFO:
+ uriTokenInfo = paramValue;
+ break;
+ case PARAM_URI_GETTOKEN:
+ uriGetToken = paramValue;
+ break;
+ case PARAM_URI_LOGIN_REDIRECT:
+ uriTokenRedirect = paramValue;
+ break;
+ case PARAM_CLIENT_ID:
+ clientId = paramValue;
+ break;
+ case PARAM_CLIENT_SECRET:
+ clientSecret = paramValue;
+ break;
+ case PARAM_CALLBACK_URI:
+ callbackUri = paramValue;
+ break;
+ case PARAM_AUDIENCE:
+ audience = paramValue;
+ break;
+ default:
+ System.out.println("Ignored param: " + paramKey + ":" + paramValue);
+ }
+ }
+ }
+
+ @Override
+ public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
+ throws IOException, ServletException {
+ HttpServletRequest request = (HttpServletRequest) req;
+ // Redirection from the authenticator server
+ String code = req.getParameter(SESSION_KEY_CODE);
+
+ // Getting token, if exists, from the current session
+ String token = (String) request.getSession().getAttribute(SESSION_KEY_ACCESS_TOKEN);
+
+ boolean continueFilterProcessing;
+ if (code != null && !"".equals(code)) { // in brooklyn, have
+ // Strings.isNonBlank(code)
+ continueFilterProcessing = getToken(req, resp, chain);
+ } else if (token == null || "".equals(token)) { // isBlank
+ continueFilterProcessing = redirectLogin(resp);
+ } else {
+ continueFilterProcessing = validateToken(token, resp);
+ }
+ if (continueFilterProcessing) {
+ chain.doFilter(req, resp);
+ }
+ }
+
+ private boolean validateToken(String token, ServletResponse resp) throws ClientProtocolException, IOException {
+ // System.out.println("########################### Validating token
+ // ###########################");
+ HashMap<String, String> params = new HashMap<String, String>();
+ params.put(SESSION_KEY_ACCESS_TOKEN, token);
+
+ String body = post(uriTokenInfo, params);
+ // System.out.println(body);
+ JSONObject jsonObject = null;
+
+ // get the access token from json and request info from Google
+ try {
+ jsonObject = (JSONObject) new JSONParser().parse(body);
+ } catch (ParseException e) {
+ throw new RuntimeException("Unable to parse json " + body);
+ }
+
+ if (!clientId.equals(jsonObject.get(audience))) {
+ return redirectLogin(resp);
+ }
+ // if (isTokenExpiredOrNearlySo(...) { ... }
+ return true;
+ }
+
+ private boolean getToken(ServletRequest req, ServletResponse resp, FilterChain chain)
+ throws ClientProtocolException, IOException, ServletException {
+ String code = req.getParameter(SESSION_KEY_CODE);
+
+ // get the access token by post to Google
+ HashMap<String, String> params = new HashMap<String, String>();
+ params.put(SESSION_KEY_CODE, code);
+ params.put("client_id", clientId);
+ params.put("client_secret", clientSecret);
+ params.put("redirect_uri", callbackUri);
+ params.put("grant_type", "authorization_code");
+
+ String body = post(uriGetToken, params);
+
+ JSONObject jsonObject = null;
+
+ // get the access token from json and request info from Google
+ try {
+ jsonObject = (JSONObject) new JSONParser().parse(body);
+ } catch (ParseException e) {
+ // throw new RuntimeException("Unable to parse json " + body);
+ return redirectLogin(resp);
+ }
+
+ // Left token and code in session
+ String accessToken = (String) jsonObject.get(SESSION_KEY_ACCESS_TOKEN);
+ HttpServletRequest request = (HttpServletRequest) req;
+ request.getSession().setAttribute(SESSION_KEY_ACCESS_TOKEN, accessToken);
+ request.getSession().setAttribute(SESSION_KEY_CODE, code);
+
+ // resp.getWriter().println(json);
+ return true;
+ }
+
+ // makes a POST request to url with form parameters and returns body as a
+ // string
+ public String post(String url, Map<String, String> formParameters) throws ClientProtocolException, IOException {
+ HttpPost request = new HttpPost(url);
+
+ List<NameValuePair> nvps = new ArrayList<NameValuePair>();
+ for (String key : formParameters.keySet()) {
+ nvps.add(new BasicNameValuePair(key, formParameters.get(key)));
+ }
+ request.setEntity(new UrlEncodedFormEntity(nvps));
+
+ return execute(request);
+ }
+
+ // makes a GET request to url and returns body as a string
+ public String get(String url) throws ClientProtocolException, IOException {
+ return execute(new HttpGet(url));
+ }
+
+ // makes request and checks response code for 200
+ private String execute(HttpRequestBase request) throws ClientProtocolException, IOException {
+ HttpClient httpClient = new DefaultHttpClient();
+ HttpResponse response = httpClient.execute(request);
+
+ HttpEntity entity = response.getEntity();
+ String body = EntityUtils.toString(entity);
+
+ if (response.getStatusLine().getStatusCode() != 200) {
+ throw new RuntimeException(
+ "Expected 200 but got " + response.getStatusLine().getStatusCode() + ", with body " + body);
+ }
+
+ return body;
+ }
+
+ private boolean redirectLogin(ServletResponse response) throws IOException {
+ HttpServletResponse res = (HttpServletResponse) response;
+ res.setContentType(ContentType.APPLICATION_XML.toString());
+ res.sendRedirect(uriTokenRedirect);
+ return false;
+ }
+
+ @Override
+ public void destroy() {
+ // TODO Auto-generated method stub
+ }
+
+}