Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/Evolveum/midpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
KaterynaHonchar committed Sep 27, 2018
2 parents 7166cf8 + 734e512 commit cbc894e
Show file tree
Hide file tree
Showing 20 changed files with 426 additions and 19 deletions.
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010-2017 Evolveum
* Copyright (c) 2010-2018 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -51,7 +51,8 @@
*
*/
public class CompositeRefinedObjectClassDefinitionImpl implements CompositeRefinedObjectClassDefinition {

private static final long serialVersionUID = 1L;

@NotNull private final RefinedObjectClassDefinition structuralObjectClassDefinition;
@NotNull private final Collection<RefinedObjectClassDefinition> auxiliaryObjectClassDefinitions;

Expand Down Expand Up @@ -778,4 +779,17 @@ public <A> void setAnnotation(QName qname, A value) {
public Integer getInstantiationOrder() {
return null;
}

@Override
public boolean canRepresent(QName specTypeQName) {
if (structuralObjectClassDefinition.canRepresent(specTypeQName)) {
return true;
}
for (RefinedObjectClassDefinition auxiliaryObjectClassDefinition : auxiliaryObjectClassDefinitions) {
if (auxiliaryObjectClassDefinition.canRepresent(specTypeQName)) {
return true;
}
}
return false;
}
}
Expand Up @@ -692,4 +692,9 @@ public <A> void setAnnotation(QName qname, A value) {
public Integer getInstantiationOrder() {
return null;
}

@Override
public boolean canRepresent(QName specTypeQName) {
return refinedObjectClassDefinition.canRepresent(specTypeQName);
}
}
Expand Up @@ -325,6 +325,12 @@ public ProjectionPolicyType getProjection() {
}
return schemaHandlingObjectTypeDefinitionType.getProjection();
}

@Override
public boolean canRepresent(QName specTypeQName) {
return originalObjectClassDefinition.canRepresent(specTypeQName);
}

//endregion

//region Generating and matching artifacts ========================================================
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010-2017 Evolveum
* Copyright (c) 2010-2018 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -152,4 +152,5 @@ public interface ComplexTypeDefinition extends TypeDefinition, LocalDefinitionSt
default boolean containsItemDefinition(QName itemName) {
return findItemDefinition(itemName) != null;
}

}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010-2017 Evolveum
* Copyright (c) 2010-2018 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down
Expand Up @@ -114,6 +114,14 @@ public Class<C> getCompileTimeClass() {
public boolean canRepresent(Class<?> compileTimeClass) {
return (compileTimeClass.isAssignableFrom(getCompileTimeClass()));
}

public boolean canRepresent(QName type) {
PrismContainerDefinition<C> definition = getDefinition();
if (definition == null) {
throw new IllegalStateException("No definition in "+this+", cannot evaluate type equivalence");
}
return definition.canRepresent(type);
}

@NotNull
@Override
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010-2017 Evolveum
* Copyright (c) 2010-2018 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -57,4 +57,6 @@ public interface PrismContainerDefinition<C extends Containerable> extends ItemD
PrismContainerValue<C> createValue();

boolean isEmpty();

boolean canRepresent(QName type);
}
Expand Up @@ -483,6 +483,11 @@ public boolean canBeDefinitionOf(PrismValue pvalue) {
return true;
}
}

@Override
public boolean canRepresent(QName specTypeQName) {
return complexTypeDefinition.canRepresent(specTypeQName);
}

