Alpha 191119 / AssignedRoles test

master
Harald Wolff 2019-11-19 11:37:33 +01:00
parent 897a774e77
commit 5a7540a2b5
11 changed files with 343 additions and 29 deletions

33
AssignedRole.cs 100644
View File

@ -0,0 +1,33 @@
using System;
namespace ln.identities
{
public class AssignedRole
{
IIdentityProvider identityProvider;
public IIdentityProvider IdentityProvider => identityProvider;
readonly Guid identityUniqueID;
public Identity Identity => IdentityProvider.GetIdentity(identityUniqueID);
public Role Role { get; set; }
protected AssignedRole(IIdentityProvider identityProvider)
{
this.identityProvider = identityProvider;
}
public AssignedRole(IIdentityProvider identityProvider, Identity identity) : this(identityProvider, identity, 0) { }
public AssignedRole(IIdentityProvider identityProvider,Identity identity,Role role) :this(identityProvider)
{
identityUniqueID = identity.UniqueID;
Role = role;
}
public override string ToString() => String.Format("[AssignedRole Identity={0} Role={1}]",Identity.IdentityName,Role);
public override int GetHashCode() => identityUniqueID.GetHashCode();
public override bool Equals(object obj) => (obj is AssignedRole you) && (identityUniqueID.Equals(you.identityUniqueID));
}
}

37
AssignedRoles.cs 100644
View File

@ -0,0 +1,37 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace ln.identities
{
public class AssignedRoles : IEnumerable<AssignedRole>
{
IIdentityProvider identityProvider;
public IIdentityProvider IdentityProvider => identityProvider;
Dictionary<Guid, AssignedRole> assignedRoles = new Dictionary<Guid, AssignedRole>();
public AssignedRoles(IIdentityProvider identityProvider)
{
this.identityProvider = identityProvider;
}
public AssignedRole this[Identity identity]
{
get
{
if (!assignedRoles.ContainsKey(identity.UniqueID))
{
assignedRoles.Add(identity.UniqueID, new AssignedRole(identityProvider, identity));
}
return assignedRoles[identity.UniqueID];
}
}
public IEnumerator<AssignedRole> GetEnumerator()
{
return assignedRoles.Values.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
}

View File

@ -30,5 +30,44 @@ namespace ln.identities
public abstract bool Save(Identity identity);
public virtual Identity GetIdentity(string identityName) => GetIdentity(GetIdentities().FirstOrDefault((kvp) => identityName.Equals(kvp.Value)).Key);
public abstract IEnumerable<RoleAssignment> GetRoleAssignments(Identity identity);
public virtual AssignedRoles GetAssignedRoles(Identity identity)
{
AssignedRoles assignedRoles = new AssignedRoles(this);
GetAssignedRoles(identity, assignedRoles);
return assignedRoles;
}
public virtual void GetAssignedRoles(Identity identity,AssignedRoles assignedRoles)
{
assignedRoles[identity].Role |= Role.BE;
foreach (RoleAssignment roleAssignment in identity.RoleAssignments)
{
foreach (AssignedRole foreignRole in roleAssignment.EffectiveIdentity.AssignedRoles)
{
if (roleAssignment.Role.HasFlag(Role.IMPERSONATE) || foreignRole.Identity.Equals(roleAssignment.EffectiveIdentity))
{
AssignedRole currentRole = assignedRoles[foreignRole.Identity];
currentRole.Role |= (foreignRole.Role & roleAssignment.Role);
}
}
}
}
}
}

View File

@ -14,5 +14,8 @@ namespace ln.identities
bool Save(Identity identity);
Identity Authenticate(AuthenticationProve authenticationProve);
AssignedRoles GetAssignedRoles(Identity identity);
IEnumerable<RoleAssignment> GetRoleAssignments(Identity identity);
}
}

View File

