Different Response based on ACL with FOS Rest Bundle - symfony

I search for a best practice method how I can send different users, different responses back based on the ACL from Symfony.
I use the FoS RestBundle. They provide the JMSSerializerBundle which I use. I've created models and serializer yml-files, so far, so good. Everything looks great and works.
Now I have different Users that access this REST API. Some of them have expanded permissions, so they are allowed to see more information. What is the best practice for handle them?
It's necessary that the URL is the same for everyone.

You can start by using serialization groups:
http://symfony.com/blog/new-in-symfony-2-7-serialization-groups
After that you can choose which group you want to your response:
http://symfony.com/doc/current/cookbook/serializer.html
You can still use the same YML you are using:
http://jmsyst.com/libs/serializer/master/reference/yml_reference
Check the groups attribute!
This should be enough, if you need more acl as well:
http://symfony.com/doc/current/cookbook/security/acl.html
Good luck, I hope this helps you!

Related

Pact. How to test a REST GET with automatically generated ID in the URL

I want to test a REST service that returns the detail of a given entity identified by an UUID, i.e. my consumer pact has an interaction requesting a GET like this:
/cities/123e4567-e89b-12d3-a456-426655440000
So I need this specific record to exist in the Database for the pact verifier to find it. In other projects I've achieved this executing an SQL INSERT in the state setup, but in this case I'd prefer to use the microservice's JPA utilities for accessing to the DB, because the data model is quite complex and using these utilities would save me much effort and make the test much more maintainable.
The problem is that these utilities do not allow specifying the identifier when you create a new record (they assign an automatic ID). So after creating the entity (in the state setup) I'd like to tell the pact verifier to use the generated ID rather than the one specified by the consumer pact.
As far as I know, Pact matching techniques are not useful here because I need the microservice to receive this specific ID. Is there any way for the verifier to be aware of the correct ID to use in the call to the service?
You have two options here:
Option 1 - Find a way to use the UUID from the pact file
This option (in my option) would be the better one, because you are using well known values for you verification. With JPA, I think you may be able to disable the auto-generation of the ID. And if you are using Hibernate as the JPA provider, it may not generate an ID if you have provided it one (i.e. setting the ID on the entity to the one from the pact file before saving it). This is what I have done recently.
Using a generator (as mentioned by Beth) would be a good mechanism for this problem, but there is no current way to provide a generator to use a specific value. They generate random ones on the fly.
Option 2 - Replace the ID in the URL
Depending on how you run the verification, you could use a request filter to change the UUID in the URL to the one which was created during the provider state callback. However, I feel this is a potentially bad thing to do, because you could change the request in a way that weakens the contract. You will not be verifying that your provider adheres to what the consumer specified.
If you choose this option, be careful to only change the UUID portion of the URL and nothing else.
For information on request filters, have a look at Gradle - Modifying the requests before they are sent and JUnit - Modifying the requests before they are sent in the Pact-JVM readmes.
Unfortunately not. The provider side verifier takes this information from the pact file itself and so can't know how to send anything else.
The best option is to use provider states to manage the injection of the specific record prior this test case (or to just have the correct record in there in the first place).
You use the JPA libraries during the provider state setup to modify the UUID in record to what you're expecting.
If you are using pact-jvm on both the consumer and provider sides, I believe you may be able to use 'generators', but you'll need to look up the documentation on that as I haven't used them.

How should I handle permission/role checking in this situation?

I have a CMS system where admin can create user groups and can grant permissions to groups to do certain things. The permissions (CRUD) are granted on the objects (i.e: can add post, can edit own post, can delete someone else's post, ...)
It's easy to come to the conclusion that we should use something like the provided ACL and store permissions on object or class. However, the question is where should we put these security checking code?
One thing came to my mind was to put that in the controller, but now it means I have to edit every controller I have, or even if I don't I need to somehow identify the object/class that the specific controller action is trying to modify. Sometimes, the controller action will involve several objects/models at once and that makes things even more complicated.
I could also put that in the manager, so that whenever I invoke the save() method I can check for permission. For some reason, that approach seems wrong in term of performance and complexity.
I have read many posts explaining voters, acl and such for Symfony and I understand all that but I'm having trouble putting all that into a solution that would avoid dirty hacks such as editing every single controller.

Symfony dynamic firewall

On a large webapplication, I want our customers to be able to enable/configure their own sigle sign-on (SAML) identity provider. Each customer has it's own specific subdomain allowing our application to determine which firewall should be active.
However, I don't want to manually configure each new firewall and clear the cache before changes are taken into effect. Now I read about dependency injection, extensions, compilers and all that, but I just can't seem to find a way to load dynamic firewall settings from the database and apply them. Any idea how I would do this?
FYI, I am using the SamlSPBundle for SSO.
Thanks!
I may have figured this out just moments after setting a bounty! ;)
Symfony2 security allows specification of a request_matcher on a per-firewall basis:
http://php-and-symfony.matthiasnoback.nl/2012/07/symfony2-security-using-advanced-request-matchers-to-activate-firewalls/
Custom RequestMatchers must implement a single method that returns true or false based on the Request object. I think this could be used to activate a firewall dynamically. As long as you have a finite number of firewalls (I do), then a custom RequestMatcher could solve your problem.

