Advice for handling permissions in SAP - abap

I've created a solution where I created an authorization object which controls what can a user handle or watch in the program. This authorization object is defined with 3 elements:
Process
Activity
Material group
Through transaction 'PFCG' the BC creates the profiles according the requests that users make to have permission to some module of the program. For example, a user or a group of users will access to process 'A1' (Data update), activity '01' (Aproval) and material group 'A0A00001'. This means that these users could only aprove for process 'A1' the data for material group 'A0A00001'.
My problem here is that managers of the areas have told me that they feel uncomfortable making requests to the BC for permissions because they think that they should manage those profiles, and if they want to change those permissions they would like to have the control of them directly instead of making requests.
This is a situation where I don't know what to do, I have thought that I would make Z tables and a Z program to emulate those permissions exactly as they are handled now with transaction 'PFCG' but I feel like I'm reinventing the wheel.
Another thing that I have thought is to create a Z program that would be a layer of transaction 'PFCG' to automate the profiles for this authorization objects but in this case I don't know where to start because I would have to investigate if is there a BAPI for creating profiles and how to manage all the issues related with this management.
The other thing is leave it like that and do nothing, but sincerely I don't know what to do.
Do you have any suggestion on this issue? What can be done in this situation?

Related

DDD Request & Activity Tracking

I have a question about tracking activity and where it belongs.
With a lot of my domain commands, you also might want to track the activity and modifications made by users to a particular context or object.
For example:
lets say we have a items domain/context where we can create and edit items. Users are going to make requests to the api to do this. We might want to track who created an item and an modifications made to it.
In a typical CRUD model, you'd probably find the created by field in the domain object/table
Something doesn't feel right when using DDD to have the activity in the domain object. The activity log feels like a general service that would cross many boundaries? Is it right to have the activity log of who changed what in the domain object. It would feel quite clean and focused without it. The activity logging seems specific to the applications case, not the domain?
So:
Should the activity tracking be in the domain object?
If it shouldn't how do you go about handling this in one command/request. I keep hearing people saying about you should only touch 1 boundary in a command/request.
I would think of this activity log as any other piece of data. You would put it together with the business logic around it. Why do you need this information in the first place? Is your items context going to implement business logic that needs the activity log? If not, then I'd say it doesn't belong in that context.
If what you are trying to achieve with this log is some data analysis that needs the activity from several contexts, then I would say publish events from your business operations (every time a user does something with one of the contexts) and have your activity tracking context listen to them and store the activity in a way that serves this purpose.
If, instead, your items context needs to apply some sort of logic, based on the past activity, then keep it in that context in a format that allows you to implement this business logic.
It's also possible that you actually need both. Some context might just publish the events and not store the activity, while others will publish the events and also track the activity for their own internal needs.

should database verify if user is authorized to perform action

Should database be verifying if user is authorized to perform certain action?
Two examples:
1)User is enrolled in 30 teams max and it can see scoresheet of these teams only. I'm passing in userid and teamid to the stored procedure and fetching the scoresheet only if user is authorized to view the scoresheet. Is it more appropriate to only pass in only teamid and check beforehand what all teams user is enrolled in? Should I do both?
2)Currently I'm passing in userid of the poster and the commentid of the comment to be deleted and I'm deleting comment only if both criteria is met - userid matches to the poster id and commentid matches to the commentid - just to make sure user is deleting his own comment and not somebody else's. Is it an overkill?
Multiple layers of validation is best practice and it doesn't seem like your methods would cause additional overhead. Just make sure to limit connecting to the database once, I've found that the most costly part of running database queries is the connection and cursors.
http://msdn.microsoft.com/en-us/library/aa174437%28v=sql.80%29.aspx
Security experts will tell you that No amount of security is enough! But at the same time you have to find a balance b/w security and unnecessary layers of protection that are bound to affect your application's performance.
Answering your 2nd question first: It is a good idea to pass both userid as well as commentid, and matching both, so that you accidentally don't delete all comments by a particular user.
Coming to your 1st question now: As I understand it, you want users only part of the team to be able to view the team's scoresheet, right? In order to do so passing only the teamid of all the teams the user is a part of will do. I am not sure what you mean by authorization here!
NOTE:
I have answered your question from a theoretical view with no idea about your Table structure or whats written in your Stored Procedures.
Your frontend is a much more friendlier (libraries, frameworks, best practices) environment to implement whatever access restrictions or authorization that you could possibly have in mind. Adding another layer inside the database just adds a lot of complexity and duplicate implementation of your access restrictions.
I would only consider doing it if clients connect and execute commands directly against the database.
So, rely on the ids provided by the application and spend your energy on sanitizing user input and implementing a sane authentication model. You will need it.

