You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ol...@apache.org on 2019/12/08 08:41:35 UTC
[sling-org-apache-sling-commons-crypto] 02/02: SLING-8886 Provide a
Web Console plugin to encrypt messages
This is an automated email from the ASF dual-hosted git repository.
olli pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-commons-crypto.git
commit 1cc4e03bfea4a24898093a35cc3d72eaa15958d0
Author: Oliver Lietz <ol...@apache.org>
AuthorDate: Sun Dec 8 09:40:56 2019 +0100
SLING-8886 Provide a Web Console plugin to encrypt messages
---
bnd.bnd | 4 +
pom.xml | 6 +
.../crypto/internal/EncryptWebConsolePlugin.java | 190 +++++++++++++++++++++
3 files changed, 200 insertions(+)
diff --git a/bnd.bnd b/bnd.bnd
index ba06157..a714ebc 100644
--- a/bnd.bnd
+++ b/bnd.bnd
@@ -1,10 +1,14 @@
DynamicImport-Package:\
+ javax.servlet,\
+ javax.servlet.http,\
org.jasypt.encryption.pbe,\
org.jasypt.iv,\
org.jasypt.registry,\
org.jasypt.salt
Import-Package:\
+ javax.servlet;resolution:=optional,\
+ javax.servlet.http;resolution:=optional,\
org.jasypt.encryption.pbe;resolution:=optional,\
org.jasypt.iv;resolution:=optional,\
org.jasypt.registry;resolution:=optional,\
diff --git a/pom.xml b/pom.xml
index 95b97c0..daa9cdb 100644
--- a/pom.xml
+++ b/pom.xml
@@ -111,6 +111,12 @@
<artifactId>javax.inject</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <scope>provided</scope>
+ <optional>true</optional>
+ </dependency>
<!-- OSGi -->
<dependency>
<groupId>org.osgi</groupId>
diff --git a/src/main/java/org/apache/sling/commons/crypto/internal/EncryptWebConsolePlugin.java b/src/main/java/org/apache/sling/commons/crypto/internal/EncryptWebConsolePlugin.java
new file mode 100644
index 0000000..cff31ae
--- /dev/null
+++ b/src/main/java/org/apache/sling/commons/crypto/internal/EncryptWebConsolePlugin.java
@@ -0,0 +1,190 @@
+/*
+ * 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.sling.commons.crypto.internal;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Arrays;
+import java.util.Objects;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.Servlet;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.sling.commons.crypto.CryptoService;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.util.tracker.ServiceTracker;
+
+import static org.osgi.service.component.ComponentConstants.COMPONENT_ID;
+
+@Component(
+ service = Servlet.class,
+ property = {
+ "felix.webconsole.label=sling-commons-crypto-encrypt",
+ "felix.webconsole.title=Sling Commons Crypto Encrypt",
+ "felix.webconsole.category=Crypto"
+ }
+)
+public class EncryptWebConsolePlugin extends HttpServlet {
+
+ private BundleContext bundleContext;
+
+ private ServiceTracker<CryptoService, CryptoService> tracker;
+
+ private static final String PARAMETER_ID = "id";
+
+ private static final String PARAMETER_MESSAGE = "message";
+
+ private static final String ATTRIBUTE_CIPHERTEXT = "org.apache.sling.commons.crypto.internal.EncryptWebConsolePlugin.ciphertext";
+
+ public EncryptWebConsolePlugin() {
+ }
+
+ @Activate
+ private void activate(final BundleContext bundleContext) {
+ this.bundleContext = bundleContext;
+ tracker = new ServiceTracker<>(bundleContext, CryptoService.class, null);
+ tracker.open();
+ }
+
+ @Deactivate
+ private void deactivate() {
+ this.bundleContext = null;
+ if (Objects.nonNull(tracker)) {
+ tracker.close();
+ tracker = null;
+ }
+ }
+
+ @Override
+ protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException {
+ final ServiceReference<CryptoService>[] references = tracker.getServiceReferences();
+ final PrintWriter writer = response.getWriter();
+ if (Objects.nonNull(references) && references.length > 0) {
+ final String form = buildForm(references);
+ writer.println(form);
+ } else {
+ writer.println("<p>No crypto service available</p>");
+ }
+
+ final String forwardRequestUri = (String) request.getAttribute(RequestDispatcher.FORWARD_REQUEST_URI);
+ if (Objects.nonNull(forwardRequestUri) && forwardRequestUri.equals(request.getRequestURI())) {
+ final String ciphertext = (String) request.getAttribute(ATTRIBUTE_CIPHERTEXT);
+ if (Objects.nonNull(ciphertext)) {
+ final String html = String.format("<p>Encrypted message: %s</p>", ciphertext);
+ writer.println(html);
+ }
+ }
+ }
+
+ @Override
+ protected void doPost(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException {
+ request.removeAttribute(ATTRIBUTE_CIPHERTEXT);
+ final String id = request.getParameter(PARAMETER_ID);
+ final String message = request.getParameter(PARAMETER_MESSAGE); // do NOT log SECRET message
+ if (Objects.isNull(id)) {
+ handleParameterMissing(response, PARAMETER_ID);
+ return;
+ }
+ if (Objects.isNull(message)) {
+ handleParameterMissing(response, PARAMETER_MESSAGE);
+ return;
+ }
+ final CryptoService cryptoService = findCryptoService(id);
+ if (Objects.isNull(cryptoService)) {
+ handleCryptoServiceNotFound(response, id);
+ return;
+ }
+ final String ciphertext = cryptoService.encrypt(message);
+ request.setAttribute(ATTRIBUTE_CIPHERTEXT, ciphertext);
+ final GetHttpServletRequestWrapper wrapper = new GetHttpServletRequestWrapper(request);
+ request.getRequestDispatcher(request.getRequestURI()).forward(wrapper, response);
+ }
+
+ private void handleParameterMissing(final HttpServletResponse response, final String parameter) throws IOException {
+ final String message = String.format("Parameter %s is missing", parameter);
+ response.sendError(400, message);
+ }
+
+ private void handleCryptoServiceNotFound(final HttpServletResponse response, final String id) throws IOException {
+ final String message = String.format("Crypto service with component id %s not found", id);
+ response.sendError(404, message);
+ }
+
+ private @NotNull String buildForm(final ServiceReference<CryptoService>[] references) {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("<form method=\"POST\">");
+ builder.append("<label for=\"message\">Message to encrypt</label>");
+ builder.append("<br>");
+ builder.append("<input type=\"text\" name=\"message\" id=\"message\">");
+ builder.append("<br>");
+ builder.append("<label>Available crypto services");
+ builder.append("<br>");
+ builder.append("<select name=\"id\">");
+ for (final ServiceReference<CryptoService> reference : references) {
+ final String id = reference.getProperty(COMPONENT_ID).toString();
+ final String[] names = (String[]) reference.getProperty("names");
+ final String algorithm = reference.getProperty("algorithm").toString();
+ final String label = String.format("Component id %s, names: %s, algorithm: %s", id, Arrays.toString(names), algorithm);
+ builder.append("<option value=\"").append(id).append("\">");
+ builder.append(label);
+ builder.append("</option>");
+ }
+ builder.append("</label>");
+ builder.append("</select>");
+ builder.append("<br>");
+ builder.append("<button type=\"submit\">encrypt</button>");
+ builder.append("</form>");
+ return builder.toString();
+ }
+
+ private @Nullable CryptoService findCryptoService(@NotNull final String id) {
+ final ServiceReference<CryptoService>[] references = tracker.getServiceReferences();
+ for (final ServiceReference<CryptoService> reference : references) {
+ if (id.equals(reference.getProperty(COMPONENT_ID).toString())) {
+ return bundleContext.getService(reference);
+ }
+ }
+ return null;
+ }
+
+ private static class GetHttpServletRequestWrapper extends HttpServletRequestWrapper {
+
+ GetHttpServletRequestWrapper(final HttpServletRequest request) {
+ super(request);
+ }
+
+ @Override
+ public String getMethod() {
+ return "GET";
+ }
+
+ }
+
+}