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 2021/05/29 21:12:50 UTC

[sling-org-apache-sling-commons-crypto] branch master updated: SLING-10438 Use Service ID instead of Component ID for Crypto Services in Web Console plugin

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


The following commit(s) were added to refs/heads/master by this push:
     new 651a927  SLING-10438 Use Service ID instead of Component ID for Crypto Services in Web Console plugin
651a927 is described below

commit 651a927d90933b06243130f93fef162de5b8a251
Author: Oliver Lietz <ol...@apache.org>
AuthorDate: Sat May 29 23:12:26 2021 +0200

    SLING-10438 Use Service ID instead of Component ID for Crypto Services in Web Console plugin
---
 pom.xml                                            |   9 +-
 .../crypto/internal/EncryptWebConsolePlugin.java   |  27 ++---
 .../crypto/it/tests/EncryptWebConsolePluginIT.java | 134 +++++++++++++++++++++
 .../crypto/it/tests/ReversingCryptoService.java    |  38 ++++++
 4 files changed, 193 insertions(+), 15 deletions(-)

diff --git a/pom.xml b/pom.xml
index dbdd33c..862ac49 100644
--- a/pom.xml
+++ b/pom.xml
@@ -203,7 +203,14 @@
       <scope>provided</scope>
       <optional>true</optional>
     </dependency>
-    <!-- JSR 305-->
+    <!-- jsoup -->
+    <dependency>
+      <groupId>org.jsoup</groupId>
+      <artifactId>jsoup</artifactId>
+      <version>1.13.1</version>
+      <scope>test</scope>
+    </dependency>
+    <!-- nullability -->
     <dependency>
       <groupId>org.jetbrains</groupId>
       <artifactId>annotations</artifactId>
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
index 2a2435e..7d9009c 100644
--- a/src/main/java/org/apache/sling/commons/crypto/internal/EncryptWebConsolePlugin.java
+++ b/src/main/java/org/apache/sling/commons/crypto/internal/EncryptWebConsolePlugin.java
@@ -35,14 +35,13 @@ 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.Constants;
 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 = {
@@ -57,7 +56,7 @@ public class EncryptWebConsolePlugin extends HttpServlet {
 
     private ServiceTracker<CryptoService, CryptoService> tracker;
 
-    private static final String PARAMETER_ID = "id";
+    private static final String PARAMETER_SERVICE_ID = "service-id";
 
     private static final String PARAMETER_MESSAGE = "message";
 
@@ -97,7 +96,7 @@ public class EncryptWebConsolePlugin extends HttpServlet {
         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);
+                final String html = String.format("<p id=\"ciphertext\">Encrypted message: %s</p>", ciphertext);
                 writer.println(html);
             }
         }
@@ -106,19 +105,19 @@ public class EncryptWebConsolePlugin extends HttpServlet {
     @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 serviceId = request.getParameter(PARAMETER_SERVICE_ID);
         final String message = request.getParameter(PARAMETER_MESSAGE); // do NOT log SECRET message
-        if (Objects.isNull(id)) {
-            handleParameterMissing(response, PARAMETER_ID);
+        if (Objects.isNull(serviceId)) {
+            handleParameterMissing(response, PARAMETER_SERVICE_ID);
             return;
         }
         if (Objects.isNull(message)) {
             handleParameterMissing(response, PARAMETER_MESSAGE);
             return;
         }
-        final CryptoService cryptoService = findCryptoService(id);
+        final CryptoService cryptoService = findCryptoService(serviceId);
         if (Objects.isNull(cryptoService)) {
-            handleCryptoServiceNotFound(response, id);
+            handleCryptoServiceNotFound(response, serviceId);
             return;
         }
         final String ciphertext = cryptoService.encrypt(message);
@@ -133,7 +132,7 @@ public class EncryptWebConsolePlugin extends HttpServlet {
     }
 
     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);
+        final String message = String.format("Crypto service with service id %s not found", id);
         response.sendError(404, message);
     }
 