Manage conflicting roles in chef

I am relatively new to chef, so I may be missing something extremely basic. After much searching I am not finding what I need, so here goes:
In Chef, I have roles that are conflicting. I need for all servers of a certain type to have roleA, except for servers with roleB.
The best way I can think of to describe it is with an example:
syslog1, syslog2
web1, web2, web3
db1, db2
mail1, mail2
Every server within this environment(dozens) has a role called syslog_client, except syslog1 and syslog2, which need to have the role syslog_server.
The syslog-server and syslog-client roles conflict, because they configure the same pieces of software differently.
These are roles rather than recipes because they actually encompass several recipes.
I thought of doing something like this:
roles/base.rb:
name "base"
description "base configuration"
override_attributes(
)
default_attributes(
)
run_list(
"recipe[one]",
"recipe[two]",
"recipe[three]",
"role[uno]"
)
unless node[:roles].include?('syslog_server')
run_list('role[syslog_client]')
end
The problem there is that the node object does not exist at this point. I have thought about moving it into the recipe, but I could not come up with a good way to do it there either. I was able to use this in the base recipe:
unless node[:roles].include?('syslog_server')
node[:roles]+=['syslog_client']
end
This adds syslog_client to the roles attribute (or doesn't) correctly, but it never actually runs the syslog_client role.
I have considered moving syslog_client into a self-contained recipe rather than a role, and moving the role attributes to the environment. This would work, because then I can just call include_recipe "syslog::client". The problem there is that virtually all of our recipes are assigned from roles (not from other recipes), and I fear that making this change will create a one-off that will be hard to keep track of. Besides that, as I mentioned already, these are actually several recipes, so adding them as a single recipe is not ideal.
We have many different server types/roles in the environment I'm currently working in, and adding role[syslog_client] to them is feasible, but not ideal. With multiple people working on this, it seems likely that someone will forget to add the recipe to a new role.
In an ideal world, something like my first solution would be possible, because that allows us to keep our environment as consistent as possible. I am open to other options though.
So to wrap up, I think what I need is someone to tell me how to:
Make the first solution work. Add a role to a run list only if another role is not present
If I cannot have #1, I'd like opinions on the best way to achieve this using the ways I've listed or other ideas I have not thought of
Please let me know if I'm missing any details about our chef setup that will be helpful.
Disclaimer: The above example is really a very simplified version of what I'm actually trying to achieve. I'm not even working with syslog, but the company it is for is very security-conscious and would not be happy with details of their environment being posted publicly. I will be as detailed as I possibly can if I've left anything out and I need to add further info.
Extending what was said above what's the issue with creating two roles. A Client and a server
The Client role includes the base role and the client function. It will get applied to all servers through replacing references to 'base' with this role in all other roles. Meaning those roles still get base but get client as well.
The server is a stand-alone role which only applies to those servers and has the base and then the server role?
That way both client and server get the base role applied to them without duplicating the definition of what the base role is. You still manage that base role as you want but you use aggregation in the creation of roles?
When a new role is created the user won't start by adding base but instead adding the syslog_client role which gives them base as well.
To me that feels like the way Chef is pushing you with the creation of roles. What we have is 1 role that applies to all servers, some that apply to 1 subtype of servers but not anothers. That way our leaf role as in the one that gets applied actually consists of 4 or 5 other roles. What's common is modelled in a way that can be shared without the need for logic within?
The other option would be to add the client recipe to every node and the first exeuction step is to check the nodes role and if it says server just basically skip the recipe execution? Which would be the same as the logic which you were wanting to use to add the recipe but it would live in the recipe and control the execution?
unless node[:roles].include?('syslog_server')
#Do your client install
end

How should I depict "User wants to see his profile" in a Dataflow Diagram? Maybe I shouldn't?

I have a User that wants to see his online profile, in a site where he previously has registered at. I am in charge of making a Dataflow Diagram out of this situation. I know for sure that the System will return a Profile. That is why I put an arrow from System to User.
How can I express that the User is requesting his profile to the System? I can't think of a way of expressing that in a DFD. I guess it's maybe because you are only supposed to show data flow in a DFD and not actions/requests? Should I completly erase the arrow that goes from User to System(?See his profile?) ?
Context Diagram (Level 0 Dataflow Diagram)
Level 1 Dataflow Diagram
Thanks
No hard and fast answer to this. It's possible to argue against including it (could be considered a control flow, not a dataflow). However, assuming purpose of DFD is for human understanding (i.e. it's a picture to look at) go with what makes most sense to your audience.
If I were drawing it, I'd include the input flow on both L0 & L1 (probably named View Profile rather than Check his profile - I prefer imperative statements). It's both the event that triggers action, and will also likely carry data to identify the user.
I wouldn't however include the flow marked ??? on the L1 diagram. Reason: you're pulling data from a datastore so the query is implicit.
hth.