@ -6,24 +6,37 @@ namespace ln.identities
{
public class Identity
{
public Guid UniqueID { get; private set; }
private IIdentityProvider identityProvider;
public IIdentityProvider IdentityProvider => identityProvider;
public Guid UniqueID { get; private set; }
public String IdentityName { get; set; }
List<SecureAttribute> secureAttributes = new List<SecureAttribute>();
List<RoleAssignment> roleAssignments = new List<RoleAssignment>();
AssignedRoles assignedRoles;
private Identity()
List<RoleAssignment> cachedRoleAssignments;
private Identity(IIdentityProvider identityProvider)
{
this.identityProvider = identityProvider;
}
private Identity(Guid uniqueID,string identityName)
private Identity(IIdentityProvider identityProvider,Guid uniqueID,string identityName)
:this(identityProvider)
{
UniqueID = uniqueID;
IdentityName = identityName;
}
public Identity(string identityName) : this(Guid.NewGuid(),identityName){}
public Identity(IIdentityProvider identityProvider,string identityName) : this(identityProvider,Guid.NewGuid(),identityName){}
public void ResetCaches()
{
cachedRoleAssignments = null;
}
public SecureAttribute GetSecureAttribute(Guid uniqueID)
{
@ -54,8 +67,33 @@ namespace ln.identities
public void AddSecureAttribute(SecureAttribute secureAttribute) => secureAttributes.Add(secureAttribute);
public void RemoveSecureAttribute(SecureAttribute secureAttribute) => secureAttributes.Remove(secureAttribute);
public void ClearAssignedRolesCache() => assignedRoles = null;
public AssignedRoles AssignedRoles
{
get {
if (assignedRoles == null)
{
assignedRoles = IdentityProvider.GetAssignedRoles(this);
}
return assignedRoles;
}
}
public IEnumerable<RoleAssignment> RoleAssignments
{
get
{
if (cachedRoleAssignments == null)
{
cachedRoleAssignments = new List<RoleAssignment>(IdentityProvider.GetRoleAssignments(this));
}
return cachedRoleAssignments;
}
}
public override bool Equals(object obj) => (obj is Identity other) && other.UniqueID.Equals(UniqueID);
public override int GetHashCode() => UniqueID.GetHashCode();
public override string ToString() => String.Format("[Identity UniqueID={0} IdentityName={1}]",UniqueID,IdentityName);
}
}

View File

@ -6,6 +6,8 @@ using System.Linq;
using ln.types.btree;
using ln.types.collections;
using System.Security.Principal;
using ln.types.odb.ng.mappings;
using System.Reflection;
namespace ln.identities
{
public class ODBIdentityProvider : BaseIdentityProvider
@ -20,6 +22,13 @@ namespace ln.identities
StorageContainer = storageContainer;
mapper = new Mapper(storageContainer);
ClassMapping identityClassMapping = new ClassMapping(
typeof(Identity),
(Mapper arg1, Document arg2) => new Identity(this,""),
(fieldInfo) => !fieldInfo.Name.Equals("identityProvider")
);
mapper.RegisterMapping(identityClassMapping.MappedType,identityClassMapping);
mapper.EnsureIndex<Identity>("UniqueID");
mapper.EnsureIndex<Identity>("IdentityName");
}
@ -54,7 +63,7 @@ namespace ln.identities
public override Identity CreateIdentity(string identityName)
{
Identity identity = new Identity(identityName);
Identity identity = new Identity(this,identityName);
identityCache.Add(identity.UniqueID, identity);
return identity;
}
@ -74,5 +83,9 @@ namespace ln.identities
return true;
}
public override IEnumerable<RoleAssignment> GetRoleAssignments(Identity identity)
{
throw new NotImplementedException();
}
}
}

58
Role.cs
View File

