blob: b2ee8c4b8ff664f264f3809da7c3950d091729e9 [file] [log] [blame]
/*
* 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.ace.it.authentication;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.util.jar.Attributes;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import org.apache.ace.client.repository.SessionFactory;
import org.apache.ace.client.repository.helper.bundle.BundleHelper;
import org.apache.ace.client.repository.repository.ArtifactRepository;
import org.apache.ace.connectionfactory.ConnectionFactory;
import org.apache.ace.obr.storage.OBRFileStoreConstants;
import org.apache.ace.repository.Repository;
import org.apache.ace.repository.RepositoryConstants;
import org.apache.ace.test.constants.TestConstants;
import org.apache.ace.test.utils.FileUtils;
import org.apache.ace.test.utils.NetUtils;
import org.apache.felix.dm.Component;
import org.osgi.framework.Constants;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.log.LogReaderService;
import org.osgi.service.useradmin.UserAdmin;
/**
* Provides a test case in which the OBR has authentication enabled, and the rest of ACE has to remain function
* correctly.
*/
public class ObrAuthenticationTest extends AuthenticationTestBase {
private volatile String m_endpoint;
private volatile File m_storeLocation;
private volatile String m_authConfigPID;
/* Injected by dependency manager */
private volatile ArtifactRepository m_artifactRepository;
private volatile Repository m_userRepository;
private volatile UserAdmin m_userAdmin;
private volatile ConfigurationAdmin m_configAdmin;
private volatile ConnectionFactory m_connectionFactory;
private volatile LogReaderService m_logReader;
private URL m_obrURL;
@Override
protected Component[] getDependencies() {
return new Component[] {
createComponent()
.setImplementation(this)
.add(createServiceDependency().setService(LogReaderService.class).setRequired(true))
.add(createServiceDependency().setService(ArtifactRepository.class).setRequired(true))
.add(createServiceDependency().setService(ConnectionFactory.class).setRequired(true))
.add(createServiceDependency().setService(ConfigurationAdmin.class).setRequired(true))
.add(createServiceDependency().setService(UserAdmin.class).setRequired(true))
.add(createServiceDependency()
.setService(Repository.class, "(&(" + RepositoryConstants.REPOSITORY_NAME + "=users)(" + RepositoryConstants.REPOSITORY_CUSTOMER + "=apache))")
.setRequired(true))
};
}
@Override
protected void configureProvisionedServices() throws Exception {
m_endpoint = "/obr";
String tmpDir = System.getProperty("java.io.tmpdir");
m_storeLocation = new File(tmpDir, "store");
m_storeLocation.delete();
m_storeLocation.mkdirs();
final String fileLocation = m_storeLocation.getAbsolutePath();
getService(SessionFactory.class).createSession("test-session-ID", null);
configureFactory("org.apache.ace.server.repository.factory",
RepositoryConstants.REPOSITORY_NAME, "users",
RepositoryConstants.REPOSITORY_CUSTOMER, "apache",
RepositoryConstants.REPOSITORY_MASTER, "true");
configure("org.apache.ace.useradmin.repository",
"repositoryLocation", "http://localhost:" + TestConstants.PORT + "/repository",
"repositoryCustomer", "apache",
"repositoryName", "users");
configure("org.apache.ace.log.server.store.filebased", "MaxEvents", "0");
m_obrURL = new URL("http://localhost:" + TestConstants.PORT + m_endpoint + "/");
configure("org.apache.ace.client.repository", "obrlocation", m_obrURL.toExternalForm());
configure("org.apache.ace.obr.storage.file", OBRFileStoreConstants.FILE_LOCATION_KEY, fileLocation);
configure("org.apache.ace.http.context", "authentication.enabled", "true");
}
@Override
protected void configureAdditionalServices() throws Exception {
try {
String userName = "d";
String password = "f";
importSingleUser(m_userRepository, userName, password);
waitForUser(m_userAdmin, userName);
URL testURL = new URL(m_obrURL, "index.xml");
assertTrue("Failed to access OBR in time!", waitForURL(m_connectionFactory, testURL, 403, 15000));
m_authConfigPID = configureFactory("org.apache.ace.connectionfactory",
"authentication.baseURL", m_obrURL.toExternalForm(),
"authentication.type", "basic",
"authentication.user.name", userName,
"authentication.user.password", password);
assertTrue("Failed to access OBR in time!", waitForURL(m_connectionFactory, testURL, 200, 15000));
}
catch (Exception e) {
printLog(m_logReader);
throw e;
}
}
@Override
public void doTearDown() throws Exception {
if (m_authConfigPID != null) {
Configuration configuration = getConfiguration(m_authConfigPID);
if (configuration != null) {
configuration.delete();
}
}
FileUtils.removeDirectoryWithContent(m_storeLocation);
}
/**
* Test that we can retrieve the 'index.xml' from the OBR.
*/
public void testAccessObrRepositoryWithCredentialsOk() throws Exception {
try {
URL url = new URL("http://localhost:" + TestConstants.PORT + m_endpoint + "/index.xml");
URLConnection conn = m_connectionFactory.createConnection(url);
assertNotNull(conn);
Object content = conn.getContent();
assertNotNull(content);
}
catch (Exception e) {
printLog(m_logReader);
throw e;
}
}
/**
* Test that we cannot retrieve the 'index.xml' from the OBR without any credentials.
*/
public void testAccessObrRepositoryWithoutCredentialsFail() throws Exception {
try {
URL url = new URL("http://localhost:" + TestConstants.PORT + m_endpoint + "/index.xml");
// do NOT use connection factory as it will supply the credentials for us...
URLConnection conn = url.openConnection();
assertNotNull(conn);
// we expect a 401 for this URL...
NetUtils.waitForURL(url, 401, 15000);
try {
// ...causing all other methods on URLConnection to fail...
conn.getContent(); // should fail!
fail("IOException expected!");
}
catch (IOException exception) {
// Ok; ignored...
}
}
catch (Exception e) {
printLog(m_logReader);
throw e;
}
}
/**
* Test that we cannot retrieve the 'index.xml' from the OBR with incorrect credentials.
*/
public void testAccessObrRepositoryWithWrongCredentialsFail() throws Exception {
try {
org.osgi.service.cm.Configuration configuration = m_configAdmin.getConfiguration(m_authConfigPID);
assertNotNull(configuration);
// Simulate incorrect credentials by updating the config of the connection factory...
configuration.getProperties().put("authentication.user.name", "foo");
configuration.update();
URL url = new URL("http://localhost:" + TestConstants.PORT + m_endpoint + "/index.xml");
// do NOT use connection factory as it will supply the credentials for us...
URLConnection conn = url.openConnection();
assertNotNull(conn);
// we expect a 401 for this URL...
NetUtils.waitForURL(url, 401, 5000);
try {
// ...causing all other methods on URLConnection to fail...
conn.getContent(); // should fail!
fail("IOException expected!");
}
catch (IOException exception) {
// Ok; ignored...
}
}
catch (Exception e) {
printLog(m_logReader);
throw e;
}
}
/**
* Test that an import of an artifact through the API of ACE works, making sure they can access an authenticated OBR
* as well.
*/
public void testImportArtifactWithCredentialsOk() throws Exception {
try {
// Use a valid JAR file, without a Bundle-SymbolicName header.
Manifest manifest = new Manifest();
Attributes attributes = manifest.getMainAttributes();
attributes.putValue(Attributes.Name.MANIFEST_VERSION.toString(), "1");
attributes.putValue(Constants.BUNDLE_MANIFESTVERSION, "2");
attributes.putValue(BundleHelper.KEY_SYMBOLICNAME, "org.apache.ace.test1");
File temp = File.createTempFile("org.apache.ace.test1", ".jar");
temp.deleteOnExit();
JarOutputStream jos = new JarOutputStream(new FileOutputStream(temp), manifest);
jos.close();
m_artifactRepository.importArtifact(temp.toURI().toURL(), true /* upload */);
assertEquals(1, m_artifactRepository.get().size());
assertTrue(m_artifactRepository.getResourceProcessors().isEmpty());
// Create a JAR file which looks like a resource processor supplying bundle.
attributes.putValue(BundleHelper.KEY_RESOURCE_PROCESSOR_PID, "someProcessor");
attributes.putValue(BundleHelper.KEY_VERSION, "1.0.0.processor");
temp = File.createTempFile("org.apache.ace.test2", ".jar");
temp.deleteOnExit();
jos = new JarOutputStream(new FileOutputStream(temp), manifest);
jos.close();
m_artifactRepository.importArtifact(temp.toURI().toURL(), true);
assertEquals(1, m_artifactRepository.get().size());
assertEquals(1, m_artifactRepository.getResourceProcessors().size());
}
catch (Exception e) {
printLog(m_logReader);
throw e;
}
}
/**
* Test that an import of an artifact through the API of ACE works, making sure they can access an authenticated OBR
* as well.
*/
public void testImportArtifactWithoutCredentialsFail() throws Exception {
try {
org.osgi.service.cm.Configuration configuration = m_configAdmin.getConfiguration(m_authConfigPID);
assertNotNull(configuration);
// Delete the credentials for the OBR-URL, thereby simulating wrong credentials for the OBR...
configuration.delete();
// Use a valid JAR file, without a Bundle-SymbolicName header.
Manifest manifest = new Manifest();
Attributes attributes = manifest.getMainAttributes();
attributes.putValue(Attributes.Name.MANIFEST_VERSION.toString(), "1");
attributes.putValue(Constants.BUNDLE_MANIFESTVERSION, "2");
attributes.putValue(BundleHelper.KEY_SYMBOLICNAME, "org.apache.ace.test3");
File temp = File.createTempFile("org.apache.ace.test3", ".jar");
temp.deleteOnExit();
JarOutputStream jos = new JarOutputStream(new FileOutputStream(temp), manifest);
jos.close();
try {
m_artifactRepository.importArtifact(temp.toURI().toURL(), true /* upload */); // should fail!
fail("IOException expected!");
}
catch (IOException exception) {
// Ok; expected...
}
}
catch (Exception e) {
printLog(m_logReader);
throw e;
}
}
}