eXtreme Enterprise Security

Post on 10-May-2015

546 views 0 download

Tags:

description

Security ist nach wie vor das Sorgenkind in Java EE. Das rollenbasierte Access-Control-Konzept hat sich in der Praxis als untauglich erwiesen. Die Session stellt einen alternativen Ansatz vor – Domain Security. Dabei wird gezeigt, wie zur Gewährleistung der Wartbarkeit eine Trennung von Business- und Zugriffslogik erreicht werden kann, auch wenn der Zugriff durch die Fachlichkeit bestimmt wird.

Transcript of eXtreme Enterprise Security

Arne Limburg / open knowledge GmbH

eXtreme Enterprise Security

Meine Person Arne Limburg @ArneLimburg Enterprise Architect @_openknowledge open knowledge GmbH www.openknowledge.de Schwerpunkte •  JPA •  CDI

Enterprise Application Security

Authentication

Authorization Network Security -  OS -  Firewall -  TCP/IP

Webserver -  Konfiguration

Kommunikationssicherheit -  HTTP / HTTPS -  Application-Firewall

Beispielanwendung E-Learning Plattform

Security-Anforderungen

•  Nur Dozenten dürfen Kurse anlegen •  Dozenten dürfen Veranstaltungen für

ihre Kurse anlegen •  Dozenten dürfen nur Studenten sehen,

die an ihren Kursen teilnehmen •  Studenten dürfen nur Mitstudenten

sehen, mit denen sie gemeinsame Kurse haben

Authentication vs. Authorization

Wer ist der aktuelle Benutzer?

Authentication

Nutzername / Kennwort

Public Key

OAuth

Biometrisch

Kerberos

Authentication in einer Web-App. web.xml

<login-config> <auth-method>FORM</auth-method> <realm-name>JAAS</realm-name> <form-login-config> <form-login-page>/login.xhtml</…> <form-error-page>/error.xhtml</…> </form-login-config> </login-config>

Servlet 3.0 Authentication public void login(HttpServletRequest request, String username, String password) { request.login(username, password); } public void logout(HttpServletRequest req) { req.logout(); }

Was darf der aktuelle Benutzer?

Authorization

Rollenbasiert

User-Permissions

Access Control Lists

Domain-Object-Security

JAAS

•  Pluggable Authentication •  Authorization

– Pluggable Policy-Provider – Permission-Checks über AccessController

Java Permissions Policy-Datei

grant principal de…User "arne" { de…ExecPermission "de…CourseDao.find*" } grant principal de…User "admin" { de…ExecPermission "de…CourseDao.*" }

Java Permissions

public class ExecPermission extends BasicPermission { public ExecPermission(String methodName) { super(methodName); } }

Java Permissions public void create(Course course) { String methodName = "de…CourseDao.create"; AccessController.checkPermission( new ExecPermission(methodName); ); entityManager.persist(course); }

Fazit Permissons

•  Jede Security-Anforderung abbildbar •  Aber

– Viel zu aufwendig – Schlecht wartbar

èErweiterungen nötig

Was darf der aktuelle Benutzer?

Authorization

Rollenbasiert

User-Permissions

Access Control Lists

Domain-Object-Security

Role based Access Control

Create Course

See Course

Permissions

See Student

Teacher

Student

Roles Users

Teacher 1

Student 1

Student 2

Role based Access Control

Servlet Spec à Permissions für Web-Resources

Role based Access Control web.xml

<security-constraint> <web-resource-name>New Course</…> <url-pattern>/courses/create.xhtml</…> <auth-constraint> <role-name>teacher</…> </auth-constraint> </security-constraint>

Role based Access Control

Servlet Spec à Permissions für Web-Resources

Java EE Security

à Permissions für Klassen und Methoden

Role based Access Control in Java EE

@DeclareRoles @RolesAllowed @PermitAll @DenyAll

Role Based Access Control @RolesAllowed("teacher") public Course create(Teacher lecturer, …) { Course course = new Course(lecturer, …); entityManager.persist(course); return course; }

@RolesAllowed("teacher") public Course create(Teacher lecturer, …) { Course course = new Course(lecturer, …); entityManager.persist(course); return course; }

Anforderung: Dozenten dürfen nur ihre Kurse anlegen.