@ -1,27 +1,51 @@
using System;
namespace ln.identities
{
public class Role
[Flags]
public enum Role : int
{
public static readonly Role SuperUser = new Role(Guid.Parse("{eefca5e2-2295-44d5-9b24-000000000000}"),"SuperUser");
public static readonly Role Owner = new Role(Guid.Parse("{eefca5e2-2295-44d5-9b24-000000000001}"), "Owner");
public static readonly Role Editor = new Role(Guid.Parse("{eefca5e2-2295-44d5-9b24-000000000002}"), "Editor");
/* Bits 0..15: Rolleneigenschaften */
VIEW = (1<<0), // Authentifizierte Identität darf die effektive Identität und ihre Eigenschaften sehen
USE = VIEW | (1 << 1), // Authentifizierte Identität darf die effektive Identität nutzen (z.B. Dateien einer Webpräsenz pflegen)
CONTROL = VIEW | (1<<2), // Authentifizierte Identität darf die effektive Identität steuern (z.B. einen Dienst starten / stoppen)
MANAGE = VIEW | CONTROL | (1<<3), // Authentifizierte Identität darf die Eigenschaften der effektiven Identität verändern ("Konfiguration")
public Guid UniqueID { get; }
public String Name { get; set; }
ADMIN = 0x0000FFFF,
/* Bits 16..23: */
MANAGEROLES = (1<<16),
private Role()
{}
/* Bits 24..31: Vererbung, Superuser */
IMPERSONATE = (1<<24), // FLAG: Identität erhält alle maskierten Rollen der effektiven Identität, welche direkt assoziiert sind
public Role(string roleName):this(Guid.NewGuid(),roleName){}
public Role(Guid uniqueID,string roleName)
{
UniqueID = uniqueID;
Name = roleName;
}
public override bool Equals(object obj) => (obj is Role other) && other.UniqueID.Equals(UniqueID);
public override int GetHashCode() => UniqueID.GetHashCode();
OWN = 0x0FFFFFFF,
BE = 0x0000FFFF,
SUPER = 0x7FFFFFFF, // SuperUser
}
//public class Role
//{
// public static readonly Role SuperUser = new Role(Guid.Parse("{eefca5e2-2295-44d5-9b24-000000000000}"),"SuperUser");
// public static readonly Role Owner = new Role(Guid.Parse("{eefca5e2-2295-44d5-9b24-000000000001}"), "Owner");
// public static readonly Role Editor = new Role(Guid.Parse("{eefca5e2-2295-44d5-9b24-000000000002}"), "Editor");
// public static readonly Role Reader = new Role(Guid.Parse("{eefca5e2-2295-44d5-9b24-000000000004}"), "Reader");
// public static readonly Role Writer = new Role(Guid.Parse("{eefca5e2-2295-44d5-9b24-000000000008}"), "Writer");
// public Guid UniqueID { get; }
// public String Name { get; set; }
// private Role()
// {}
// public Role(string roleName):this(Guid.NewGuid(),roleName){}
// public Role(Guid uniqueID,string roleName)
// {
// UniqueID = uniqueID;
// Name = roleName;
// }
// public override bool Equals(object obj) => (obj is Role other) && other.UniqueID.Equals(UniqueID);
// public override int GetHashCode() => UniqueID.GetHashCode();
//}
}

View File

@ -3,11 +3,44 @@ namespace ln.identities
{
public class RoleAssignment
{
public Identity EffectiveIdentity { get; }
public Role Role { get; }
IIdentityProvider identityProvider;
public IIdentityProvider IdentityProvider => identityProvider;
private RoleAssignment()
Guid identityUniqueID;
Guid effectiveIdentityUniqueID;
public Identity Identity => IdentityProvider.GetIdentity(identityUniqueID); // Identity this Role is assigned to
public Identity EffectiveIdentity => IdentityProvider.GetIdentity(effectiveIdentityUniqueID); // Identity for that this Role is valid
public Role Role { get; } // Role that is assigned
private RoleAssignment(IIdentityProvider identityProvider)
{
this.identityProvider = identityProvider;
}
public RoleAssignment(IIdentityProvider identityProvider,Identity identity,Identity effectiveIdentity,Role role)
:this(identityProvider)
{
identityUniqueID = identity.UniqueID;
effectiveIdentityUniqueID = effectiveIdentity.UniqueID;
Role = role;
}
public override int GetHashCode()
{
return EffectiveIdentity.GetHashCode() ^ Role.GetHashCode();
}
public override bool Equals(object obj)
{
return (obj is RoleAssignment you) &&
(identityUniqueID.Equals(you.identityUniqueID) && effectiveIdentityUniqueID.Equals(you.effectiveIdentityUniqueID) && Role.Equals(you.Role));
}
public override string ToString()
{
return string.Format("[RoleAssigment Identity={0} EffectiveIdentity={1} Role={2}]",Identity.IdentityName,EffectiveIdentity.IdentityName,Role);
}
}
}

View File

@ -28,15 +28,12 @@ namespace ln.identities
using (SHA256 sha256 = SHA256.Create())
{
byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
Console.WriteLine("PasswordBytes={0}", passwordBytes.ToHexString());
Console.WriteLine("Seed={0}", Seed.ToHexString());
sha256.TransformBlock(Seed, 0, Seed.Length, null, 0);
sha256.TransformBlock(passwordBytes, 0, passwordBytes.Length, null, 0);
sha256.TransformFinalBlock(Seed, 0, Seed.Length);
secretBytes = sha256.Hash;
Console.WriteLine("SecretBytes={0}", secretBytes.ToHexString());
}
}

