You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by si...@apache.org on 2019/10/30 16:18:18 UTC

[sling-org-apache-sling-feature-apiregions] branch SLING-8815 created (now ae15a0c)

This is an automated email from the ASF dual-hosted git repository.

simonetripodi pushed a change to branch SLING-8815
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-apiregions.git.


      at ae15a0c  SLING-8815 - [API Regions] Prevent from resolving to customer-provided bundles

This branch includes the following new commits:

     new ae15a0c  SLING-8815 - [API Regions] Prevent from resolving to customer-provided bundles

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[sling-org-apache-sling-feature-apiregions] 01/01: SLING-8815 - [API Regions] Prevent from resolving to customer-provided bundles

Posted by si...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

simonetripodi pushed a commit to branch SLING-8815
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-apiregions.git

commit ae15a0cf388d88926f5690526cd8663a0373ca8e
Author: Simo Tripodi <st...@adobe.com>
AuthorDate: Wed Oct 30 17:18:03 2019 +0100

    SLING-8815 - [API Regions] Prevent from resolving to customer-provided
    bundles
    
    initial checkin
---
 .../impl/AbstractResolverHookFactory.java          | 70 ++++++++++++++++
 .../apiregions/impl/PlatformIsolationEnforcer.java | 78 ++++++++++++++++++
 .../apiregions/impl/PlatformIsolationHook.java     | 93 ++++++++++++++++++++++
 .../feature/apiregions/impl/RegionEnforcer.java    | 48 ++---------
 4 files changed, 248 insertions(+), 41 deletions(-)

