I've been trying to "read between the lines" about the original (and/or current) motivation for the NetSqlAzMan project.
Was this written for?
An adapter for Windows Authorization Manager (AzMan). Where the methods in the NetSqlAzMan just passes calls to (Windows Authorization Manager (AzMan)), but perhaps with nicer/cleaner methods?
A replacement for (Windows Authorization Manager (AzMan)). Where (most or all of) the features available in (Windows Authorization Manager (AzMan)) are recreated in NetSqlAzMan, but the code was developed independently.
(Perhaps to provide DotNet 4.0 support???) (Perhaps to remove any COM dependencies)
To provide more features than (Windows Authorization Manager (AzMan)) provided. Aka, a "smarter"/"better" version of (Windows Authorization Manager (AzMan)).
To rewrite but also keep a semi-dead project alive through open-source. (As in, perhaps (Windows Authorization Manager (AzMan))) is a dead or abandoned project by Microsoft).
Other?
................
I like the object model of NetSqlAzMan. But I need to defend any decision to use it to my project manager(s) and other developers.
The object model seems "just right" (think goldilocks and the middle bed) as far as what I desire for security.
I do NOT want to do role based security. I want right(or task or permission) based security.
(See:
http://lostechies.com/derickbailey/2011/05/24/dont-do-role-based-authorization-checks-do-activity-based-checks/
and
http://granadacoder.wordpress.com/2010/12/01/rant-hard-coded-security-roles/
)
And basically the question that came up is: "What is the advantage of using NetSqlAzMan instead of (Windows Authorization Manager (AzMan))?"
And the sub question is "Is Windows Authorization Manager (AzMan) dead?". (And something along the lines of Long Live NetSqlAzMan!).
..................
My in-general requirements are:
Non Active-Directory users. (Down the road Active Directory and/or LDAP support would be nice, but not a requirement).
Passwords not stored as plain text.
Be able to handle RIGHTS for security checks.
Group the rights under any role.
Assign roles to users. (But again, the code will check for the right, not the role when performing an action.)
Allow (on occasion) rights to be assigned to users. With a Deny override. (Aka, a single user who does on stupid thing (like "Delete Employee") can have that right revoked.)
Roles and Rights can be maintained for multiple applications.
So other ideas are welcome. But Windows Identity Foundation seems like a little overkill.
Thanks.
I finally found a "compare" article last night.
http://www.c-sharpcorner.com/uploadfile/a.ferendeles/netsqlazman12122006123316pm/netsqlazman.aspx
I am going to paste the relevant portion here (below). (Just in case that website ceases to exist in the future. Small chance, I know, but I hate "The answer is here" links, and when you hit the link, it is a dead one.)
From what I can tell.
NetSqlAzMan provides a (table) user-defined-function that you can overload to provide a list of users (to be assigned to roles/tasks).
NetSqlAzMan provides not only "Yeah you can" mappings (Grant), but also Deny and Grant-With-Delegate as well.
NetSqlAzMan and Azman allows users(groups) to role mappings. Only NetSqlAzMan allows users to Task mappings.
After looking at a few samples ... the object model of NetSqlAzMan is very clean.
=======================================================
Ms Authorization Manager (AzMan) vs .NET Sql Authorization Manager
(NetSqlAzMan)
As pointed out before, an analogous Microsoft product already exists
and is called Authorization Manager (AzMan); AzMan is present, by
default, in Windows Server 2003 and, through the Admin Pack setup, in
Windows XP.
The important difference between AzMan and NetSqlAzMan is that the
first is Role-based, that is, based on the belonging - Role concept
and the operations container in each role, while the second is
Item-based (or if you prefer Operation-based), that is users or users
group or group of groups that can or cannot belong to Roles or execute
such Task and/or Operations (Items).
Here the most important features and differences between the two
products:
Ms AzMan:
* It's COM.
* It's equipped by a MMC 2.0 (COM) console.
* Its storage can be an XML file or ADAM (Active Directory Application Mode - e un LDAP).
* It's role-based.
* It supports static/dynamic applicative groups, members/not-members.
* Structure based on Roles -> Tasks -> Operations. (Hierarchical Roles and Tasks , none Operations).
* Authorizations can be added only to Roles.
* It doesn't implement the "delegate" concept.
* It doesn't manage authorizations "in the time".
* It doesn't trigger events.
* The only type of authorization is "Allow".
(to "deny" it needs to remove the user/group from his Role).
* It supports Scripting / Biz rules.
* It supports Active Directory users/groups and ADAM users.
NetSqlAzMan:
* It's .NET 2.0.
* It's equipped by a MMC 3.0 (.NET) console.
* Its storage is a Sql Server database(2000/MSDE/2005/Express).
* It's based on Tdo - Typed Data Object technology.
* It's Item-based.
* Structure based on Roles -> Tasks -> Operations. (all hierarchical ones).
* Authorizations can be added to Roles, Task and Operations.
* It supports static/dynamic applicative groups, members/not-members.
* LDAP query testing directly from console.
* It's time-dependant.
* It's delegate-compliant.
* It triggers events (ENS).
* It supports 4 authorization types:
o Allow with delegation (authorized and authorized to delegate).
o Allow (authorized).
o Deny (not authorized).
o Neutral (neutral permission, it depends on higher level Item permission).
* Hierarchical authorizations.
* It supports Scripting / Biz rules (compiled in .NET - C# - VB - and not interpreted)
* It supports Active Directory users/groups and custom users defined in SQL Server Database.
Here's another gotcha.
Azman sample code:
http://channel9.msdn.com/forums/sandbox/252978-AzMan-in-the-Enterprise-Sample-Code
http://channel9.msdn.com/forums/sandbox/252973-Programming-AzMan-Sample-Code
using System;
using System.Security.Principal;
using System.Runtime.InteropServices;
using AZROLESLib;
namespace TreyResearch {
public class AzManHelper : IDisposable {
AzAuthorizationStore store;
IAzApplication app;
string appName;
public AzManHelper(string connectionString, string appName) {
this.appName = appName;
try {
// load and initialize the AzMan runtime
store = new AzAuthorizationStore();
store.Initialize(0, connectionString, null);
// drill down to our application
app = store.OpenApplication(appName, null);
}
catch (COMException x) {
throw new AzManException("Failed to initizlize AzManHelper", x);
}
catch (System.IO.FileNotFoundException x) {
throw new AzManException(string.Format("Failed to load AzMan policy from {0} - make sure your connection string is correct.", connectionString), x);
}
}
public void Dispose() {
if (null == app) return;
Marshal.ReleaseComObject(app);
Marshal.ReleaseComObject(store);
app = null;
store = null;
}
public bool AccessCheck(string audit, Operations op,
WindowsIdentity clientIdentity) {
try {
// first step is to create an AzMan context for the client
// this looks at the security identifiers (SIDs) in the user's
// access token and maps them onto AzMan roles, tasks, and operations
IAzClientContext ctx = app.InitializeClientContextFromToken(
(ulong)clientIdentity.Token.ToInt64(), null);
// next step is to see if this user is authorized for
// the requested operation. Note that AccessCheck allows
// you to check multiple operations at once if you desire
object[] scopes = { "" };
object[] operations = { (int)op };
object[] results = (object[])ctx.AccessCheck(audit, scopes, operations,
null, null, null, null, null);
int result = (int)results[0];
return 0 == result;
}
catch (COMException x) {
throw new AzManException("AccessCheck failed", x);
}
}
public bool AccessCheckWithArg(string audit, Operations op,
WindowsIdentity clientIdentity,
string argName, object argValue) {
try {
// first step is to create an AzMan context for the client
// this looks at the security identifiers (SIDs) in the user's
// access token and maps them onto AzMan roles, tasks, and operations
IAzClientContext ctx = app.InitializeClientContextFromToken(
(ulong)clientIdentity.Token.ToInt64(), null);
// next step is to see if this user is authorized for
// the requested operation. Note that AccessCheck allows
// you to check multiple operations at once if you desire
object[] scopes = { "" };
object[] operations = { (int)op };
object[] argNames = { argName };
object[] argValues = { argValue };
object[] results = (object[])ctx.AccessCheck(audit, scopes, operations,
argNames, argValues,
null, null, null);
int result = (int)results[0];
return 0 == result;
}
catch (COMException x) {
throw new AzManException("AccessCheckWithArg failed", x);
}
}
// use this to update a running app
// after you change the AzMan policy
public void UpdateCache() {
try {
store.UpdateCache(null);
Marshal.ReleaseComObject(app);
app = store.OpenApplication(appName, null);
}
catch (COMException x) {
throw new AzManException("UpdateCache failed", x);
}
}
}
public class AzManException : Exception {
public AzManException(string message, Exception innerException)
: base(message, innerException)
{}
}
}
That is Azman helper code. That is ugly COM/Interopish stuff. :<
Now check the NetSqlAzMan code samples:
http://netsqlazman.codeplex.com/wikipage?title=Samples
/// <summary>
/// Create a Full Storage through .NET code
/// </summary>
private void CreateFullStorage()
{
// USER MUST BE A MEMBER OF SQL DATABASE ROLE: NetSqlAzMan_Administrators
//Sql Storage connection string
string sqlConnectionString = "data source=(local);initial catalog=NetSqlAzManStorage;user id=netsqlazmanuser;password=password";
//Create an instance of SqlAzManStorage class
IAzManStorage storage = new SqlAzManStorage(sqlConnectionString);
//Open Storage Connection
storage.OpenConnection();
//Begin a new Transaction
storage.BeginTransaction(AzManIsolationLevel.ReadUncommitted);
//Create a new Store
IAzManStore newStore = storage.CreateStore("My Store", "Store description");
//Create a new Basic StoreGroup
IAzManStoreGroup newStoreGroup = newStore.CreateStoreGroup(SqlAzManSID.NewSqlAzManSid(), "My Store Group", "Store Group Description", String.Empty, GroupType.Basic);
//Retrieve current user SID
IAzManSid mySid = new SqlAzManSID(WindowsIdentity.GetCurrent().User);
//Add myself as sid of "My Store Group"
IAzManStoreGroupMember storeGroupMember = newStoreGroup.CreateStoreGroupMember(mySid, WhereDefined.Local, true);
//Create a new Application
IAzManApplication newApp = newStore.CreateApplication("New Application", "Application description");
//Create a new Role
IAzManItem newRole = newApp.CreateItem("New Role", "Role description", ItemType.Role);
//Create a new Task
IAzManItem newTask = newApp.CreateItem("New Task", "Task description", ItemType.Task);
//Create a new Operation
IAzManItem newOp = newApp.CreateItem("New Operation", "Operation description", ItemType.Operation);
//Add "New Operation" as a sid of "New Task"
newTask.AddMember(newOp);
//Add "New Task" as a sid of "New Role"
newRole.AddMember(newTask);
//Create an authorization for myself on "New Role"
IAzManAuthorization auth = newRole.CreateAuthorization(mySid, WhereDefined.Local, mySid, WhereDefined.Local, AuthorizationType.AllowWithDelegation, null, null);
//Create a custom attribute
IAzManAttribute<IAzManAuthorization> attr = auth.CreateAttribute("New Key", "New Value");
//Create an authorization for DB User "Andrea" on "New Role"
IAzManAuthorization auth2 = newRole.CreateAuthorization(mySid, WhereDefined.Local, storage.GetDBUser("Andrea").CustomSid, WhereDefined.Local, AuthorizationType.AllowWithDelegation, null, null);
//Commit transaction
storage.CommitTransaction();
//Close connection
storage.CloseConnection();
}
That tells a story in and of itself.
I think the reason for the lack of updates from Microsoft on their blogs and in their SDKs has something to do with them already moving all their tools and designs towards a social network/federation friendly "claims model":
http://msdn.microsoft.com/en-us/magazine/ee335707.aspx
In comparison to any of the AzMan variants, at the low AzMan operation level (what the code demands to decouple it from the rest) we only have a permission type claim. This new style of operation is simply a URN string/action name issued from any trusted claims provider/service validated by signatures you (or later re-configuration) define. They are then just a flat list of roles in the user identity so easy to check with common IsInRole methods.
The justification for this is clear. Modern internet solutions (and perhaps some future corporate intranet applications once the privacy laws are improved) demand multi-domain authentication and authorization, e.g. this StackOverflow.com user account and the connected Facebook account or any OpenID account you may have linked.
So for authorization you can now CODE rules which map between external claims and internal "permission claims" (analogous to AzMan operations). However there is no standard format, hierarchy or administration tool.
Perhaps a hybrid solution of Claims Service (Authentication) + AzMan XML/SQL (Roles to Claims mapping) + Claims Permission demand is the way forwards. All the samples I found so far just have code in the middle. I want to see something with recursive group memberships from Active Directory resolved to Roles to Tasks to claims (operations) like we already have with AzMan.
More investigation is necessary to achieve the "good old" but still essential "role based security" pattern with the newer technology...
If you're looking to start, head towards the Microsoft Windows Identity Foundation (WIF) which first appeared in .NET 3.5.1 but has since been integrated into the .NET 4.5 framework.
http://msdn.microsoft.com/en-us/library/hh377151(v=vs.110).aspx