Asp.net Page access through IP address control

Is it possible to create a page in asp.net that allow the access to a user that has a defined IPaddres? My goal is to add a page "test" (not linked to my website) and I want to define a rule that only a specified IP address can get the access.
How can I implement this throught asp.net?
You could try putting the page(s) in a separate folder and password protect it, then, give the password to your user, so they may access the content. You could go as far as password protecting each file. This helps if your website is password protected or has a login.
You could also create a sub-domain for that user specifically.
These are just a few. I'm sure you'll get better suggestions here on SO!
You could go for a programmatic solution. However, I would use IIS functions to block the access. Less code, easier to configure and no hassle on your developement/test environment.
Assumption: you are using IIS since it is ASP.NET. But other webservers should have similar solutions.
You can add IP restrictions to the directory (meaning you would have to put your page in a separate directory). Example here: http://www.therealtimeweb.com/index.cfm/2012/10/18/iis7-restrict-by-ip
Obviously there are a lot of other and arguably better ways to grant access to a page if what you really want is for a specific "user" or "group" to have access, but assuming that your really want the access control to be based on IP, the answer may still be dependent on peripheral concerns such as what web server you are using. IIS for example has some features for IP based security that you could check out.
Assuming though that you really, really want to check IPs and that you want to do it in code, you would find information about the calling environment in the Request of the current HttpContext, i.e. context.Request.UserHostAddress.
If you want to reject calls based on this information, you should probably do that as early as possible. In the HttpApplication.BeginRequest event you could check if the call is targeted for the page in question and reject the request if the UserHostAddress is not to your liking.
If you prefer to make this control in the actual page, do it in some early page event.
To manage the acceptable IP(s), rather than hard coding them into your checking code, I suggest you work with a ConfigurationSection or similar. Your checking code could be something similar to:
var authorizedIps =
authorizedIpConfiguration.Split(',').Select(ipString => ipString.Trim()).ToList();
isValid = authorizedIps.Any()
&& authorizedIps.Contains(context.Request.UserHostAddress);
If the check fails, you should alter the response accordingly, i.e. at least set its status code to 401 (http://en.wikipedia.org/wiki/List_of_HTTP_status_codes).
NB: There are a lot of things to consider when implementing security features, and the general recommendation would probably stand as "don't do it" - it's so easy to falter. Try to use well proven concepts and "standard implementations" if possible. The above example should not in itself be considered to provide a "secure" solution, as there are generally speaking many ways that restricted data can leak from you solution.
EDIT: From you comment to the answer given by nocturns2 it seems you want to restrict access to the local computer? If so, then there is a much easier and cleaner solution: Just check the Request.IsLocal property. It will return true only for requests originating from the local computer, see HttpRequest.IsLocal Property
(Also, you should really make sure that this "debug page" is not at all published when deploying your solution. If you manage that properly and securely, then perhaps you do not even need the access check any more. If you want debugging options in a "live" environment, you should probably look to HttpContext.Current.Trace or some other logging functionality.)

Symfony2 Group permissions with ACL

Where I work we are designing a webapp in which users may belong to multiple groups and each group has access on a set of resources not known in advanced. Plus, users can enter or leave groups and groups can acquire or lose access to resources, so the whole permission granting system needs to be dynamic.
We are using Symfony2 and the FOSUserBundle.
We like how the ACL system works, but we could not find a way to apply it to the Group object.
Has anyone done something like that with Symfony? Or do you have any suggestion on how to implement it in other ways?
According to the cookbook, you can use the RoleSecurityIdentity instead of just the UserSecurityIdentity. So from my understanding of it your Role is your Group. Im working on a similar issue now. When have have done a little more with it Ill try and update this with some code snippets.
But for now have a look at: http://symfony.com/doc/current/cookbook/security/acl_advanced.html
EDIT:
We have gone in another direction and are instead going more with a permission per controller action system. So every controller action is assigned a permission name using annotations.
#SomeDomain/SomeBundle/Controller/SomeController.php
/**
* #Permissions(perm="some.name.for.the.node")
*/
public function indexAction(){ ... }
Then we have a permission bundle with a service that checks the permissions when a controller function is called. Our admins are given a GUI that will allow them to manage the permissions that groups will have and individual users.
Check out this gist that inspired what we are doing: https://gist.github.com/1391850
Im aware this isnt the acl system you were looking for but just thought i would update with what we are doing.

Resources