@@ -146,12 +145,12 @@ public class EncryptWebConsolePlugin extends HttpServlet {
         builder.append("<br>");
         builder.append("<label>Available crypto services");
         builder.append("<br>");
-        builder.append("<select name=\"id\">");
+        builder.append("<select id=\"service-id\" name=\"service-id\">");
         for (final ServiceReference<CryptoService> reference : references) {
-            final String id = reference.getProperty(COMPONENT_ID).toString();
+            final String id = reference.getProperty(Constants.SERVICE_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);
+            final String label = String.format("Service id %s, names: %s, algorithm: %s", id, Arrays.toString(names), algorithm);
             builder.append("<option value=\"").append(id).append("\">");
             builder.append(label);
             builder.append("</option>");
@@ -170,7 +169,7 @@ public class EncryptWebConsolePlugin extends HttpServlet {
             return null;
         }
         for (final ServiceReference<CryptoService> reference : references) {
-            if (id.equals(reference.getProperty(COMPONENT_ID).toString())) {
+            if (id.equals(reference.getProperty(Constants.SERVICE_ID).toString())) {
                 return bundleContext.getService(reference);
             }
         }
diff --git a/src/test/java/org/apache/sling/commons/crypto/it/tests/EncryptWebConsolePluginIT.java b/src/test/java/org/apache/sling/commons/crypto/it/tests/EncryptWebConsolePluginIT.java
new file mode 100644
index 0000000..8827162
--- /dev/null
+++ b/src/test/java/org/apache/sling/commons/crypto/it/tests/EncryptWebConsolePluginIT.java
@@ -0,0 +1,134 @@
+/*
+ * 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.it.tests;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import javax.inject.Inject;
+
+import org.apache.sling.commons.crypto.CryptoService;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
+import org.ops4j.pax.exam.spi.reactors.PerMethod;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.apache.sling.testing.paxexam.SlingOptions.webconsole;
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+import static org.ops4j.pax.exam.CoreOptions.options;
+import static org.ops4j.pax.exam.cm.ConfigurationAdminOptions.newConfiguration;
+
+@RunWith(PaxExam.class)
+@ExamReactorStrategy(PerMethod.class)
+public class EncryptWebConsolePluginIT extends CryptoTestSupport {
+
+    private String url;
+
+    private CryptoService cryptoService = new ReversingCryptoService();
+
+    private ServiceRegistration<CryptoService> registration;
+
+    @Inject
+    private BundleContext bundleContext;
+
+    private static final String CREDENTIALS = new String(Base64.getEncoder().encode("admin:admin".getBytes()));
+
+    public EncryptWebConsolePluginIT() { //
+    }
+
+    private void registerCryptoService() {
+        final Dictionary<String, Object> properties = new Hashtable<>();
+        properties.put("names", new String[]{"reverse"});
+        properties.put("algorithm", "reverse");
+        registration = bundleContext.registerService(CryptoService.class, cryptoService, properties);
+    }
+
+    @Configuration
+    public Option[] configuration() {
+        final int httpPort = findFreePort();
+        return options(
+            baseConfiguration(),
+            newConfiguration("org.apache.felix.http")
+                .put("org.osgi.service.http.port", httpPort)
+                .asOption(),
+            webconsole(),
+            mavenBundle().groupId("org.jsoup").artifactId("jsoup").versionAsInProject()
+        );
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        url = String.format("http://localhost:%s/system/console/sling-commons-crypto-encrypt", httpPort());
+        registerCryptoService();
+    }
+
+    @Test
+    public void testGetFormNoCryptoServiceAvailable() throws IOException {
+        registration.unregister();
+        final Document document = Jsoup.connect(url)
+            .header("Authorization", String.format("Basic %s", CREDENTIALS))
+            .get();
+        assertThat(document.title()).isEqualTo("Apache Felix Web Console - Sling Commons Crypto Encrypt");
+        assertThat(document.getElementById("content").child(0).text()).isEqualTo("No crypto service available");
+    }
+
+    @Test
+    public void testGetFormCryptoServiceAvailable() throws IOException {
+        final ServiceReference<CryptoService> reference = registration.getReference();
+        final String id = reference.getProperty(Constants.SERVICE_ID).toString();
+        final String[] names = (String[]) reference.getProperty("names");
+        final String algorithm = reference.getProperty("algorithm").toString();
+        final String label = String.format("Service id %s, names: %s, algorithm: %s", id, Arrays.toString(names), algorithm);
+        final Document document = Jsoup.connect(url)
+            .header("Authorization", String.format("Basic %s", CREDENTIALS))
+            .get();
+        assertThat(document.title()).isEqualTo("Apache Felix Web Console - Sling Commons Crypto Encrypt");
+        assertThat(document.getElementById("service-id").child(0).text()).isEqualTo(label);
+    }
+
+    @Test
+    public void testEncrypt() throws IOException {
+        final ServiceReference<CryptoService> reference = registration.getReference();
+        final String id = reference.getProperty(Constants.SERVICE_ID).toString();
+        final String message = "Very secret message";
+        final String text = String.format("Encrypted message: %s", cryptoService.encrypt(message));
+        final Document document = Jsoup.connect(url)
+            .header("Authorization", String.format("Basic %s", CREDENTIALS))
+            .data("service-id", id)
+            .data("message", message)
+            .post();
+        assertThat(document.title()).isEqualTo("Apache Felix Web Console - Sling Commons Crypto Encrypt");
+        assertThat(document.getElementById("ciphertext").text()).isEqualTo(text);
+    }
+
+}
diff --git a/src/test/java/org/apache/sling/commons/crypto/it/tests/ReversingCryptoService.java b/src/test/java/org/apache/sling/commons/crypto/it/tests/ReversingCryptoService.java
new file mode 100644
index 0000000..3c30108
--- /dev/null
+++ b/src/test/java/org/apache/sling/commons/crypto/it/tests/ReversingCryptoService.java
@@ -0,0 +1,38 @@
+/*
+ * 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.it.tests;
+
+import org.apache.sling.commons.crypto.CryptoService;
+import org.jetbrains.annotations.NotNull;
+
+public class ReversingCryptoService implements CryptoService {
+
+    @Override
+    public @NotNull String encrypt(@NotNull String message) {
+        final StringBuilder sb = new StringBuilder(message);
+        return sb.reverse().toString();
+    }
+
+    @Override
+    public @NotNull String decrypt(@NotNull String ciphertext) {
+        final StringBuilder sb = new StringBuilder(ciphertext);
+        return sb.reverse().toString();
+    }
+
+}