Uploaded image for project: 'Felix'
  1. Felix
  2. FELIX-5682

Deploying a bundle from a URL that requires Authentication



    • Type: Bug
    • Status: Open
    • Priority: Major
    • Resolution: Unresolved
    • Affects Version/s: bundlerepository-2.0.10
    • Fix Version/s: bundlerepository-2.0.12
    • Labels:
    • Environment:
      macOS Sierra 10.12.6, Felix 5.6.4
    • Flags:


      Referring to class:

      • org.apache.felix.bundlerepository.impl.ResolverImpl

      Problem Scenario: Deploying a bundle from a OBR that has a capability 'osgi.content' with an attribute 'url' with value pointing to a bundle jar file on a HTTP URL that requires Authorization leads to a "java.io.IOException: Server returned HTTP response code: 401 for URL". The HTTP URL could be any jar hosted on a Web server with Authorization esp. a Maven repo.

      To reproduce: On the Gogo Shell, follow these steps:

      1. repos add <URL_OBR_repository.xml>
      2. bundlelevel -i 2 // set the initial bundle level to 2 (Tier 3 services)
      3. frameworklevel 2 // move the framework level to that level
      4. deploy -s <bundle-name>


      Target resource(s):

      ERROR: Resolver: Install error - <bundle-name>
      java.io.IOException: Error accessing <bundle-jar-on-a-HTTP-URL-that-requires-authorization>
      at org.apache.felix.bundlerepository.impl.FileUtil.openURL(FileUtil.java:217)
      at org.apache.felix.bundlerepository.impl.FileUtil.openURL(FileUtil.java:199)
      at org.apache.felix.bundlerepository.impl.ResolverImpl.deploy(ResolverImpl.java:575)
      at org.apache.felix.bundlerepository.impl.ObrGogoCommand.deploy(ObrGogoCommand.java:377)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:498)
      at org.apache.felix.gogo.runtime.Reflective.invoke(Reflective.java:136)
      at org.apache.felix.gogo.runtime.CommandProxy.execute(CommandProxy.java:91)
      at org.apache.felix.gogo.runtime.Closure.executeCmd(Closure.java:571)
      at org.apache.felix.gogo.runtime.Closure.executeStatement(Closure.java:497)
      at org.apache.felix.gogo.runtime.Closure.execute(Closure.java:386)
      at org.apache.felix.gogo.runtime.Pipe.doCall(Pipe.java:417)
      at org.apache.felix.gogo.runtime.Pipe.call(Pipe.java:229)
      at org.apache.felix.gogo.runtime.Pipe.call(Pipe.java:59)
      at java.util.concurrent.FutureTask.run(FutureTask.java:266)
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
      at java.lang.Thread.run(Thread.java:748)
      Caused by: java.io.IOException: Server returned HTTP response code: 401 for URL: <bundle-jar-on-a-HTTP-URL-that-requires-authorization>
      at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1876)
      at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1474)
      at org.apache.felix.bundlerepository.impl.FileUtil.openURL(FileUtil.java:209)
      ... 19 more

      Possible Solution: In felix/bundlerepository, org.apache.felix.bundlerepository.impl.ResolverImpl.java, in deploy() method on lines 549 and 575, replace FileUtil.openURL(url) with an object of URLConnection as FileUtil.openURL(conn). An URLConnection object has method setRequestProperty(key, value) which could then make it possible to add HttpHeaders.AUTHORIZATION as a key with value as a String with Basic Authorization. Such a URLConnection would also enable to handle diverse HTTP request property-like scenarios.

      Side note: From the org.osgi.framework, Bundle.update() and BundleContext.installBundle() takes an InputStream as a paramater which are used in deploy() method above.

      Code replacements might look like:

      Replace above lines that have FileUtil.openURL(url) with the following:

      HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
      conn.setRequestProperty(HttpHeaders.AUTHORIZATION, this.getAuthHeader(USERNAME, PASSWORD));


      String getAuthHeader (String username, String password) {
      String auth = username + ":" + password;
      return "Basic " + new String(Base64.encodeBase64(auth.getBytes()));

      However, what would be a good way to read such authentication parameters such as username and password for basic Authorization and pass it to deploy() method? What about other Authorization mechanisms as other HTTP Headers?

      Related issue: FELIX-5680 - although not directly relevant.




            • Assignee:
              dangiankit Ankit Dangi
            • Votes:
              0 Vote for this issue
              1 Start watching this issue


              • Created: