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)