Anforderung: Dozenten dürfen nur ihre Kurse anlegen.

Role Based Access Control

Role Based Access Control @Resource private EjbContext context; public Course create(Teacher lecturer, …) { Principal caller = ejbContext.getCallerPrincipal(); if (!lecturer.equals(caller)) { throw new SecurityException(…); } … }

Role Based Access Control @Resource private EjbContext context; public Course create(Teacher lecturer, …) { Principal caller = ejbContext.getCallerPrincipal(); if (!lecturer.equals(caller)) { throw new SecurityException(…); } … }

Das Rollenkonzept ist sehr limitiert!

Komplexere Access-Control-Anforderungen finden sich im Code „verstreut“ wieder!

èWartbarkeits- und Erweiterbarkeitsprobleme!

Alternativen zu Role based Access Control?

Alternativen zu Role based Access Control?

Die Rechte sollten nicht danach vergeben werden, was der Benutzer ist

(welche Rolle er hat), sondern danach, was er darf!

<h:outputLink value="editCourse.xhtml" rendered ="#{sec:isUserInRole('teacher')}"/> <f:param name="courseId" value="#{course.id}"/> <h:outputText value="Edit Course"/> </h:outputLink>

Beispiel I

Beispiel I <h:outputLink value="editCourse.xhtml" rendered ="#{sec:isUserInRole('teacher')}"/> <f:param name="courseId" value="#{course.id}"/> <h:outputText value="Edit Course"/> </h:outputLink>

Beispiel I <h:outputLink value="editCourse.xhtml" rendered ="#{sec:hasPermission('editCourse')}"/> <f:param name="courseId" value="#{course.id}"/> <h:outputText value="Edit Course"/> </h:outputLink>

Beispiel I <h:outputLink value="editCourse.xhtml" rendered ="#{sec:canUpdate(course)}"/> <f:param name="courseId" value="#{course.id}"/> <h:outputText value="Edit Course"/> </h:outputLink>

<h:outputLink value="createLesson.xhtml" rendered ="#{sec:isUserInRole('teacher')}"/> <f:param name="courseId" value="#{course.id}"/> <h:outputText value="Create Lesson"/> </h:outputLink>

Beispiel II

<h:outputLink value="createLesson.xhtml" rendered ="#{sec:isUserInRole('teacher')}"/> <f:param name="courseId" value="#{course.id}"/> <h:outputText value="Create Lesson"/> </h:outputLink>

Beispiel II

<h:outputLink value="createLesson.xhtml" rendered ="#{sec:hasPermission('createLesson')}"/> <f:param name="courseId" value="#{course.id}"/> <h:outputText value="Create Lesson"/> </h:outputLink>

Beispiel II

<h:outputLink value="createLesson.xhtml" rendered ="#{sec:canCreate('Lesson', course)}"/> <f:param name="courseId" value="#{course.id}"/> <h:outputText value="Create Lesson"/> </h:outputLink>

Beispiel II

Authorization-Konzepte – Bewertung

Entwicklungsaufwand

Laufzeit

Separation of Concern

Was darf der aktuelle Benutzer?

Authorization

Rollenbasiert

User-Permissions

Access Control Lists

Domain-Object-Security

Access Control Lists

Object Access Control List

Access Control Entry Access Control Entry Access Control Entry

User 1

User 2

User 3

Spring Security

Security für spring-basierten Web-Apps •  Umfangreiche Authentication-Module •  Authorization

– Request-basiert – Methoden-basiert – Access Control Lists

ACLs in Spring Security public List<Student> findAll() { TypedQuery<Student> query = entityManager.createNamedQuery(…, …); return query.getResultList(); }

ACLs in Spring Security public List<Student> findAll() { TypedQuery<Student> query = entityManager.createNamedQuery(…, …); return query.getResultList(); }

Anforderungen: Dozenten dürfen nur Studenten sehen, die ihre

Kurse besuchen.

Studenten dürfen nur Kommilitonen sehen, mit denen sie gemeinsame Kurse haben.

ACLs in Spring Security

Spring Context

<global-method-security pre-post-annotations="enabled" />

ACLs in Spring Security @PostFilter ("hasPermission(filterObject, 'read')") public List<Student> findAll() { TypedQuery<Student> query = entityManager.createNamedQuery(…, …); return query.getResultList(); }

