blob: 1f21bf060974dcbad1ec2837acb5a3a3d3a05430 [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.directory.server.core.authz;
import static org.apache.directory.server.core.authz.AutzIntegUtils.addUserToGroup;
import static org.apache.directory.server.core.authz.AutzIntegUtils.createAccessControlSubentry;
import static org.apache.directory.server.core.authz.AutzIntegUtils.createUser;
import static org.apache.directory.server.core.authz.AutzIntegUtils.getConnectionAs;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.apache.directory.api.ldap.model.entry.DefaultEntry;
import org.apache.directory.api.ldap.model.entry.Entry;
import org.apache.directory.api.ldap.model.exception.LdapException;
import org.apache.directory.api.ldap.model.name.Dn;
import org.apache.directory.ldap.client.api.LdapConnection;
import org.apache.directory.server.core.annotations.CreateDS;
import org.apache.directory.server.core.integ.AbstractLdapTestUnit;
import org.apache.directory.server.core.integ.FrameworkRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
* Tests whether or not authorization around entry addition works properly.
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
@RunWith(FrameworkRunner.class)
@CreateDS(name = "AddAuthorizationIT")
public class AddAuthorizationIT extends AbstractLdapTestUnit
{
@Before
public void setService()
{
AutzIntegUtils.service = getService();
getService().setAccessControlEnabled( true );
}
/**
* Checks if a simple entry (organizationalUnit) can be added to the DIT at an
* Rdn relative to ou=system by a specific non-admin user. If a permission exception
* is encountered it is caught and false is returned, otherwise true is returned
* when the entry is created. The entry is deleted after being created just in case
* subsequent calls to this method do not fail: the admin account is used to delete
* this test entry so permissions to delete are not required to delete it by the user.
*
* @param uid the unique identifier for the user (presumed to exist under ou=users,ou=system)
* @param password the password of this user
* @param entryRdn the relative Dn, relative to ou=system where entry creation is tested
* @return true if the entry can be created by the user at the specified location, false otherwise
* @throws Exception if there are problems conducting the test
*/
public boolean checkCanAddEntryAs( String uid, String password, String entryRdn ) throws Exception
{
LdapConnection connection = null;
Dn userName = new Dn( "uid=" + uid + ",ou=users,ou=system" );
connection = getConnectionAs( userName, password );
String entryDn = entryRdn + ",ou=system";
Entry entry = new DefaultEntry( entryDn );
entry.add( "ou", "testou" );
entry.add( "ObjectClass", "top", "organizationalUnit" );
try
{
connection.add( entry );
return true;
}
catch ( LdapException le )
{
return false;
}
finally
{
if ( connection != null )
{
connection.close();
}
}
}
/**
* Checks to make sure group membership based userClass works for add operations.
*
* @throws Exception if the test encounters an error
*/
@Test
public void testGrantAddAdministrators() throws Exception
{
// create the non-admin user
createUser( "billyd", "billyd" );
// try an add operation which should fail without any ACI
assertFalse( checkCanAddEntryAs( "billyd", "billyd", "ou=testou" ) );
// Gives grantAdd perm to all users in the Administrators group for
// entries and all attribute types and values
createAccessControlSubentry( "administratorAdd",
"{ " +
" identificationTag \"addAci\", " +
" precedence 14, " +
" authenticationLevel none, " +
" itemOrUserFirst userFirst: " +
" { " +
" userClasses { userGroup { \"cn=Administrators,ou=groups,ou=system\" } }, " +
" userPermissions " +
" { " +
" { " +
" protectedItems {entry, allUserAttributeTypesAndValues}, " +
" grantsAndDenials { grantAdd, grantBrowse } " +
" } " +
" } " +
" } " +
"}" );
// see if we can now add that test entry which we could not before
// add op should still fail since billd is not in the admin group
assertFalse( checkCanAddEntryAs( "billyd", "billyd", "ou=testou" ) );
// now add billyd to the Administrator group and try again
addUserToGroup( "billyd", "Administrators" );
// try an add operation which should succeed with ACI and group membership change
assertTrue( checkCanAddEntryAs( "billyd", "billyd", "ou=testou1" ) );
// Now, make sure the ACI is persisted if we stop and restart the server
// Stop the server now, we will restart it immediately
// And shutdown the DS too
getService().shutdown();
assertFalse( getService().isStarted() );
// And restart
getService().startup();
assertTrue( getService().isStarted() );
// try an add operation which should succeed with ACI and group membership change
assertTrue( checkCanAddEntryAs( "billyd", "billyd", "ou=testou2" ) );
}
/**
* Checks to make sure name based userClass works for add operations.
*
* @throws Exception if the test encounters an error
*/
@Test
public void testGrantAddByName() throws Exception
{
// create the non-admin user
createUser( "billyd", "billyd" );
// try an add operation which should fail without any ACI
assertFalse( checkCanAddEntryAs( "billyd", "billyd", "ou=testou" ) );
// now add a subentry that enables user billyd to add an entry below ou=system
createAccessControlSubentry( "billydAdd",
"{ " +
" identificationTag \"addAci\", " +
" precedence 14, " +
" authenticationLevel none, " +
" itemOrUserFirst userFirst: " +
" { " +
" userClasses { name { \"uid=billyd,ou=users,ou=system\" } }, " +
" userPermissions " +
" { " +
" { " +
" protectedItems {entry, allUserAttributeTypesAndValues}, " +
" grantsAndDenials { grantAdd, grantBrowse } " +
" } " +
" } " +
" } " +
"}" );
// should work now that billyd is authorized by name
assertTrue( checkCanAddEntryAs( "billyd", "billyd", "ou=testou" ) );
}
/**
* Checks to make sure subtree based userClass works for add operations.
*
* @throws Exception if the test encounters an error
*/
@Test
public void testGrantAddBySubtree() throws Exception
{
// create the non-admin user
createUser( "billyd", "billyd" );
// try an add operation which should fail without any ACI
assertFalse( checkCanAddEntryAs( "billyd", "billyd", "ou=testou" ) );
// now add a subentry that enables user billyd to add an entry below ou=system
createAccessControlSubentry( "billyAddBySubtree",
"{ " +
" identificationTag \"addAci\", " +
" precedence 14, " +
" authenticationLevel none, " +
" itemOrUserFirst userFirst: " +
" { " +
" userClasses " +
" { " +
" subtree { { base \"ou=users,ou=system\" } } " +
" }, " +
" userPermissions " +
" { " +
" { " +
" protectedItems {entry, allUserAttributeTypesAndValues}, " +
" grantsAndDenials { grantAdd, grantBrowse } " +
" } " +
" } " +
" } " +
"}" );
// should work now that billyd is authorized by the subtree userClass
assertTrue( checkCanAddEntryAs( "billyd", "billyd", "ou=testou" ) );
}
/**
* Checks to make sure <b>allUsers</b> userClass works for add operations.
*
* @throws Exception if the test encounters an error
*/
@Test
public void testGrantAddAllUsers() throws Exception
{
// create the non-admin user
createUser( "billyd", "billyd" );
// try an add operation which should fail without any ACI
assertFalse( checkCanAddEntryAs( "billyd", "billyd", "ou=testou" ) );
// now add a subentry that enables anyone to add an entry below ou=system
createAccessControlSubentry( "anybodyAdd",
"{ " +
" identificationTag \"addAci\", " +
" precedence 14, " +
" authenticationLevel none, " +
" itemOrUserFirst userFirst: " +
" { " +
" userClasses { allUsers }, " +
" userPermissions " +
" { " +
" { " +
" protectedItems {entry, allUserAttributeTypesAndValues}, " +
" grantsAndDenials { grantAdd, grantBrowse } " +
" } " +
" } " +
" } " +
"}" );
// see if we can now add that test entry which we could not before
// should work now with billyd now that all users are authorized
assertTrue( checkCanAddEntryAs( "billyd", "billyd", "ou=testou" ) );
}
}