2025-11-28 00:35:46 +09:00

253 lines
9.2 KiB
C#

//-----------------------------------------------------------------------
// <copyright file="RbacSystem.cs" company="Microsoft Corporation">
// Copyright (C) 2011 Microsoft Corporation
// </copyright>
//-----------------------------------------------------------------------
namespace Microsoft.Samples.Management.OData.RoleBasedPlugins
{
using System;
using System.Collections.Generic;
using System.Management.Automation.Remoting;
using System.Security.Principal;
/// <summary>
/// Role Based management system implementation
/// </summary>
internal class RbacSystem
{
/// <summary> static instance of RbacSystem </summary>
private static RbacSystem current = null;
/// <summary> Lock to modify the static instance of RbacSystem </summary>
private static object syncObject = new object();
/// <summary>
/// Prevents a default instance of the RbacSystem class from being created.
/// </summary>
private RbacSystem()
{
this.Users = new List<RbacUser>();
this.Groups = new List<RbacGroup>();
this.Populate(Utils.GetRbacFilePath());
}
/// <summary> Gets singleton instance of the RbacSystem class</summary>
public static RbacSystem Current
{
get
{
if (RbacSystem.current == null)
{
lock (RbacSystem.syncObject)
{
if (RbacSystem.current == null)
{
RbacSystem.current = new RbacSystem();
}
}
}
return RbacSystem.current;
}
}
/// <summary> Gets collection of users registered in the system </summary>
public List<RbacUser> Users { get; private set; }
/// <summary> Gets collection of groups present in the system </summary>
public List<RbacGroup> Groups { get; private set; }
/// <summary>
/// Authorizes a user
/// For authorized users, it returns the WindowsIdentity in which context commands need to be executed
/// </summary>
/// <param name="userInfo">User information</param>
/// <param name="quota">User quota value</param>
/// <returns>WindowsIdentiy in which context commands need to be executed</returns>
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);
}
/// <summary>
/// Gets management system execution state membershipId for a user
/// </summary>
/// <param name="userInfo">User information</param>
/// <returns>Managment system execution state membershipId</returns>
public string GetMembershipId(RbacUser.RbacUserInfo userInfo)
{
return this.FindUser(userInfo).GetMembershipId();
}
/// <summary>
/// Gets collection of cmdlets for a user
/// </summary>
/// <param name="userInfo">User information</param>
/// <returns>Collection of cmdlet names </returns>
public List<string> GetCmdlets(PSPrincipal userInfo)
{
RbacGroup group = this.FindGroup(userInfo);
return new List<string>(group.Cmdlets);
}
/// <summary>
/// Gets collection of scripts for a user
/// </summary>
/// <param name="userInfo">User information</param>
/// <returns>Collection of scripts</returns>
public List<string> GetScripts(PSPrincipal userInfo)
{
RbacGroup group = this.FindGroup(userInfo);
return new List<string>(group.Scripts);
}
/// <summary>
/// Gets collection of modules for a user
/// </summary>
/// <param name="userInfo">User information </param>
/// <returns>Collection of module names</returns>
public List<string> GetModules(PSPrincipal userInfo)
{
RbacGroup group = this.FindGroup(userInfo);
return new List<string>(group.Modules);
}
/// <summary>
/// Populates the RbacSystem from an RBAC configuration file
/// </summary>
/// <param name="configPath">full path to the config file</param>
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);
}
}
/// <summary>
/// restores all collections to default/empty values
/// </summary>
private void Reset()
{
this.Users.Clear();
this.Groups.Clear();
}
/// <summary>
/// Finds group for a PSPrincipal
/// </summary>
/// <param name="principal">PSPrincipal instance</param>
/// <returns>Group associated with the identity</returns>
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;
}
/// <summary>
/// Finds a user in the RbacSytem
/// </summary>
/// <param name="userInfo">User information</param>
/// <returns>User from RbacSystem which was searched</returns>
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;
}
}
}