ACLs in Spring Security @PostFilter ("hasPermission(filterObject, 'read')") public List<Student> findAll() { TypedQuery<Student> query = entityManager.createNamedQuery(…, …); return query.getResultList(); }

Problem:

Filtern passiert im Speicher!

èSchlechte Performance bei großen Datenmengen!

ACLs in Spring Security @PreAuthorize ("hasPermission(#course, 'create')") public void create(Course course) { entityManager.persist(course); }

AccessDeniedException

ACLs in Spring Security @PreAuthorize ("hasPermission(#course, 'create')") public void create(Course course) { entityManager.persist(course); }

AccessDeniedException

Weiteres Problem:

Wie kommen die ACLs in die Datenbank?

ACLs in Spring Security @PreAuthorize ("hasPermission(#course, 'create')") public void create(Course course) { entityManager.persist(course); }

ACLs in Spring Security @PostAuthorize ("hasPermission(returnedObject, 'create')") public Course create(Course course) { entityManager.persist(course); return course; }

ACLs in Spring Security @PostAuthorize ("hasPermission(returnedObject, 'create')") public Course create(Course course) { entityManager.persist(course); ObjectIdentity identity = new ObjectIdentityImpl(Course.class, course.getId()); … }

ACLs in Spring Security @PostAuthorize ("hasPermission(returnedObject, 'create')") public Course create(Course course) { entityManager.persist(course); ObjectIdentity identity = …; String name = course.getTeacher().getName(); PrincipalSid principal = new PrincipalSid(name);

ACLs in Spring Security @PostAuthorize ("hasPermission(returnedObject, 'create')") public Course create(Course course) { entityManager.persist(course); ObjectIdentity identity = …; PrincipalSid principal = …; MutableAcl acl = aclService.createAcl(i); acl.insertAce(0, CREATE, principal, true); aclService.updateAcl(acl); return course; }

ACLs in Spring Security public void add(Course course, Student student) { course.subscribe(student); createACE(student, course.getLecturer()); for (Student participant: course.getParticipants()) { createACE(student, participant); createACE(participant, student); } }

ACLs in Spring Security public void add(Course course, Student student) { course.subscribe(student); createACE(student, course.getLecturer()); for (Student participant: course.getParticipants()) { createACE(student, participant); createACE(participant, student); } }

Anlegen und Löschen von ACLs findet sich im Code „verstreut“ wieder!

èWartbarkeits- und Erweiterbarkeitsprobleme!

Was passiert, wenn ein Entwickler vergisst, eine ACL anzulegen oder zu löschen?

Laufzeit Laufzeit

Entwicklungsaufwand Entwicklungsaufwand

Separation of Concern

Fazit ACLs in Spring Security

Separation of Concern

Was darf der aktuelle Benutzer?

Authorization

Rollenbasiert

User-Permissions Domain-Object-Security

Access Control Lists

Domain-Object-basiert @PreAuthorize("#lecturer == principal") @PostAuthorize ("returnedObject.lecturer == principal") public Course create(Teacher lecturer, …) { Course course = new Course(lecturer, …); entityManager.persist(course); return course; }

Domain-Object-basiert @PreAuthorize("#lecturer == principal") @PostAuthorize ("returnedObject.lecturer == principal") public Course create(Teacher lecturer, …) { Course course = new Course(lecturer, …); entityManager.persist(course); return course; }

Was ist, wenn das Anlegen des Kurses nicht über die create-Methode erfolgt?

Seam Security

Security für Seam Anwendungen •  JAAS-based Authentication •  Rule-based Authorization

– Seam 2 Security: Drools – Seam 3 Security: Picketlink mit AuthZ

Seam 2 Security

Security für Seam Anwendungen •  JAAS-based Authentication •  Rule-based Authorization

– JSF-Pages – Business-Logik – Entities

Entity-Security in Seam 2 @Restrict @Entity public Course { … }

Entity-Security in Seam 2 Drools Konfiguration rule CreateCourse no-loop activation-group "permission" when principal: Principal() course: Course(lecturer: lecturer -> (lecturer.equals(principal))) check: PermissionCheck(target == course, action == "insert", granted == false) then check.grant(); end;

Entity-Security mit Seam 2 orm.xml

<persistence-unit-metadata> <persistence-unit-defaults> <entity-listeners> <entity-listener class= "org.jboss.seam.security.EntitySecurityListener" /> </entity-listeners> </persistence-unit-defaults> </persistence-unit-metadata>

Entity-Security mit Seam 2 public List<Student> findAll() { TypedQuery<Student> query = entityManager.createNamedQuery(…, …); return query.getResultList(); }

AuthorizationException

Entity-Security mit Seam 2 public List<Student> findAll() { TypedQuery<Student> query = entityManager.createNamedQuery(…, …); return query.getResultList(); }

AuthorizationException

èZwei Methoden notwendig

Entity-Security mit Seam 2 public List<Student> find(Teacher lecturer) { … } public List<Student> find(Student fellow) { … }

Entity-Security mit Seam 2 public List<Student> find(Teacher lecturer) { … } public List<Student> find(Student fellow) { … }

Aufruf geschieht auf Basis des aktuell angemeldeten Benutzers!

Entity-Security mit Seam 2 public List<Student> findAll() { Principal caller = ejbContext.getCallerPrincipal(); if (caller instanceof Teacher) { return find((Teacher)caller); } else { return find((Student)caller); } }

Entity-Security mit Seam 2 public List<Student> findAll() { Principal caller = ejbContext.getCallerPrincipal(); if (caller instanceof Teacher) { return find((Teacher)caller); } else { return find((Student)caller); } }

Wieder Security im Code „verstreut“!

Laufzeit Laufzeit

Entwicklungsaufwand Entwicklungsaufwand

Separation of Concern

Fazit Entity-Security mit Seam Security

Separation of Concern

JPA Security

Security Framework für JPA •  Pluggable Authentication •  Authorization

– JSP- und JSF-Support – Access-Check bei CRUD-Operationen –  In-Memory-Filtern von Collections –  In-Database-Filtern von Queries

(JPQL und Criteria)

@Permit(access = AccessType.CREATE, rule = "lecturer = CURRENT_PRINCIPAL") @Entity public Course { … }

Entity-Security mit JPA Security

@Permit(access = AccessType.CREATE, rule = "lecturer = CURRENT_PRINCIPAL") @Entity public Course { … }

Automatischer Check bei entityManager.persist(…) oder entityManager.merge(…) oder bei

Cascarding!

Entity-Security mit JPA Security

Entity-Security mit JPA Security public List<Student> findAll() { TypedQuery<Student> query = entityManager.createNamedQuery(…, …); return query.getResultList(); }

Entity-Security mit JPA Security public List<Student> findAll() { TypedQuery<Student> query = entityManager.createNamedQuery(…, …); return query.getResultList(); }

Automatische Filterung von JPA Queries und Criterias!

@PermitAny({ @Permit(access = AccessType.READ, rule = "this IN (SELECT p" + " FROM Course course" + " JOIN course.participants p" + " WHERE course.lecturer" + " = CURRENT_PRINCIPAL"), @Permit(…)}) @Entity public Student { …

Entity-Security mit JPA Security

Entity-Security mit JPA Security persistence.xml

<persistence …> <persistence-unit name="…"> <provider>org.hibernate.ejb.HibernatePersistence</…> <properties> … </properties> </persistence-unit> </persistence>

<persistence …> <persistence-unit name="…"> <provider>net.sf.jpase…SecurePersistenceProvider</…> <properties> <property name="net.sf.jpasecurity.persistence.provider" value="org.hibernate.ejb.HibernatePersistence"/> </properties> </persistence-unit> </persistence>

<persistence …> <persistence-unit name="…"> <provider>net.sf.jpase…SecurePersistenceProvider</…> <properties> </properties> </persistence-unit> </persistence>

Entity-Security mit JPA Security persistence.xml

Laufzeit Laufzeit

Entwicklungsaufwand Entwicklungsaufwand

Separation of Concern

Fazit JPA Security

Separation of Concern

Live Demo

Arne Limburg / open knowledge GmbH

Zeit für Fragen und Diskussion

Vielen Dank! http://www.openknowledge.de/publikationen/vortraege.html

Arne Limburg / open knowledge GmbH

Vielen Dank!