//-----------------------------------------------------------------------
//
// 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;
}
}
}