diff --git a/src/main/java/org/apache/sling/feature/apiregions/impl/AbstractResolverHookFactory.java b/src/main/java/org/apache/sling/feature/apiregions/impl/AbstractResolverHookFactory.java
new file mode 100644
index 0000000..dcab1d1
--- /dev/null
+++ b/src/main/java/org/apache/sling/feature/apiregions/impl/AbstractResolverHookFactory.java
@@ -0,0 +1,70 @@
+/*
+ * 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.feature.apiregions.impl;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.hooks.resolver.ResolverHookFactory;
+
+abstract class AbstractResolverHookFactory implements ResolverHookFactory {
+
+    static final String CLASSLOADER_PSEUDO_PROTOCOL = "classloader://";
+
+    static final String PROPERTIES_RESOURCE_PREFIX = "sling.feature.apiregions.resource.";
+
+    static final String PROPERTIES_FILE_LOCATION = "sling.feature.apiregions.location";
+
+    static final String IDBSNVER_FILENAME = "idbsnver.properties";
+
+    protected final URI getDataFileURI(BundleContext ctx, String name) throws IOException, URISyntaxException {
+        String fn = ctx.getProperty(PROPERTIES_RESOURCE_PREFIX + name);
+        if (fn == null) {
+            String loc = ctx.getProperty(PROPERTIES_FILE_LOCATION);
+            if (loc != null) {
+                fn = loc + "/" + name;
+            }
+        }
+
+        if (fn == null) {
+            throw new IOException("API Region Enforcement enabled, but no configuration found to find "
+                    + "region definition resource: " + name);
+        }
+
+        if (fn.contains(":")) {
+            if (fn.startsWith(CLASSLOADER_PSEUDO_PROTOCOL)) {
+                // It's using the 'classloader:' protocol looks up the location from the classloader
+                String loc = fn.substring(CLASSLOADER_PSEUDO_PROTOCOL.length());
+                if (!loc.startsWith("/")) {
+                    loc = "/" + loc;
+                }
+                fn = getClass().getResource(loc).toString();
+            }
+            // It's already a URL
+            return new URI(fn);
+        }
+
+        // It's a file location
+        return new File(fn).toURI();
+    }
+
+}
diff --git a/src/main/java/org/apache/sling/feature/apiregions/impl/PlatformIsolationEnforcer.java b/src/main/java/org/apache/sling/feature/apiregions/impl/PlatformIsolationEnforcer.java
new file mode 100644
index 0000000..04b30a3
--- /dev/null
+++ b/src/main/java/org/apache/sling/feature/apiregions/impl/PlatformIsolationEnforcer.java
@@ -0,0 +1,78 @@
+/*
+ * 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.feature.apiregions.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Version;
+import org.osgi.framework.hooks.resolver.ResolverHook;
+import org.osgi.framework.wiring.BundleRevision;
+
+public class PlatformIsolationEnforcer extends AbstractResolverHookFactory {
+
+    final Map<String, Version> bsnVerMap;
+
+    PlatformIsolationEnforcer(BundleContext context) throws IOException, URISyntaxException {
+        bsnVerMap = readBsnVerMap(context);
+    }
+
+    private Map<String, Version> readBsnVerMap(BundleContext context) throws IOException, URISyntaxException {
+        final Map<String, Version> bsnVerMap = new HashMap<>();
+
+        URI idbsnverFile = getDataFileURI(context, IDBSNVER_FILENAME);
+
+        Properties p = new Properties();
+        try (InputStream is = idbsnverFile.toURL().openStream()) {
+            p.load(is);
+        }
+
+        for (Object valueObject : p.values()) {
+            if (valueObject != null) { // it shouldn't happen, but...
+                String value = valueObject.toString();
+
+                int splitIndex = value.indexOf('~');
+                if (splitIndex != -1) { // again, it shouldn't happen...
+                    String bundleSymbolicName = value.substring(0, splitIndex);
+                    String bundleVersion = value.substring(splitIndex + 1);
+                    Version version = Version.valueOf(bundleVersion);
+
+                    bsnVerMap.put(bundleSymbolicName, version);
+                }
+            }
+        }
+
+        return Collections.unmodifiableMap(bsnVerMap);
+    }
+
+    @Override
+    public ResolverHook begin(Collection<BundleRevision> triggers) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+}
diff --git a/src/main/java/org/apache/sling/feature/apiregions/impl/PlatformIsolationHook.java b/src/main/java/org/apache/sling/feature/apiregions/impl/PlatformIsolationHook.java
new file mode 100644
index 0000000..0c7ef48
--- /dev/null
+++ b/src/main/java/org/apache/sling/feature/apiregions/impl/PlatformIsolationHook.java
@@ -0,0 +1,93 @@
+/*
+ * 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.feature.apiregions.impl;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.osgi.framework.Version;
+import org.osgi.framework.hooks.resolver.ResolverHook;
+import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.framework.wiring.BundleRequirement;
+import org.osgi.framework.wiring.BundleRevision;
+
+public class PlatformIsolationHook implements ResolverHook {
+
+    protected static final String OSGI_WIRING_PACKAGE_NAMESPACE = "osgi.wiring.package";
+
+    private final Map<String, Version> bsnVerMap;
+
+    PlatformIsolationHook(Map<String, Version> bsnVerMap) {
+        this.bsnVerMap = bsnVerMap;
+    }
+
+    @Override
+    public void filterResolvable(Collection<BundleRevision> candidates) {
+        // not used in this version
+    }
+
+    @Override
+    public void filterSingletonCollisions(BundleCapability singleton, Collection<BundleCapability> collisionCandidates) {
+        // not used in this version
+    }
+
+    @Override
+    public void filterMatches(BundleRequirement requirement, Collection<BundleCapability> candidates) {
+        for (Iterator<BundleCapability> it = candidates.iterator(); it.hasNext();) {
+            BundleCapability candidate = it.next();
+
+            BundleRevision rev = candidate.getRevision();
+
+            // bundle is allowed to wire to itself
+            if (requirement.getRevision().getBundle().getBundleId() == rev.getBundle().getBundleId()) {
+                continue;
+            }
+
+            // is it a restricted bundle?
+            if (filter(requirement, candidate)) {
+                it.remove();
+                // LOG.info("Prevented {} from resolving to {}", requirement, candidate);
+            }
+        }
+    }
+
+    private boolean filter(BundleRequirement requirement, BundleCapability candidate) {
+        String requirementNamespace = requirement.getNamespace();
+        String candidateNamespace = candidate.getNamespace();
+        if (!OSGI_WIRING_PACKAGE_NAMESPACE.equals(requirementNamespace)
+                || !requirementNamespace.equals(candidateNamespace)) {
+            return false; // checking wiring packages only
+        }
+
+        BundleRevision candidateRevision = candidate.getRevision();
+        String candidateSymbolicName = candidateRevision.getSymbolicName();
+        Version candidateVersion = candidateRevision.getVersion();
+
+        Version expectedVersion = bsnVerMap.get(candidateSymbolicName);
+
+        return expectedVersion != null && expectedVersion.equals(candidateVersion);
+    }
+
+    @Override
+    public void end() {
+        // not used in this version
+    }
+
+}
diff --git a/src/main/java/org/apache/sling/feature/apiregions/impl/RegionEnforcer.java b/src/main/java/org/apache/sling/feature/apiregions/impl/RegionEnforcer.java
index a2dd9f8..468a66a 100644
--- a/src/main/java/org/apache/sling/feature/apiregions/impl/RegionEnforcer.java
+++ b/src/main/java/org/apache/sling/feature/apiregions/impl/RegionEnforcer.java
@@ -18,13 +18,6 @@
  */
 package org.apache.sling.feature.apiregions.impl;
 
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Version;
-import org.osgi.framework.hooks.resolver.ResolverHook;
-import org.osgi.framework.hooks.resolver.ResolverHookFactory;
-import org.osgi.framework.wiring.BundleRevision;
-
-import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URI;
@@ -45,15 +38,17 @@ import java.util.Properties;
 import java.util.Set;
 import java.util.logging.Logger;
 
