You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@felix.apache.org by "Ankit Dangi (JIRA)" <ji...@apache.org> on 2017/08/22 20:10:00 UTC

[jira] [Created] (FELIX-5682) Deploying a bundle from a URL that requires Authentication

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)