//----------------------------------------------------------------------- // // Copyright (C) 2011 Microsoft Corporation // //----------------------------------------------------------------------- namespace Microsoft.Samples.Management.OData.RoleBasedPlugins { using System; using System.Collections.Generic; using System.Management.Automation.Remoting; using System.Security.Principal; /// /// Role Based management system implementation /// internal class RbacSystem { /// static instance of RbacSystem private static RbacSystem current = null; /// Lock to modify the static instance of RbacSystem private static object syncObject = new object(); /// /// Prevents a default instance of the RbacSystem class from being created. /// private RbacSystem() { this.Users = new List(); this.Groups = new List(); this.Populate(Utils.GetRbacFilePath()); } /// Gets singleton instance of the RbacSystem class public static RbacSystem Current { get { if (RbacSystem.current == null) { lock (RbacSystem.syncObject) { if (RbacSystem.current == null) { RbacSystem.current = new RbacSystem(); } } } return RbacSystem.current; } } /// Gets collection of users registered in the system public List Users { get; private set; } /// Gets collection of groups present in the system public List Groups { get; private set; } /// /// Authorizes a user /// For authorized users, it returns the WindowsIdentity in which context commands need to be executed /// /// User information /// User quota value /// WindowsIdentiy in which context commands need to be executed public WindowsIdentity AuthorizeUser(RbacUser.RbacUserInfo userInfo, out Microsoft.Management.Odata.UserQuota quota) { RbacUser user = this.FindUser(userInfo); quota = new Microsoft.Management.Odata.UserQuota(user.Quota.MaxConcurrentRequests, user.Quota.MaxRequestsPerTimeSlot, user.Quota.Timeslot); return user.Group.GetWindowsIdentity(userInfo.WindowsIdentity); } /// /// Gets management system execution state membershipId for a user /// /// User information /// Managment system execution state membershipId public string GetMembershipId(RbacUser.RbacUserInfo userInfo) { return this.FindUser(userInfo).GetMembershipId(); } /// /// Gets collection of cmdlets for a user /// /// User information /// Collection of cmdlet names public List GetCmdlets(PSPrincipal userInfo) { RbacGroup group = this.FindGroup(userInfo); return new List(group.Cmdlets); } /// /// Gets collection of scripts for a user /// /// User information /// Collection of scripts public List GetScripts(PSPrincipal userInfo) { RbacGroup group = this.FindGroup(userInfo); return new List(group.Scripts); } /// /// Gets collection of modules for a user /// /// User information /// Collection of module names public List GetModules(PSPrincipal userInfo) { RbacGroup group = this.FindGroup(userInfo); return new List(group.Modules); } /// /// Populates the RbacSystem from an RBAC configuration file /// /// full path to the config file private void Populate(string configPath) { this.Reset(); XmlConfiguration rbacConfiguration = XmlConfiguration.Create(configPath); foreach (XmlGroup group in rbacConfiguration.Groups) { WindowsIdentity identity = null; try { if (group.UserName == null || group.Password == null) { if (group.UserName != null || group.Password != null) { if (group.UserName == null) { throw new ArgumentException("User name is null for group " + group.Name); } if (group.Password == null) { throw new ArgumentException("Password is null for group " + group.Name); } } } else { if (group.DomainName == null) { group.DomainName = Environment.MachineName; } identity = WindowsIdentityHelper.GetWindowsIdentity(group.UserName, group.Password, group.DomainName); } } catch (Exception) { // Not able to get the impersonated WindowsIdentity // use the current WindowsIdentity identity = WindowsIdentity.GetCurrent(); } this.Groups.Add(new RbacGroup(group)); } foreach (XmlUser userConfig in rbacConfiguration.Users) { RbacUser user = new RbacUser(new RbacUser.RbacUserInfo(userConfig.Name, userConfig.AuthenticationType, userConfig.DomainName), userConfig.Quota); RbacGroup group = this.Groups.Find(item => item.Name == userConfig.GroupName); if (group == null) { throw new ArgumentException("Group not found = " + userConfig.GroupName); } user.Group = group; this.Users.Add(user); } } /// /// restores all collections to default/empty values /// private void Reset() { this.Users.Clear(); this.Groups.Clear(); } /// /// Finds group for a PSPrincipal /// /// PSPrincipal instance /// Group associated with the identity private RbacGroup FindGroup(PSPrincipal principal) { if (principal == null) { throw new ArgumentNullException("principal"); } if (principal.Identity == null) { throw new ArgumentException("Null identity passed"); } if (principal.Identity.IsAuthenticated == false) { throw new UnauthorizedAccessException(); } PSIdentity powerShellIdentity = principal.Identity; GenericIdentity identity = new GenericIdentity(powerShellIdentity.Name, powerShellIdentity.AuthenticationType); RbacUser.RbacUserInfo userInfo = new RbacUser.RbacUserInfo(identity, powerShellIdentity.CertificateDetails); RbacUser user = this.Users.Find(item => item.UserInfo.Equals(userInfo)); if (user == null) { throw new ArgumentException("User not found: name=" + userInfo.Name + ", authentication=" + userInfo.AuthenticationType); } RbacGroup group = this.Groups.Find(item => item.Name == user.Group.Name); if (group == null) { throw new ArgumentException("group not found = " + user.Group.Name); } return group; } /// /// Finds a user in the RbacSytem /// /// User information /// User from RbacSystem which was searched private RbacUser FindUser(RbacUser.RbacUserInfo userInfo) { RbacUser user = this.Users.Find(item => item.UserInfo.Equals(userInfo)); if (user == null) { throw new ArgumentException("User not found. Name = " + userInfo.Name + " Authentication Type = " + userInfo.AuthenticationType); } return user; } } }