Typical normalization security issue in web applications

i am currently having a problem, i guess a lot of people have run into before and i would like to know how you handled it.
So, imagine you have 10.000 Users on your App. ( each one has an own user/pw login to administrate his stuff ).
Imagine further, that you have a growing normalized SQL-tablestructure in the backend, with tables like: Users, Orders, OrderPositions, Invoices, etc.
So, to show/edit/delete stuff of a table which isn't the usertable itself, u'll probably have links like these, to let ypur users interact with the application.
~/Orders/EditOrder?id=12
~/Orders/ShowOrderPosition?orderId=12&posId=443
Ok, and now the problem:
How, do i prevent in a "none-complex"-way, that user A has access ( show/edit/delete ) the data of user B.
Example:
User B calls:
~/Orders/ShowOrderPosition?orderId=12&posId=443
which is an order of user A, so user B should have no access to it.
So, in my code i would need to have a UserIdentity-check before or within every single SQL-statement, like:
select * from OrderPosition op, Order o, User u
where op.Id = :orderId
and op.Fk_OrderId = :orderpositionId
and o.Id = :orderId
and o.Fk_User = :userId
Only this way i can make sure, that the data belongs to the requesting user.
To reach the usertable will of course get far more complex, the deeper the usertable-connection is "buried" in the normalization ( imagine tables like payments or invoices, connected to the order-table... )
Question:
What is your approach to deal with this, concidering: Low complexity, DRY and performance
( Hope u understand what i mean ;) )
This is a bit like a multi-tenant application - I have gone down this route and denormalized an ID onto all those tables that require this kind of check (a tenant ID, in your case, sounds like the user id).
I then created an interface that contains this field only and applied it to all those classes in my model layer that required this access.
In my base data access (repository) class, where all the select/update/delete calls go through, I then check to see if the class if of the type of that interface, and I then check that the current access matches that ID.
Of course, this depends on how your code is structured, and how simple/complex making this global kind of change will be...
Never expose ids.
And if you have to: encrypt them.
Performance
for ultimate performance you will have to denormalize to the point that reading the row and comparing with some application level variable would give you an answer on what kind of rights the user has (this is fairly fast and if your DAO/BAO level is well organized plugging it in will keep it relatively DRY and at relatively low complexity.) NOTE: complexity is also a function of your security model, once you start to implement inheritable, positive and negative, role-based access rules then it can not be really simple.
DRY
another route to take (which is very seldomly taken these days) is to use your database roles to manage security; this might get complicated but will offer unparalleled security (as it will be ensured at the DB level and not application level. Complexity should go down, at the application code level, if you manage to encapsulate all of your access paths into VIEWS, which might require quite a bit of re-tailoring at the database level. However(!), it might be possible to implement security model with very little changes to the application code - by renaming existing tables and replacing them with secured views)
Don't use your internal ID column, encrypted or not, it'll come back to bite you one day.
Create a random, unique, string (GUID, whatever), which contains the link between the user and the data he's requesting. So, instead of having, for user 34567:
Edit order
Create a record {"5dsfwe8frf823jrf",34567,12} in a temporary table and show:
Edit order
When the users clicks the link, fetch 34567,12 from your temporary table.
The string 5dsfwe8frf823jrf is impossible to guess = no security risk.