@Override
public PrismContainerValue<C> createValue() {
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010-2017 Evolveum
* Copyright (c) 2010-2018 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -48,4 +48,6 @@ public interface TypeDefinition extends Definition {
Collection<TypeDefinition> getStaticSubTypes();

Integer getInstantiationOrder();

boolean canRepresent(QName specTypeQName);
}
Expand Up @@ -18,6 +18,8 @@

import org.jetbrains.annotations.NotNull;

import com.evolveum.midpoint.util.QNameUtil;

import javax.xml.namespace.QName;
import java.util.Collection;
import java.util.HashSet;
Expand Down Expand Up @@ -80,6 +82,18 @@ protected void copyDefinitionData(TypeDefinitionImpl clone) {
clone.superType = this.superType;
clone.compileTimeClass = this.compileTimeClass;
}

@Override
public boolean canRepresent(QName specTypeQName) {
if (QNameUtil.match(specTypeQName, getTypeName())) {
return true;
}
if (superType != null) {
ComplexTypeDefinition supertypeDef = getPrismContext().getSchemaRegistry().findComplexTypeDefinitionByType(superType);
return supertypeDef.canRepresent(specTypeQName);
}
return false;
}

@Override
public boolean equals(Object o) {
Expand Down
Expand Up @@ -71,6 +71,9 @@ public class TestSecurityMultitenant extends AbstractSecurityTest {
protected static final String ORG_JUNCTION_NAME = "Junction";
protected static final String ORG_JUNCTION_DISPLAY_NAME = "Plannet Junction";

protected static final File ORG_GUILD_SUBTENANT_FILE = new File(TEST_DIR, "org-guild-subtenant.xml");
protected static final String ORG_GUILD_SUBTENANT_OID = "00000000-8888-6666-a001-000000000fff";

protected static final String ROLE_GUILD_BROKEN_ADMIN_OID = "00000000-8888-6666-a001-100000000001";

protected static final String USER_EDRIC_OID = "00000000-8888-6666-a001-200000000000";
Expand Down Expand Up @@ -117,8 +120,14 @@ public class TestSecurityMultitenant extends AbstractSecurityTest {
protected static final String ORG_CASTLE_CALADAN_NAME = "Castle Caladan";
protected static final String ORG_CASTLE_CALADAN_DISPLAY_NAME = "Castle Caladan";

protected static final File ORG_ATREIDES_SUBTENANT_FILE = new File(TEST_DIR, "org-atreides-subtenant.xml");
protected static final String ORG_ATREIDES_SUBTENANT_OID = "00000000-8888-6666-a200-000000000fff";

protected static final String ROLE_ATREIDES_ADMIN_OID = "00000000-8888-6666-a200-100000000000";

protected static final String ROLE_ATREIDES_GUARD_OID = "00000000-8888-6666-a200-100000000002";
protected static final File ROLE_ATREIDES_GUARD_FILE = new File(TEST_DIR, "role-atreides-guard.xml");

protected static final String USER_LETO_ATREIDES_OID = "00000000-8888-6666-a200-200000000000";
protected static final String USER_LETO_ATREIDES_NAME = "leto";
protected static final String USER_LETO_ATREIDES_FULL_NAME = "Duke Leto Atreides";
Expand All @@ -143,7 +152,10 @@ public class TestSecurityMultitenant extends AbstractSecurityTest {
protected static final String ORG_GIEDI_PRIME_OID = "00000000-8888-6666-a300-000000000001";
protected static final String ORG_GIEDI_PRIME_NAME = "Geidi Prime";
protected static final String ORG_GIEDI_PRIME_DISPLAY_NAME = "Plannet Geidi Prime";


protected static final File ORG_HARKONNEN_SUBTENANT_FILE = new File(TEST_DIR, "org-harkonnen-subtenant.xml");
protected static final String ORG_HARKONNEN_SUBTENANT_OID = "00000000-8888-6666-a300-000000000fff";

protected static final String ROLE_HARKONNEN_ADMIN_OID = "00000000-8888-6666-a300-100000000000";

protected static final String USER_VLADIMIR_HARKONNEN_OID = "00000000-8888-6666-a300-200000000000";
Expand Down Expand Up @@ -435,6 +447,8 @@ public void test102AutzLetoAdd() throws Exception {
assertGlobalStateUntouched();
}

// TODO: add role with authorizations

/**
* MID-4882
*/
Expand Down Expand Up @@ -465,6 +479,8 @@ public void test104AutzLetoModify() throws Exception {
assertGlobalStateUntouched();
}

// TODO: add authorizations to existing role

/**
* MID-4882
*/
Expand Down Expand Up @@ -540,7 +556,7 @@ public void test109AutzLetoDelete() throws Exception {

assertGlobalStateUntouched();
}

/**
* MID-4882
*/
Expand All @@ -558,7 +574,6 @@ public void test110AutzLetoAddOrgs() throws Exception {

// Matching tenant
assertAddAllow(ORG_ARRAKIS_FILE);
display("HEREHERE");
assertAddAllow(ORG_CASTLE_CALADAN_FILE);

// Wrong tenant
Expand Down Expand Up @@ -597,6 +612,118 @@ public void test110AutzLetoAddOrgs() throws Exception {
assertGlobalStateUntouched();
}

/**
* Tenant admin must not be able to add, modify or delete a tenant.
*/
@Test
public void test112AutzLetoProtectTenant() throws Exception {
final String TEST_NAME = "test112AutzLetoProtectTenant";
displayTestTitle(TEST_NAME);
// GIVEN
cleanupAutzTest(null);

login(USER_LETO_ATREIDES_NAME);

// WHEN
displayWhen(TEST_NAME);

// Matching tenant
assertAddDeny(ORG_ATREIDES_SUBTENANT_FILE);
assertModifyDeny(OrgType.class, ORG_ATREIDES_OID, OrgType.F_LOCALITY, createPolyString("Arrakis"));
assertModifyDeny(OrgType.class, ORG_ATREIDES_OID, OrgType.F_TENANT, false);
assertModifyDeny(OrgType.class, ORG_ATREIDES_OID, OrgType.F_TENANT /* no value */);
// Attempt to "move" tenant, make it a root node
assertDeny("unassign root",
(task, result) -> unassignOrg(OrgType.class, ORG_ATREIDES_OID, ORG_ROOT_OID, task, result));
// Attempt to assign new org to tenant. Target of new assignment is org that we control.
assertDeny("assign caladan",
(task, result) -> assignOrg(OrgType.class, ORG_ATREIDES_OID, ORG_CALADAN_OID, task, result));
// Attempt to assign new org to tenant. Target of new assignment is org that we do not control.
assertDeny("assign kaitain",
(task, result) -> assignOrg(OrgType.class, ORG_ATREIDES_OID, ORG_KAITAIN_OID, task, result));
assertDeleteDeny(OrgType.class, ORG_ATREIDES_OID);

// Wrong tenant
assertAddDeny(ORG_HARKONNEN_SUBTENANT_FILE);
assertModifyDeny(OrgType.class, ORG_HARKONNEN_OID, OrgType.F_LOCALITY, createPolyString("Arrakis"));
assertModifyDeny(OrgType.class, ORG_HARKONNEN_OID, OrgType.F_TENANT, false);
assertModifyDeny(OrgType.class, ORG_HARKONNEN_OID, OrgType.F_TENANT /* no value */);
// Attempt to "move" tenant, make it a root node
assertDeny("unassign root",
(task, result) -> unassignOrg(OrgType.class, ORG_HARKONNEN_OID, ORG_ROOT_OID, task, result));
// Attempt to assign new org to tenant. Target of new assignment is org that we control.
assertDeny("assign caladan",
(task, result) -> assignOrg(OrgType.class, ORG_HARKONNEN_OID, ORG_CALADAN_OID, task, result));
// Attempt to assign new org to tenant. Target of new assignment is org that we do not control.
assertDeny("unassign root",
(task, result) -> assignOrg(OrgType.class, ORG_HARKONNEN_OID, ORG_KAITAIN_OID, task, result));
assertDeleteDeny(OrgType.class, ORG_HARKONNEN_OID);

// No tenant
assertAddDeny(ORG_GUILD_SUBTENANT_FILE);
assertModifyDeny(OrgType.class, ORG_GUILD_OID, OrgType.F_LOCALITY, createPolyString("Arrakis"));
assertModifyDeny(OrgType.class, ORG_GUILD_OID, OrgType.F_TENANT, false);
assertModifyDeny(OrgType.class, ORG_GUILD_OID, OrgType.F_TENANT /* no value */);
// Attempt to "move" tenant, make it a root node
assertDeny("unassign root",
(task, result) -> unassignOrg(OrgType.class, ORG_GUILD_OID, ORG_ROOT_OID, task, result));
// Attempt to assign new org to tenant. Target of new assignment is org that we control.
assertDeny("assign caladan",
(task, result) -> assignOrg(OrgType.class, ORG_GUILD_OID, ORG_CALADAN_OID, task, result));
// Attempt to assign new org to tenant. Target of new assignment is org that we do not control.
assertDeny("unassign root",
(task, result) -> assignOrg(OrgType.class, ORG_GUILD_OID, ORG_KAITAIN_OID, task, result));
assertDeleteDeny(OrgType.class, ORG_GUILD_OID);

// THEN
displayThen(TEST_NAME);

assertGlobalStateUntouched();
}

/**
* Make sure that tenant admin cannot break tenant isolation.
* E.g. that cannot move object outside of his domain of control.
*/
@Test
public void test114AutzLetoKeepWithinTenant() throws Exception {
final String TEST_NAME = "test114AutzLetoKeepWithinTenant";
displayTestTitle(TEST_NAME);
// GIVEN
cleanupAutzTest(null);

login(USER_LETO_ATREIDES_NAME);

// WHEN
displayWhen(TEST_NAME);

assertAddAllow(ROLE_ATREIDES_GUARD_FILE);

assertAllow("assign guard to arrakis",
(task, result) -> assignOrg(RoleType.class, ROLE_ATREIDES_GUARD_OID, ORG_ARRAKIS_OID, task, result));

assertRoleAfter(ROLE_ATREIDES_GUARD_OID)
.assertTenantRef(ORG_ATREIDES_OID);

// Guard role is still in the same tenant, so this should go well.
assertAllow("unassign guard from caladan",
(task, result) -> unassignOrg(RoleType.class, ROLE_ATREIDES_GUARD_OID, ORG_CALADAN_OID, task, result));

assertRoleAfter(ROLE_ATREIDES_GUARD_OID)
.assertTenantRef(ORG_ATREIDES_OID);

// WORK IN PROGRESS
// display("HEREHERE");
// // This would make Castle Caladan a root object - outside out tenant zone of control.
// assertDeny("unassign caladan castle from caladan",
// (task, result) -> unassignOrg(OrgType.class, ORG_CASTLE_CALADAN_OID, ORG_CALADAN_OID, task, result));

// THEN
displayThen(TEST_NAME);

assertGlobalStateUntouched();
}

/**
* Edric is part of Spacing Guld. But the Guild is not tenant.
* Edric has a broken role that should work only for tenants.
Expand Down Expand Up @@ -639,5 +766,6 @@ public void test120AutzEdricRead() throws Exception {
}




}
2 changes: 1 addition & 1 deletion model/model-intest/src/test/resources/logback-test.xml
Expand Up @@ -97,7 +97,7 @@
<logger name="com.evolveum.midpoint.model.impl.controller.ObjectMerger" level="DEBUG" />
<logger name="com.evolveum.midpoint.notifications" level="DEBUG" />
<logger name="com.evolveum.midpoint.security" level="DEBUG" />
<logger name="com.evolveum.midpoint.security.enforcer.impl.SecurityEnforcerImpl" level="DEBUG" />
<logger name="com.evolveum.midpoint.security.enforcer.impl.SecurityEnforcerImpl" level="TRACE" />
<logger name="com.evolveum.midpoint.model.impl.security" level="DEBUG" />
<logger name="com.evolveum.midpoint.model.impl.util.AbstractSearchIterativeTaskHandler" level="DEBUG" />
<logger name="com.evolveum.midpoint.model.impl.sync.SynchronizationServiceImpl" level="DEBUG" />
Expand Down
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2010-2018 Evolveum
~
~ Licensed 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.
-->

<org oid="00000000-8888-6666-a200-000000000fff"
xmlns='http://midpoint.evolveum.com/xml/ns/public/common/common-3'
xmlns:org='http://midpoint.evolveum.com/xml/ns/public/common/org-3'
xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3">
<name>Atreides Subtenant</name>
<assignment id="1">
<targetRef oid="00000000-8888-6666-a200-000000000001" type="OrgType"/> <!-- Planet Caladan -->
</assignment>
<displayName>Atreides Subtenant</displayName>
<identifier>2FF</identifier>
<tenant>true</tenant>
</org>

0 comments on commit cbc894e

Please sign in to comment.