View File

@ -28,6 +28,9 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="nunit.framework">
<Package>nunit</Package>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
@ -42,6 +45,9 @@
<Compile Include="AuthenticationRequest.cs" />
<Compile Include="AuthenticationChallenges.cs" />
<Compile Include="BaseIdentityProvider.cs" />
<Compile Include="test\IdentityTests.cs" />
<Compile Include="AssignedRole.cs" />
<Compile Include="AssignedRoles.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ln.types\ln.types.csproj">
@ -49,5 +55,8 @@
<Name>ln.types</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Folder Include="test\" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -0,0 +1,88 @@
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
namespace ln.identities.test
{
public class TestIdentityProvider : BaseIdentityProvider
{
List<Identity> identities = new List<Identity>();
List<RoleAssignment> roleAssignments = new List<RoleAssignment>();
public TestIdentityProvider()
{
}
public override Identity CreateIdentity(string identityName)
{
Identity identity = new Identity(this, identityName);
identities.Add(identity);
return identity;
}
public override IEnumerable<KeyValuePair<Guid, string>> GetIdentities() => identities.Select((Identity arg) => new KeyValuePair<Guid, string>(arg.UniqueID, arg.IdentityName));
public override Identity GetIdentity(Guid uniqueID)
{
foreach (Identity identity in identities)
if (identity.UniqueID.Equals(uniqueID))
return identity;
throw new KeyNotFoundException();
}
public override IEnumerable<RoleAssignment> GetRoleAssignments(Identity identity) => roleAssignments.Where((RoleAssignment arg) => arg.Identity.Equals(identity));
public override bool Save(Identity identity)
{
throw new NotImplementedException();
}
public void AddRoleAssignment(RoleAssignment roleAssignment) => roleAssignments.Add(roleAssignment);
}
[TestFixture()]
public class IdentityTests
{
[Test()]
public void TestCase()
{
TestIdentityProvider identityProvider = new TestIdentityProvider();
Identity idService = identityProvider.CreateIdentity("Service");
Identity idOrg = identityProvider.CreateIdentity("Organization");
Identity idManager = identityProvider.CreateIdentity("Manager");
Identity idEmpA = identityProvider.CreateIdentity("EmployeeA");
Identity idEmpB = identityProvider.CreateIdentity("EmployeeB");
Identity idEmpC = identityProvider.CreateIdentity("EmployeeC");
Identity idEmpD = identityProvider.CreateIdentity("EmployeeD");
identityProvider.AddRoleAssignment(new RoleAssignment(identityProvider,idOrg,idService,Role.OWN));
identityProvider.AddRoleAssignment(new RoleAssignment(identityProvider, idManager, idOrg, Role.OWN));
identityProvider.AddRoleAssignment(new RoleAssignment(identityProvider, idEmpA, idOrg, Role.IMPERSONATE | Role.CONTROL));
identityProvider.AddRoleAssignment(new RoleAssignment(identityProvider, idEmpB, idEmpA, Role.IMPERSONATE | Role.ADMIN));
identityProvider.AddRoleAssignment(new RoleAssignment(identityProvider, idEmpC, idOrg, Role.IMPERSONATE | Role.CONTROL));
identityProvider.AddRoleAssignment(new RoleAssignment(identityProvider, idEmpD, idEmpC, Role.ADMIN));
DumpRoleAssigments(idService);
DumpRoleAssigments(idOrg);
DumpRoleAssigments(idManager);
DumpRoleAssigments(idEmpA);
DumpRoleAssigments(idEmpB);
DumpRoleAssigments(idEmpC);
DumpRoleAssigments(idEmpD);
}
public void DumpRoleAssigments(Identity identity)
{
Console.WriteLine("Identity: {0}", identity.IdentityName);
foreach (RoleAssignment roleAssignment in identity.RoleAssignments)
{
Console.WriteLine(" {0}", roleAssignment);
}
foreach (AssignedRole assignedRole in identity.AssignedRoles)
{
Console.WriteLine(" {0}", assignedRole);
}
}
}
}