TYPO3 Neos and Flow - Security 2.0

26
Security 2.0 Andreas Förthner Bastian Waidelich

Transcript of TYPO3 Neos and Flow - Security 2.0

Security 2.0

Andreas Förthner Bastian Waidelich

What is security?

Goals

• Perfect fit for Neos

• Separated from code

• Fast

• Declarative

Why change it?

Extensibility!

Security 2.0

It’s all about protecting database reads and method calls!

How would that work?

Changing the title of a page

fancy AOP magic

included!

method(Node->setProperty(propertyName == "title"))

How would that work?

Visibility of a page

mind blowing SQL

rewrites in the

wild!

this.workspace.name != ''live''

Your benefit!

• All privileges are defined declaratively in a central place, not in your code

• SQL constraints are faster than in memory filters

• The actual protection code is part of the framework

robust, well tested, updated in a central place

Technically that’s all you need!

Seriously?!

We want to use the Neos Language!

Am I allowed to edit this property?

Am I allowed to move this node to this target?

Am I allowed to publish this node to that workspace?

Am I allowed to see this part of the node tree?

We just invented

custom privilege types

Edit Node Read Node Create Node Move Node

Remove Node Node Tree

isDescendantNodeOf(„/sites/typo3cr/service/")

nodeIsOfType(„TYPO3.Neos.NodeTypes:Text“)

hasDimensionValue(„language“, „de_DE“)

Policy.yaml:

privilegeTargets:

'TYPO3\TYPO3CR\Security\Authorization\Privilege\Node\ReadNodePrivilege': 'Acme.SomePackage:CustomerArea': matcher: 'isDescendantNodeOf("/sites/yoursite/customers")'

'TYPO3\TYPO3CR\Security\Authorization\Privilege\Node\CreateNodePrivilege': 'Acme.SomePackage:CreateTextElementsOnProductPages': matcher: 'isDescendantNodeOf("/sites/yoursite/products") && createdNodeIsOfType("TYPO3.Neos.NodeTypes:Text")'

roles: 'TYPO3.Flow:Everybody': privileges: - privilegeTarget: 'Acme.SomePackage:CreateTextElementsOnProductPages' permission: GRANT

‚Acme.SomePackage:RegisteredCustomers': privileges: - privilegeTarget: 'Acme.SomePackage:CustomerArea' permission: GRANT

Behind the scenes

1. Privilege types are real php classes

2. Functionality can be inherited!

3. Eel is used for the expressions

4. You can easily implement your own types

Neos Privilege Architecture

Method

Entity ReadNode

EditNode

MoveNode

RemoveNode

CreateNode

NodeTree

Use cases

1. Neos Comment Form

1. Neos Comment FormNodeTypes.yaml: 'Acme.YourSite:CommentForm': superTypes: ['TYPO3.Neos:Content'] ui: label: 'Comment Form'

CommentForm.html: <f:form actionUri="{neos:uri.node()}" objectName="newNode"> <f:form.hidden name="referenceNode" value="{node.path}" /> <f:form.hidden property="__nodeType" value="TYPO3.Neos.NodeTypes:Text" /> <f:form.textarea property="text" /> <f:form.submit value="Send comment" /></f:form>

Policy.yaml: privilegeTargets: 'TYPO3\TYPO3CR\Security\Authorization\Privilege\Node\CreateNodePrivilege': 'Acme.SomePackage:CreateCommentNode': matcher: 'isDescendantNodeOf("/sites/yoursite/comments") && createdNodeIsOfType("TYPO3.Neos.NodeTypes:Text")'roles: 'TYPO3.Flow:Everybody': privileges: - privilegeTarget: 'Acme.SomePackage:CreateCommentNode' permission: GRANT

2. Document ManagementAuthorizationService.php: public function isAllowed($document, $privilege = self::PRIVILEGE_READ) { if ($this->getAuthenticatedUser() === NULL) { return FALSE; } if ($this->getAuthenticatedUser()->isAdministrator()) { return TRUE; } switch ($privilege) { case self::PRIVILEGE_READ: return $this->isAllowedToReadDocument($document); case self::PRIVILEGE_CREATE: case self::PRIVILEGE_UPDATE: case self::PRIVILEGE_DELETE: return $this->hasAccessToResource('Acme_SomePackage_DocumentAdministration') && $this->isAllowedToEditCategory($document->getCategory()); case self::PRIVILEGE_VIEW_USER_GROUPS: return $this->isAllowedToViewUserGroupsOfDocument($document); } }

2. Document ManagementPolicy.yaml: privilegeTargets: 'Acme\SomePackage\Security\Authorization\Privilege\EditDocumentPrivilege': 'Acme.SomePackage:DocumentAdministration': matcher: 'documentIsInCategory(authenticatedUser.allowedCategories)'

SomePhpFile.php: $documentSubject = new EditDocumentPrivilegeSubject($document); $this->privilegeManager->isGranted(EditDocumentPrivilege::class, $documentSubject);

SomeFluidTemplate.html: <x:security.isAllowedToEditDocument document="{document}"> <!-- edit links, ... --></x:security.isAllowedToEditDocument>

Questions?

Bastian Waidelich @bwaidelich

Andreas Förthner @t3andi