Skip to content

Commit

Permalink
Merge pull request #7 from fabric-testbed/project.educational
Browse files Browse the repository at this point in the history
Project.educational support
  • Loading branch information
ibaldin authored Nov 2, 2023
2 parents e8e5dc1 + c63b9cf commit 3bb11b9
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 23 deletions.
28 changes: 16 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,28 +22,31 @@ The following logical predicates reflect role assignments in FABRIC (with a view
| facilityOperator(principal, facility) | A facility operator can create and delete any project and manage owners and members of any project. Facility operator can create slices in any project subject to project resource constraints. |
| projectOwner(principal, project) | A project Owner may add or remove project members for the projects they own. Project Owners are also project members. |
| projectMember(principal, project) | A project Member may create slices assigned to their corresponding project(s). Slice creation requires a membership in a valid project. A project member can provision resources/add slivers into a valid slice subject to resource federation- or aggregate-level resource constraints. A slice may contain slivers created by different project members. A sliver can only be modified or deleted by the project member who created it or by a project owner with one exception: slivers belonging to different project members are automatically allowed to be stitched together as necessary (i.e. if adding a sliver from Alice to a slice requires modifying another sliver already created by Bob, permission is automatically granted assuming Alice and Bob are members of the same project). |
| tokenHolder(principal, project) | A token holder may create long-lived API tokens |

Projects are bound to specific facilities at the time of creation, thus effectively adding a `facility` parameter to projectOwner and projectMember predicates.

| Rule | Implemented in |
|---|---|
| 1. Project Lead can create projects at a facility | ProjectRegistry |
| 2. Project Lead can delete the project they created at a facility | ProjectRegistry |
| 3. Facility Operator can remove any project at a facility | ProjectRegistry |
| 4. Project Lead can add and remove Project Owners from projects they created at a facility | ProjectRegistry |
| 5. Facility Operator can add and remove Project Owners from any project at a facility | ProjectRegistry |
| 6. Project Lead includes privileges of a Project Owner | ProjectRegistry |
| 7. Project Owner can add and remove Project Members from their project at a facility | ProjectRegistry |
| 8. Facility Operator includes privileges of a Project Owner on a project (can add remove members) | ProjectRegistry |
| 9. Project Owner includes privileges as Project Member | ProjectRegistry |
| 1. Project Lead can create projects at a facility | CoreAPI |
| 2. Project Lead can delete the project they created at a facility | CoreAPI |
| 3. Facility Operator can remove any project at a facility | CoreAPI |
| 4. Project Lead can add and remove Project Owners from projects they created at a facility | CoreAPI |
| 5. Facility Operator can add and remove Project Owners from any project at a facility | CoreAPI |
| 6. Project Lead includes privileges of a Project Owner | CoreAPI |
| 7. Project Owner can add and remove Project Members from their project at a facility | CoreAPI |
| 8. Facility Operator includes privileges of a Project Owner on a project (can add remove members) | CoreAPI |
| 9. Project Owner includes privileges as Project Member | CoreAPI |
| 10. Project Member can create slices within a project at a facility | XACML PDPs |
| 11. Project Member can delete a slice they created or any slice in their project | XACML PDPs |
| 12. Project Member can create slivers within any project slice subject to federation- or aggregate-level resource constraints at a facility | XACML PDPs |
| 13. Project Owner can modify or delete any sliver belonging to a slice created within their project. Modify operations are subject to federation- and aggregate-level resource constraints. | XACML PDPs |
| 14. Facility Operator is also a Project Member for any project (can create/delete slices and slivers) subject to project resource constraints. | ProjectRegistry |
| 14. Facility Operator is also a Project Member for any project (can create/delete slices and slivers) subject to project resource constraints. | CoreAPI |
| 15. Resource type/project tag based policies | XACML PDPs |

Rules 1-9 of the project management policies above are embedded in the [ProjectRegistry](https://github.com/fabric-testbed/project-registry) procedural code and CI Logon logic. The remaining rules are federation-level and are implemented using XACML PDPs.
Rules 1-9 of the project management policies above are embedded in the [CoreAPI](https://github.com/fabric-testbed/fabric-core-api) procedural code and CI Logon logic. The remaining rules are federation-level and are implemented using XACML PDPs.

Generation of API tokens for control framework is handled by [Credential Manager](https://github.com/fabric-testbed/CredentialManager).

# Resource provisioning authorizations using ABAC

Expand All @@ -53,7 +56,7 @@ Much of the resource authorization is done inside Orchestrator, Broker and Aggre
dimensions/sizes of the slivers and the duration for which slivers are being created. Operations related to modifying existing resources require information about the identity of the user invoking the modify operation as well as the user who originally created the resource that is being modified.

Tags are added to a project by Facility Operators based on requests from the Project Owners. The full discussion of how project attributes are communicated to the PDP is outside the scope of this document, however briefly:
- One or more attributes or tags are added to a project within a Project registry by Facility Operator
- One or more attributes or tags are added to a project within a CoreAPI by Facility Operator
- Prior to requesting to create a slice, experimenter receives a cryptographically signed authorization token that contains relevant project tags
- The PDP received information about requested resource attributes (their type, size, components, duration) as well as the project tags extracted from a validated token.
- In addition the control framework agent invoking the PDP provides identity attributes (e.g. email) of the principal invoking the action and the principal who e.g. created the resource
Expand Down Expand Up @@ -114,6 +117,7 @@ The following is an incomplete list of possible project tag values:
- Slice.Multisite - allows to create slices spanning multiple sites
- Slice.Measurements - allows to provision measurement VMs
- Slice.NoLimitLifetime - allows to create slices with a lifetime beyond default limit X time units without the need to renew
- Project.Educational - tags the project as educational restricting it to a subset of resources


### Actions, Scopes and Action Attributes
Expand Down
12 changes: 12 additions & 0 deletions authzforce/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Overview

This directory is used by the test harness, you can put the .jar files from authzforce distribution, like authzforce-ce-core-pdp-cli-20.1.0.jar, into this folder. Note that the test harness uses a combination of the jar files here and the running PDP Docker container.

You can also add javalib/ folder in here to hold any missing java dependencies for starting the CLI jar above. For example

javalib/
├── jaxb-api-2.2.11.jar
├── jaxb-api-2.3.0.jar
└── jaxb-runtime-2.2.11.jar


Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,16 @@ namespace fabricTags {
}
}

rule eduSite {
deny
condition not(Attributes.resourceSite == "EDUKY") && Attributes.projectTag == "Project.Educational" && not(Attributes.projectTag == "Slice.Multisite")
on deny {
advice reasonToDeny {
Attributes.message = "Policy Violation: Your project is tagged as Educational and lacks Slice.Multisite tag and cannot use resources on sites other than EDUKY."
}
}
}

rule bandwidth {
deny
condition Attributes.resourceBW > 10 && not(Attributes.projectTag == "Net.NoLimitBW")
Expand Down
2 changes: 1 addition & 1 deletion src-gen/fabricTags.OrchestratorTags.xml

Large diffs are not rendered by default.

132 changes: 122 additions & 10 deletions test/test-harness.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
NOPDP = 'pdp-no.xml'

# make sure the CLI executable and appropriate Java version are available
AUTHZFORCECLI = '../authzforce/authzforce-ce-core-pdp-cli-20.1.0.jar'
#AUTHZFORCECLI = '../authzforce/authzforce-ce-core-pdp-cli-20.1.0.jar'
AUTHZFORCECLI = '../authzforce/authzforce-ce-core-pdp-cli-20.3.2.jar'
PERMIT_REQUESTS = [
'../policies/alfa/Requests/orchestrator-request-simplest.json',
'../policies/alfa/Requests/orchestrator-request-simple.json',
Expand Down Expand Up @@ -63,10 +64,10 @@ def setUp(self) -> None:
makePDPFile(NOPOLICY, NOPOLICYID, NOPDP)

def tearDown(self) -> None:
print('Deleting pdp.xml file')
os.unlink('pdp-tag.xml')
os.unlink('pdp-yes.xml')
os.unlink('pdp-no.xml')
print('Deleting pdp.xml files')
os.unlink(TAGPDP)
os.unlink(YESPDP)
os.unlink(NOPDP)
pass

def runOnAllRequests(self, pdpFile, outcome='Permit', printResponse=False):
Expand Down Expand Up @@ -441,7 +442,7 @@ def testModifyFail1(self) -> None:
def testFABNetv4ExtOK(self) -> None:

"""
Test that adding FABNetv4 with proper tag works
Test that adding FABNetv4Ext with proper tag works
"""
t = fu.ExperimentTopology()
n1 = t.add_node(name='n1', site='RENC', capacities=fu.Capacities(core=1, ram=10, disk=25))
Expand Down Expand Up @@ -479,7 +480,7 @@ def testFABNetv4ExtOK(self) -> None:
def testFABNetv4ExtFail(self) -> None:

"""
Test that adding FABNetv4 with proper tag fails
Test that adding FABNetv4Ext without proper tag fails
"""
t = fu.ExperimentTopology()
n1 = t.add_node(name='n1', site='RENC', capacities=fu.Capacities(core=1, ram=10, disk=25))
Expand Down Expand Up @@ -517,7 +518,7 @@ def testFABNetv4ExtFail(self) -> None:
def testFABNetv6ExtOK(self) -> None:

"""
Test that adding FABNetv4 with proper tag works
Test that adding FABNetv6Ext with proper tag works
"""
t = fu.ExperimentTopology()
n1 = t.add_node(name='n1', site='RENC', capacities=fu.Capacities(core=1, ram=10, disk=25))
Expand Down Expand Up @@ -555,7 +556,7 @@ def testFABNetv6ExtOK(self) -> None:
def testFABNetv6ExtFail(self) -> None:

"""
Test that adding FABNetv4 with proper tag fails
Test that adding FABNetv6Ext without proper tag fails
"""
t = fu.ExperimentTopology()
n1 = t.add_node(name='n1', site='RENC', capacities=fu.Capacities(core=1, ram=10, disk=25))
Expand Down Expand Up @@ -684,4 +685,115 @@ def testFacilityFail(self) -> None:
authz.set_resource_subject_and_project(subject_id='[email protected]', project='MyProject')

print(f"FacilityFail: {authz.transform_to_pdp_request()}")
self.runOnStringRequest(authz.transform_to_pdp_request(), TAGPDP, 'Deny')
self.runOnStringRequest(authz.transform_to_pdp_request(), TAGPDP, 'Deny')

def testEducationalOK(self) -> None:

"""
Test that adding using EDUKY with Project.Educational is OK
"""
t = fu.ExperimentTopology()
n1 = t.add_node(name='n1', site='EDUKY', capacities=fu.Capacities(core=1, ram=10, disk=25))
c1 = n1.add_component(name='c1', model_type=fu.ComponentModelType.SmartNIC_ConnectX_6)
c2 = n1.add_component(name='c2', model_type=fu.ComponentModelType.SharedNIC_ConnectX_6)
n2 = t.add_node(name='n2', site='EDUKY', capacities=fu.Capacities(core=10, ram=10, disk=35))
c4 = n2.add_component(name='c4', model_type=fu.ComponentModelType.SmartNIC_ConnectX_5)
s1 = t.add_network_service(name='s1', nstype=fu.ServiceType.FABNetv6Ext,
interfaces=[c1.interface_list[0]])
s2 = t.add_network_service(name='s2', nstype=fu.ServiceType.FABNetv6Ext,
interfaces=[c4.interface_list[0]])

t.validate()

authz = ResourceAuthZAttributes()

now = datetime.datetime.now(datetime.timezone.utc)
delta = datetime.timedelta(days=13, hours=11, minutes=7, seconds=4, milliseconds=10)
future = now + delta

authz.collect_resource_attributes(source=t)
authz.set_action('create')
authz.set_lifetime(future)
authz.set_subject_attributes(subject_id='[email protected]', project='MyProject', project_tag=[
'VM.NoLimit',
'Component.SmartNIC', 'Net.FABNetv6Ext',
'Project.Educational'
])
authz.set_resource_subject_and_project(subject_id='[email protected]', project='MyProject')

print(f"EducationalOK: {authz.transform_to_pdp_request()}")
self.runOnStringRequest(authz.transform_to_pdp_request(), TAGPDP)

def testEducationalFail(self) -> None:

"""
Test that adding using non-UKY with Project.Educational fails
"""
t = fu.ExperimentTopology()
n1 = t.add_node(name='n1', site='RENC', capacities=fu.Capacities(core=1, ram=10, disk=25))
c1 = n1.add_component(name='c1', model_type=fu.ComponentModelType.SmartNIC_ConnectX_6)
c2 = n1.add_component(name='c2', model_type=fu.ComponentModelType.SharedNIC_ConnectX_6)
n2 = t.add_node(name='n2', site='RENC', capacities=fu.Capacities(core=10, ram=10, disk=35))
c4 = n2.add_component(name='c4', model_type=fu.ComponentModelType.SmartNIC_ConnectX_5)
s1 = t.add_network_service(name='s1', nstype=fu.ServiceType.FABNetv6Ext,
interfaces=[c1.interface_list[0]])
s2 = t.add_network_service(name='s2', nstype=fu.ServiceType.FABNetv6Ext,
interfaces=[c4.interface_list[0]])

t.validate()

authz = ResourceAuthZAttributes()

now = datetime.datetime.now(datetime.timezone.utc)
delta = datetime.timedelta(days=13, hours=11, minutes=7, seconds=4, milliseconds=10)
future = now + delta

authz.collect_resource_attributes(source=t)
authz.set_action('create')
authz.set_lifetime(future)
authz.set_subject_attributes(subject_id='[email protected]', project='MyProject', project_tag=[
'VM.NoLimit',
'Component.SmartNIC', 'Net.FABNetv6Ext',
'Project.Educational'
])
authz.set_resource_subject_and_project(subject_id='[email protected]', project='MyProject')

print(f"EducationalFail: {authz.transform_to_pdp_request()}")
self.runOnStringRequest(authz.transform_to_pdp_request(), TAGPDP, 'Deny')

def testEducationalMultisiteOK(self) -> None:

"""
Test that adding using non-UKY with Project.Educational and Slice.Multisite is OK
"""
t = fu.ExperimentTopology()
n1 = t.add_node(name='n1', site='RENC', capacities=fu.Capacities(core=1, ram=10, disk=25))
c1 = n1.add_component(name='c1', model_type=fu.ComponentModelType.SmartNIC_ConnectX_6)
c2 = n1.add_component(name='c2', model_type=fu.ComponentModelType.SharedNIC_ConnectX_6)
n2 = t.add_node(name='n2', site='UKY', capacities=fu.Capacities(core=10, ram=10, disk=35))
c4 = n2.add_component(name='c4', model_type=fu.ComponentModelType.SmartNIC_ConnectX_5)
s1 = t.add_network_service(name='s1', nstype=fu.ServiceType.FABNetv6Ext,
interfaces=[c1.interface_list[0]])
s2 = t.add_network_service(name='s2', nstype=fu.ServiceType.FABNetv6Ext,
interfaces=[c4.interface_list[0]])

t.validate()

authz = ResourceAuthZAttributes()

now = datetime.datetime.now(datetime.timezone.utc)
delta = datetime.timedelta(days=13, hours=11, minutes=7, seconds=4, milliseconds=10)
future = now + delta

authz.collect_resource_attributes(source=t)
authz.set_action('create')
authz.set_lifetime(future)
authz.set_subject_attributes(subject_id='[email protected]', project='MyProject', project_tag=[
'VM.NoLimit',
'Component.SmartNIC', 'Net.FABNetv6Ext',
'Project.Educational', 'Slice.Multisite'
])
authz.set_resource_subject_and_project(subject_id='[email protected]', project='MyProject')

print(f"EducationalMultisiteOK: {authz.transform_to_pdp_request()}")
self.runOnStringRequest(authz.transform_to_pdp_request(), TAGPDP)

0 comments on commit 3bb11b9

Please sign in to comment.