Ankit Dangi created FELIX-5682:
----------------------------------

             Summary: Deploying a bundle from a URL that requires Authentication
                 Key: FELIX-5682
                 URL: https://issues.apache.org/jira/browse/FELIX-5682
             Project: Felix
          Issue Type: Bug
          Components: Bundle Repository (OBR)
    Affects Versions: bundlerepository-2.0.10
         Environment: macOS Sierra 10.12.6, Felix 5.6.4
            Reporter: Ankit Dangi
             Fix For: bundlerepository-2.0.12


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:
# repos add <URL_OBR_repository.xml>
# bundlelevel -i 2      // set the initial bundle level to 2 (Tier 3 services)
# frameworklevel 2   // move the framework level to that level
# deploy -s <bundle-name> 

Yields: 
{quote}Target resource(s):
-------------------
   <bundle-name>

Deploying...
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{quote}

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: 

{quote}HttpURLConnection conn = (HttpURLConnection) new 
URL(url).openConnection();
conn.setRequestProperty(HttpHeaders.AUTHORIZATION, this.getAuthHeader(USERNAME, 
PASSWORD));
FileUtil.openURL(conn.getInputStream());{quote}

where, 
{quote}String getAuthHeader (String username, String password) {
        String auth = username + ":" + password;
        byte[] encodedAuth = Base64.encodeBase64(auth.getBytes());
        String authHeader = "Basic " + new String(encodedAuth);
        return authHeader;
}{quote}

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. 



--
This message was sent by Atlassian JIRA
(v6.4.14#64029)

Reply via email to