-class RegionEnforcer implements ResolverHookFactory {
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Version;
+import org.osgi.framework.hooks.resolver.ResolverHook;
+import org.osgi.framework.wiring.BundleRevision;
+
+class RegionEnforcer extends AbstractResolverHookFactory {
     public static final String GLOBAL_REGION = "global";
 
-    static final String CLASSLOADER_PSEUDO_PROTOCOL = "classloader://";
     static final String APIREGIONS_JOINGLOBAL = "sling.feature.apiregions.joinglobal";
-    static final String PROPERTIES_RESOURCE_PREFIX = "sling.feature.apiregions.resource.";
-    static final String PROPERTIES_FILE_LOCATION = "sling.feature.apiregions.location";
 
-    static final String IDBSNVER_FILENAME = "idbsnver.properties";
+    
     static final String BUNDLE_FEATURE_FILENAME = "bundles.properties";
     static final String FEATURE_REGION_FILENAME = "features.properties";
     static final String REGION_PACKAGE_FILENAME = "regions.properties";
@@ -199,35 +194,6 @@ class RegionEnforcer implements ResolverHookFactory {
         bf.addAll(values);
     }
 
-    private URI getDataFileURI(BundleContext ctx, String name) throws IOException, URISyntaxException {
-        String fn = ctx.getProperty(PROPERTIES_RESOURCE_PREFIX + name);
-        if (fn == null) {
-            String loc = ctx.getProperty(PROPERTIES_FILE_LOCATION);
-            if (loc != null) {
-                fn = loc + "/" + name;
-            }
-        }
-
-        if (fn == null)
-            throw new IOException("API Region Enforcement enabled, but no configuration found to find "
-                    + "region definition resource: " + name);
-
-        if (fn.contains(":")) {
-            if (fn.startsWith(CLASSLOADER_PSEUDO_PROTOCOL)) {
-                // It's using the 'classloader:' protocol looks up the location from the classloader
-                String loc = fn.substring(CLASSLOADER_PSEUDO_PROTOCOL.length());
-                if (!loc.startsWith("/"))
-                    loc = "/" + loc;
-                fn = getClass().getResource(loc).toString();
-            }
-            // It's already a URL
-            return new URI(fn);
-        } else {
-            // It's a file location
-            return new File(fn).toURI();
-        }
-    }
-
     @Override
     public ResolverHook begin(Collection<BundleRevision> triggers) {
         if (enabledRegions.isEmpty())